private static Mono<Void> doSend(WebSocketSession session, Publisher<WebSocketMessage> output) { return session.send(output); // workaround for suspected RxNetty WebSocket client issue // https://github.com/ReactiveX/RxNetty/issues/560 // return session.send(Mono.delay(Duration.ofMillis(100)).thenMany(output)); }
@Override public Mono<Void> handle(WebSocketSession session) { // Use retain() for Reactor Netty return session.send(session.receive().doOnNext(WebSocketMessage::retain)); } }
@Override public Mono<Void> handle(WebSocketSession session) { String protocol = session.getHandshakeInfo().getSubProtocol(); WebSocketMessage message = session.textMessage(protocol != null ? protocol : "none"); return session.send(Mono.just(message)); } }
@Override public Mono<Void> handle(WebSocketSession proxySession) { // Use retain() for Reactor Netty Mono<Void> proxySessionSend = proxySession .send(session.receive().doOnNext(WebSocketMessage::retain)); // .log("proxySessionSend", Level.FINE); Mono<Void> serverSessionSend = session .send(proxySession.receive().doOnNext(WebSocketMessage::retain)); // .log("sessionSend", Level.FINE); return Mono.zip(proxySessionSend, serverSessionSend).then(); }
@Override public Mono<Void> handle(WebSocketSession session) { HttpHeaders headers = session.getHandshakeInfo().getHeaders(); String payload = "my-header:" + headers.getFirst("my-header"); WebSocketMessage message = session.textMessage(payload); return session.send(Mono.just(message)); } }
@Override public Mono<Void> handle(WebSocketSession session) { return session.send(Flux .error(new Throwable()) .onErrorResume(ex -> session.close(CloseStatus.GOING_AWAY)) // SPR-17306 (nested close) .cast(WebSocketMessage.class)); } }
@Override public Mono<Void> handle(WebSocketSession session) { // Use retain() for Reactor Netty return session.send(session.receive().doOnNext(WebSocketMessage::retain)); } }
@Test public void echo() throws Exception { int count = 100; Flux<String> input = Flux.range(1, count).map(index -> "msg-" + index); ReplayProcessor<Object> output = ReplayProcessor.create(count); this.client.execute(getUrl("/echo"), session -> session .send(input.map(session::textMessage)) .thenMany(session.receive().take(count).map(WebSocketMessage::getPayloadAsText)) .subscribeWith(output) .then()) .block(TIMEOUT); assertEquals(input.collectList().block(TIMEOUT), output.collectList().block(TIMEOUT)); }
@Test public void echo() throws Exception { int count = 100; Flux<String> input = Flux.range(1, count).map(index -> "msg-" + index); ReplayProcessor<Object> output = ReplayProcessor.create(count); client.execute(getUrl("/echo"), session -> { logger.debug("Starting to send messages"); return session .send(input.doOnNext(s -> logger.debug("outbound " + s)).map(s -> session.textMessage(s))) .thenMany(session.receive().take(count).map(WebSocketMessage::getPayloadAsText)) .subscribeWith(output) .doOnNext(s -> logger.debug("inbound " + s)) .then() .doOnSuccessOrError((aVoid, ex) -> logger.debug("Done with " + (ex != null ? ex.getMessage() : "success"))); }) .block(Duration.ofMillis(5000)); assertEquals(input.collectList().block(Duration.ofMillis(5000)), output.collectList().block(Duration.ofMillis(5000))); }
@Test public void echoForHttp() throws Exception { int count = 100; Flux<String> input = Flux.range(1, count).map(index -> "msg-" + index); ReplayProcessor<Object> output = ReplayProcessor.create(count); client.execute(getHttpUrl("/echoForHttp"), session -> { logger.debug("Starting to send messages"); return session .send(input.doOnNext(s -> logger.debug("outbound " + s)).map(s -> session.textMessage(s))) .thenMany(session.receive().take(count).map(WebSocketMessage::getPayloadAsText)) .subscribeWith(output) .doOnNext(s -> logger.debug("inbound " + s)) .then() .doOnSuccessOrError((aVoid, ex) -> logger.debug("Done with " + (ex != null ? ex.getMessage() : "success"))); }) .block(Duration.ofMillis(5000)); assertEquals(input.collectList().block(Duration.ofMillis(5000)), output.collectList().block(Duration.ofMillis(5000))); }
private Mono<Void> doSend(WebSocketSession session, Publisher<WebSocketMessage> output) { return session.send(Mono.delay(Duration.ofMillis(100)).thenMany(output)); }
@Override public Mono<Void> handle(WebSocketSession session) { // Use retain() for Reactor Netty return session.send(session.receive().doOnNext(WebSocketMessage::retain)); } }
@Override public Mono<Void> handle(WebSocketSession session) { return session.send(session.receive() .doOnNext(WebSocketMessage::retain) .delayElements(Duration.ofSeconds(1)).log()); } }
@Override public Mono<Void> handle(WebSocketSession session) { session.receive().doFinally(sig -> { Long wampSessionId = this.webSocketId2WampSessionId.get(session.getId()); if (wampSessionId != null) { this.applicationEventPublisher.publishEvent( new WampDisconnectEvent(wampSessionId, session.getId(), session.getHandshakeInfo().getPrincipal().block())); this.webSocketId2WampSessionId.remove(session.getId()); } session.close(); // ? }).subscribe(inMsg -> { handleIncomingMessage(inMsg, session); }); Publisher<Message<Object>> publisher = MessageChannelReactiveUtils .toPublisher(this.clientOutboundChannel); return session.send(Flux.from(publisher) .filter(msg -> resolveSessionId(msg).equals(session.getId())) .map(msg -> handleOutgoingMessage(msg, session))); }