3 changed files with 120 additions and 17 deletions
@ -0,0 +1,90 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2016 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.web.reactive.socket.client; |
||||||
|
|
||||||
|
import java.net.URI; |
||||||
|
import java.util.concurrent.atomic.AtomicReference; |
||||||
|
import java.util.function.Consumer; |
||||||
|
|
||||||
|
import io.netty.buffer.ByteBufAllocator; |
||||||
|
import reactor.core.publisher.Mono; |
||||||
|
import reactor.ipc.netty.NettyOutbound; |
||||||
|
import reactor.ipc.netty.http.client.HttpClient; |
||||||
|
import reactor.ipc.netty.http.client.HttpClientOptions; |
||||||
|
import reactor.ipc.netty.http.client.HttpClientRequest; |
||||||
|
|
||||||
|
import org.springframework.core.io.buffer.NettyDataBufferFactory; |
||||||
|
import org.springframework.http.HttpHeaders; |
||||||
|
import org.springframework.web.reactive.socket.HandshakeInfo; |
||||||
|
import org.springframework.web.reactive.socket.WebSocketHandler; |
||||||
|
import org.springframework.web.reactive.socket.WebSocketSession; |
||||||
|
import org.springframework.web.reactive.socket.adapter.ReactorNettyWebSocketSession; |
||||||
|
|
||||||
|
/** |
||||||
|
* A {@link WebSocketClient} based on Reactor Netty. |
||||||
|
* |
||||||
|
* @author Rossen Stoyanchev |
||||||
|
* @since 5.0 |
||||||
|
*/ |
||||||
|
public class ReactorNettyWebSocketClient implements WebSocketClient { |
||||||
|
|
||||||
|
private final HttpClient httpClient; |
||||||
|
|
||||||
|
|
||||||
|
public ReactorNettyWebSocketClient() { |
||||||
|
this.httpClient = HttpClient.create(); |
||||||
|
} |
||||||
|
|
||||||
|
public ReactorNettyWebSocketClient(Consumer<? super HttpClientOptions> clientOptions) { |
||||||
|
this.httpClient = HttpClient.create(clientOptions); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Mono<Void> execute(URI url, WebSocketHandler handler) { |
||||||
|
return execute(url, new HttpHeaders(), handler); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Mono<Void> execute(URI url, HttpHeaders headers, WebSocketHandler handler) { |
||||||
|
|
||||||
|
// We have to store the NettyOutbound fow now..
|
||||||
|
// The alternative HttpClientResponse#receiveWebSocket does not work at present
|
||||||
|
AtomicReference<NettyOutbound> outboundRef = new AtomicReference<>(); |
||||||
|
|
||||||
|
return this.httpClient |
||||||
|
.get(url.toString(), request -> { |
||||||
|
addHeaders(request, headers); |
||||||
|
NettyOutbound outbound = request.sendWebsocket(); |
||||||
|
outboundRef.set(outbound); |
||||||
|
return outbound; |
||||||
|
}) |
||||||
|
.then(inbound -> { |
||||||
|
ByteBufAllocator allocator = inbound.channel().alloc(); |
||||||
|
NettyDataBufferFactory factory = new NettyDataBufferFactory(allocator); |
||||||
|
NettyOutbound outbound = outboundRef.get(); |
||||||
|
HandshakeInfo info = new HandshakeInfo(url, headers, Mono.empty()); |
||||||
|
WebSocketSession session = new ReactorNettyWebSocketSession(inbound, outbound, info, factory); |
||||||
|
return handler.handle(session); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void addHeaders(HttpClientRequest request, HttpHeaders headers) { |
||||||
|
headers.entrySet().stream() |
||||||
|
.forEach(e -> request.requestHeaders().set(e.getKey(), e.getValue())); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue