static HttpClientOperations bindHttp(Channel channel, BiFunction<? super HttpClientResponse, ? super HttpClientRequest, ? extends Publisher<Void>> handler, ContextHandler<?> context) { return new HttpClientOperations(channel, handler, context); }
@Override protected void onHandlerStart() { applyHandler(); }
@Override protected void onOutboundComplete() { if (isWebsocket() || isInboundCancelled()) { return; } if (markSentHeaderAndBody()) { if (log.isDebugEnabled()) { log.debug(format(channel(), "No sendHeaders() called before complete, sending " + "zero-length header")); } channel().writeAndFlush(newFullEmptyBodyMessage()); } else if (markSentBody()) { channel().writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); } channel().read(); }
@Override protected void onInboundCancel() { if (isInboundDisposed()){ return; } channel().close(); }
@Override public Mono<Void> send() { if (markSentHeaderAndBody()) { HttpMessage request = newFullEmptyBodyMessage(); return FutureMono.deferFuture(() -> channel().writeAndFlush(request)); } else { return Mono.empty(); } }
if (response.decoderResult() .isFailure()) { onInboundError(response.decoderResult() .cause()); ReferenceCountUtil.release(msg); log.debug(format(channel(), "HttpClientOperations cannot proceed more than one response {}"), response.headers() .toString()); setNettyResponse(response); if (!isKeepAlive()) { markPersistent(false); if(isInboundCancelled()){ ReferenceCountUtil.release(msg); return; log.debug(format(channel(), "Received response (auto-read:{}) : {}"), channel().config() .isAutoRead(), responseHeaders().entries() .toString()); if (checkResponseCode(response)) { prefetchMore(ctx); parentContext().fireContextActive(this);
final Mono<Void> withWebsocketSupport(URI url, String protocols, BiFunction<? super WebsocketInbound, ? super WebsocketOutbound, ? extends Publisher<Void>> websocketHandler) { //prevent further header to be sent for handshaking if (markSentHeaders()) { addHandlerFirst(NettyPipeline.HttpAggregator, new HttpObjectAggregator(8192)); HttpClientWSOperations ops = new HttpClientWSOperations(url, protocols, this); if (replace(ops)) { Mono<Void> handshake = FutureMono.from(ops.handshakerResult); return applyWebsocketHandler(ops, handshake, websocketHandler); } } else if (isWebsocket()) { HttpClientWSOperations ops = (HttpClientWSOperations) get(channel()); if(ops != null) { Mono<Void> handshake = FutureMono.from(ops.handshakerResult); return applyWebsocketHandler(ops, handshake, websocketHandler); } } else { log.error(format(channel(), "Cannot enable websocket if headers have already been sent")); } return Mono.error(new IllegalStateException("Failed to upgrade to websocket")); }
@Override protected void onOutboundError(Throwable err) { if(NettyContext.isPersistent(channel()) && responseState == null){ if (log.isDebugEnabled()) { log.debug(format(channel(), "Outbound error happened"), err); } parentContext().fireContextError(err); if (markSentBody()) { markPersistent(false); } onHandlerTerminate(); return; } super.onOutboundError(err); }
if (serverError){ if (log.isDebugEnabled()) { log.debug(format(channel(), "Received server error, stop reading: {}"), response.toString()); Exception ex = new HttpClientException(uri(), response); parentContext().fireContextError(ex); receive().subscribe(); return false; if (clientError) { if (log.isDebugEnabled()) { log.debug(format(channel(), "Received request error, stop reading: {}"), response.toString()); Exception ex = new HttpClientException(uri(), response); parentContext().fireContextError(ex); receive().subscribe(); return false; if ((code == 301 || code == 302) && isFollowRedirect()) { if (log.isDebugEnabled()) { log.debug(format(channel(), "Received redirect location: {}"), response.headers() .entries() .toString()); Exception ex = new RedirectClientException(uri(), response); parentContext().fireContextError(ex);
host = host + ':' + port; ch.getNettyRequest() .setUri(uri.getRawPath() + (uri.getQuery() == null ? "" : "?" + uri.getRawQuery())) || Objects.equals(parent.method, HttpMethod.HEAD) || Objects.equals(parent.method, HttpMethod.DELETE)) { ch.chunkedTransfer(false); return ch.send();
parent.chunkedTransfer(false); parent.addHandlerFirst(NettyPipeline.ChunkedWriter, new ChunkedWriteHandler()); ChannelFuture f = parent.channel() .writeAndFlush(r); parent.channel() .writeAndFlush(encoder);
Mono<Void> sendClose(CloseWebSocketFrame frame) { if (isWebsocket()) { HttpClientWSOperations ops = (HttpClientWSOperations) get(channel()); return ops.sendClose(frame); } frame.release(); return Mono.empty(); }
HttpClientWSOperations(URI currentURI, String protocols, HttpClientOperations replaced) { super(replaced.channel(), replaced); protocols, true, replaced.requestHeaders() .remove(HttpHeaderNames.HOST));
@Override public InetSocketAddress address() { return ((SocketChannel) channel()).remoteAddress(); }
@Override public HttpClientOperations context(Consumer<NettyContext> contextCallback) { contextCallback.accept(context()); return this; }
HttpClientOperations(Channel channel, BiFunction<? super HttpClientResponse, ? super HttpClientRequest, ? extends Publisher<Void>> handler, ContextHandler<?> context) { super(channel, handler, context); this.isSecure = channel.pipeline() .get(NettyPipeline.SslHandler) != null; String[] redirects = channel.attr(REDIRECT_ATTR_KEY) .get(); this.redirectedFrom = redirects == null ? EMPTY_REDIRECTIONS : redirects; this.nettyRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"); this.requestHeaders = nettyRequest.headers(); this.requestHeaders.set(HttpHeaderNames.USER_AGENT, HttpClient.USER_AGENT); this.inboundPrefetch = 16; chunkedTransfer(true); }
@Override protected ContextHandler<SocketChannel> doHandler(BiFunction<? super NettyInbound, ? super NettyOutbound, ? extends Publisher<Void>> handler, MonoSink<NettyContext> sink, boolean secure, SocketAddress providedAddress, ChannelPool pool, Consumer<? super Channel> onSetup) { ContextHandler<SocketChannel> h = ContextHandler.newClientContext(sink, options, loggingHandler, secure, providedAddress, pool, handler != null ? (ch, c, msg) -> { if(onSetup != null){ onSetup.accept(ch); } return HttpClientOperations.bindHttp(ch, handler, c); } : EMPTY); if (handler == null) { h.onPipeline(ACTIVE_CONFIGURATOR.andThen(this)); } else { h.onPipeline(this); } return h; }