/** * Send data to the peer, listen for any error on write and close on terminal signal * (complete|error). <p>A new {@link NettyOutbound} type (or the same) for typed send * sequences. An implementor can therefore specialize the Outbound after a first after * a prepending data publisher. * Note: Nesting any send* method is not supported. * * @param dataStream the dataStream publishing OUT items to write on this channel * * @return A new {@link NettyOutbound} to append further send. It will emit a complete * signal successful sequence write (e.g. after "flush") or any error during write. */ default NettyOutbound send(Publisher<? extends ByteBuf> dataStream) { return sendObject(dataStream); }
/** * Immediately call the passed callback with a {@link NettyContext} to operate on the * underlying * {@link Channel} state. This allows for chaining outbound API. * * @param contextCallback context callback * * @return the {@link NettyContext} */ default NettyOutbound context(Consumer<NettyContext> contextCallback){ contextCallback.accept(context()); return this; }
final FileChunkedStrategy<?> strategy = getFileChunkedStrategy(); return then(Mono.using(() -> FileChannel.open(file, StandardOpenOption.READ), fc -> { strategy.preparePipeline(context()); try { return FutureMono.from(context().channel().writeAndFlush(message)); strategy.cleanupPipeline(context());
@Override public Mono<Void> send(Publisher<WebSocketMessage> messages) { Flux<WebSocketFrame> frames = Flux.from(messages).map(this::toFrame); return getDelegate().getOutbound() .options(NettyPipeline.SendOptions::flushOnEach) .sendObject(frames) .then(); }
/** * Send String to the peer, listen for any error on write and close on terminal signal * (complete|error). If more than one publisher is attached (multiple calls to send()) * completion occurs after all publishers complete. * Note: Nesting any send* method is not supported. * * @param dataStream the dataStream publishing Buffer items to write on this channel * @param charset the encoding charset * * @return A Publisher to signal successful sequence write (e.g. after "flush") or any * error during write */ default NettyOutbound sendString(Publisher<? extends String> dataStream, Charset charset) { return sendObject(ReactorNetty.publisherOrScalarMap(dataStream, s -> alloc() .buffer() .writeBytes(s.getBytes(charset)))); }
/** * Send content from given {@link Path} using * {@link java.nio.channels.FileChannel#transferTo(long, long, WritableByteChannel)} * support. If the system supports it and the path resolves to a local file * system {@link File} then transfer will use zero-byte copy * to the peer. * <p>It will * listen for any error on * write and close * on terminal signal (complete|error). If more than one publisher is attached * (multiple calls to send()) completion occurs after all publishers complete. * <p> * Note: this will emit {@link io.netty.channel.FileRegion} in the outbound * {@link io.netty.channel.ChannelPipeline} * Note: Nesting any send* method is not supported. * * @param file the file Path * * @return A Publisher to signal successful sequence write (e.g. after "flush") or any * error during write */ default NettyOutbound sendFile(Path file) { try { return sendFile(file, 0L, Files.size(file)); } catch (IOException e) { return then(Mono.error(e)); } }
@Override default HttpClientRequest options(Consumer<? super NettyPipeline.SendOptions> configurator){ NettyOutbound.super.options(configurator); return this; }
@Override default HttpClientRequest onWriteIdle(long idleTimeout, Runnable onWriteIdle){ NettyOutbound.super.onWriteIdle(idleTimeout, onWriteIdle); return this; }
/** * Send String to the peer, listen for any error on write and close on terminal signal * (complete|error). If more than one publisher is attached (multiple calls to send()) * completion occurs after all publishers complete. * Note: Nesting any send* method is not supported. * * @param dataStream the dataStream publishing Buffer items to write on this channel * * @return A Publisher to signal successful sequence write (e.g. after "flush") or any * error during write */ default NettyOutbound sendString(Publisher<? extends String> dataStream) { return sendString(dataStream, Charset.defaultCharset()); }
/** * Send bytes to the peer, listen for any error on write and close on terminal * signal (complete|error). If more than one publisher is attached (multiple calls to * send()) completion occurs after all publishers complete. * Note: Nesting any send* method is not supported. * * @param dataStream the dataStream publishing Buffer items to write on this channel * * @return A Publisher to signal successful sequence write (e.g. after "flush") or any * error during write */ default NettyOutbound sendByteArray(Publisher<? extends byte[]> dataStream) { return send(ReactorNetty.publisherOrScalarMap(dataStream, Unpooled::wrappedBuffer)); }
Objects.requireNonNull(file); return then(Mono.using(() -> FileChannel.open(file, StandardOpenOption.READ), fc -> { if ((context().channel().pipeline().get(SslHandler.class) != null) || context().channel().pipeline().get(NettyPipeline.CompressionHandler) != null || (!(context().channel().eventLoop() instanceof NioEventLoop) && !"file".equals(file.toUri().getScheme()))) { final FileChunkedStrategy<?> strategy = getFileChunkedStrategy(); strategy.preparePipeline(context()); return FutureMono.from(context().channel().writeAndFlush(message)); return FutureMono.from(context().channel() .writeAndFlush(new DefaultFileRegion(fc, position, count))); if (context().channel() .pipeline() .get(NettyPipeline.ChunkedWriter) != null) { getFileChunkedStrategy().cleanupPipeline(context());
/** * Send Object to the peer, listen for any error on write and close on terminal signal * (complete|error). If more than one publisher is attached (multiple calls to send()) * completion occurs after all publishers complete. * Note: Nesting any send* method is not supported. * * @param dataStream the dataStream publishing Buffer items to write on this channel * * @return A Publisher to signal successful sequence write (e.g. after "flush") or any * error during write */ default NettyOutbound sendObject(Publisher<?> dataStream) { return then(FutureMono.disposableWriteAndFlush(context().channel(), dataStream)); }
@Override default HttpServerResponse options(Consumer<? super NettyPipeline.SendOptions> configurator){ NettyOutbound.super.options(configurator); return this; }
@Override default HttpServerResponse onWriteIdle(long idleTimeout, Runnable onWriteIdle){ NettyOutbound.super.onWriteIdle(idleTimeout, onWriteIdle); return this; }
/** * Send data to the peer, listen for any error on write and close on terminal signal * (complete|error). * Note: Nesting any send* method is not supported. * * @param msg the object to publish * * @return A {@link Mono} to signal successful sequence write (e.g. after "flush") or * any error during write */ default NettyOutbound sendObject(Object msg) { context().onClose(() -> ReactorNetty.safeRelease(msg)); return then(FutureMono.deferFuture(() -> context().channel() .writeAndFlush(msg))); }
/** * Subscribe a {@code Void} subscriber to this outbound and trigger all eventual * parent outbound send. * * @param s the {@link Subscriber} to listen for send sequence completion/failure */ @Override default void subscribe(Subscriber<? super Void> s) { then().subscribe(s); }
/** * Assign a {@link Runnable} to be invoked when writes have become idle for the given * timeout. This replaces any previously set idle callback. * * @param idleTimeout the idle timeout * @param onWriteIdle the idle timeout handler * * @return {@literal this} */ default NettyOutbound onWriteIdle(long idleTimeout, Runnable onWriteIdle) { context().removeHandler(NettyPipeline.OnChannelWriteIdle); context().addHandlerFirst(NettyPipeline.OnChannelWriteIdle, new ReactorNetty.OutboundIdleStateHandler(idleTimeout, onWriteIdle)); return this; }
/** * Send headers and empty content thus delimiting a full empty body http request * * @return a {@link Mono} successful on committed response * * @see #send(Publisher) */ default Mono<Void> send() { return sendObject(Unpooled.EMPTY_BUFFER).then(); }