async Task SendUsingNewClient(IPipe<ClientContext> clientPipe, ClientScope scope, CancellationToken cancellationToken) { try { var client = new HttpClient(); var clientContext = new HttpClientContext(client, _receivePipe, _cacheTaskScope); scope.Created(clientContext); } catch (Exception ex) { Interlocked.CompareExchange(ref _scope, null, scope); scope.CreateFaulted(ex); throw; } await SendUsingExistingClient(clientPipe, scope, cancellationToken).ConfigureAwait(false); }
/// <summary> /// 接口方法的拦截器 /// </summary> /// <param name="context">httpClient上下文</param> public HttpApiInterceptor(HttpClientContext context) { this.context = context; }
public void Created(HttpClientContext clientContext) { _clientContext.TrySetResult(clientContext); _taskScope.SetReady(); }
/// <summary> /// 执行Action /// </summary> /// <param name="context">上下文</param> /// <param name="arguments">参数值</param> /// <returns></returns> public sealed override object Invoke(HttpClientContext context, object?[] arguments) { return(this.InvokeAsync(context, arguments)); }
/// <summary>Creates a tunnel to the target server.</summary> /// <remarks> /// Creates a tunnel to the target server. /// The connection must be established to the (last) proxy. /// A CONNECT request for tunnelling through the proxy will /// be created and sent, the response received and checked. /// This method does <i>not</i> update the connection with /// information about the tunnel, that is left to the caller. /// </remarks> /// <exception cref="Apache.Http.HttpException"></exception> /// <exception cref="System.IO.IOException"></exception> private bool CreateTunnelToTarget(AuthState proxyAuthState, HttpClientConnection managedConn, HttpRoute route, IHttpRequest request, HttpClientContext context) { RequestConfig config = context.GetRequestConfig(); int timeout = config.GetConnectTimeout(); HttpHost target = route.GetTargetHost(); HttpHost proxy = route.GetProxyHost(); HttpResponse response; string authority = target.ToHostString(); IHttpRequest connect = new BasicHttpRequest("CONNECT", authority, request.GetProtocolVersion ()); this.requestExecutor.PreProcess(connect, this.proxyHttpProcessor, context); for (; ;) { if (!managedConn.IsOpen()) { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); } connect.RemoveHeaders(AUTH.ProxyAuthResp); this.authenticator.GenerateAuthResponse(connect, proxyAuthState, context); response = this.requestExecutor.Execute(connect, managedConn, context); int status = response.GetStatusLine().GetStatusCode(); if (status < 200) { throw new HttpException("Unexpected response to CONNECT request: " + response.GetStatusLine ()); } if (config.IsAuthenticationEnabled()) { if (this.authenticator.IsAuthenticationRequested(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)) { if (this.authenticator.HandleAuthChallenge(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)) { // Retry request if (this.reuseStrategy.KeepAlive(response, context)) { this.log.Debug("Connection kept alive"); // Consume response content HttpEntity entity = response.GetEntity(); EntityUtils.Consume(entity); } else { managedConn.Close(); } } else { break; } } else { break; } } } int status_1 = response.GetStatusLine().GetStatusCode(); if (status_1 > 299) { // Buffer response content HttpEntity entity = response.GetEntity(); if (entity != null) { response.SetEntity(new BufferedHttpEntity(entity)); } managedConn.Close(); throw new TunnelRefusedException("CONNECT refused by proxy: " + response.GetStatusLine (), response); } // How to decide on security of the tunnelled connection? // The socket factory knows only about the segment to the proxy. // Even if that is secure, the hop to the target may be insecure. // Leave it to derived classes, consider insecure by default here. return(false); }
/// <summary>Establishes the target route.</summary> /// <remarks>Establishes the target route.</remarks> /// <exception cref="Apache.Http.HttpException"></exception> /// <exception cref="System.IO.IOException"></exception> internal virtual void EstablishRoute(AuthState proxyAuthState, HttpClientConnection managedConn, HttpRoute route, IHttpRequest request, HttpClientContext context) { RequestConfig config = context.GetRequestConfig(); int timeout = config.GetConnectTimeout(); RouteTracker tracker = new RouteTracker(route); int step; do { HttpRoute fact = tracker.ToRoute(); step = this.routeDirector.NextStep(route, fact); switch (step) { case HttpRouteDirector.ConnectTarget: { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); tracker.ConnectTarget(route.IsSecure()); break; } case HttpRouteDirector.ConnectProxy: { this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); HttpHost proxy = route.GetProxyHost(); tracker.ConnectProxy(proxy, false); break; } case HttpRouteDirector.TunnelTarget: { bool secure = CreateTunnelToTarget(proxyAuthState, managedConn, route, request, context ); this.log.Debug("Tunnel to target created."); tracker.TunnelTarget(secure); break; } case HttpRouteDirector.TunnelProxy: { // The most simple example for this case is a proxy chain // of two proxies, where P1 must be tunnelled to P2. // route: Source -> P1 -> P2 -> Target (3 hops) // fact: Source -> P1 -> Target (2 hops) int hop = fact.GetHopCount() - 1; // the hop to establish bool secure = CreateTunnelToProxy(route, hop, context); this.log.Debug("Tunnel to proxy created."); tracker.TunnelProxy(route.GetHopTarget(hop), secure); break; } case HttpRouteDirector.LayerProtocol: { this.connManager.Upgrade(managedConn, route, context); tracker.LayerProtocol(route.IsSecure()); break; } case HttpRouteDirector.Unreachable: { throw new HttpException("Unable to establish route: " + "planned = " + route + "; current = " + fact); } case HttpRouteDirector.Complete: { this.connManager.RouteComplete(managedConn, route, context); break; } default: { throw new InvalidOperationException("Unknown step indicator " + step + " from RouteDirector." ); } } }while (step > HttpRouteDirector.Complete); }
/// <exception cref="System.IO.IOException"></exception> /// <exception cref="Apache.Http.HttpException"></exception> public virtual CloseableHttpResponse Execute(HttpRoute route, HttpRequestWrapper request, HttpClientContext context, HttpExecutionAware execAware) { Args.NotNull(route, "HTTP route"); Args.NotNull(request, "HTTP request"); Args.NotNull(context, "HTTP context"); AuthState targetAuthState = context.GetTargetAuthState(); if (targetAuthState == null) { targetAuthState = new AuthState(); context.SetAttribute(HttpClientContext.TargetAuthState, targetAuthState); } AuthState proxyAuthState = context.GetProxyAuthState(); if (proxyAuthState == null) { proxyAuthState = new AuthState(); context.SetAttribute(HttpClientContext.ProxyAuthState, proxyAuthState); } if (request is HttpEntityEnclosingRequest) { Proxies.EnhanceEntity((HttpEntityEnclosingRequest)request); } object userToken = context.GetUserToken(); ConnectionRequest connRequest = connManager.RequestConnection(route, userToken); if (execAware != null) { if (execAware.IsAborted()) { connRequest.Cancel(); throw new RequestAbortedException("Request aborted"); } else { execAware.SetCancellable(connRequest); } } RequestConfig config = context.GetRequestConfig(); HttpClientConnection managedConn; try { int timeout = config.GetConnectionRequestTimeout(); managedConn = connRequest.Get(timeout > 0 ? timeout : 0, TimeUnit.Milliseconds); } catch (Exception interrupted) { Sharpen.Thread.CurrentThread().Interrupt(); throw new RequestAbortedException("Request aborted", interrupted); } catch (ExecutionException ex) { Exception cause = ex.InnerException; if (cause == null) { cause = ex; } throw new RequestAbortedException("Request execution failed", cause); } context.SetAttribute(HttpClientContext.HttpConnection, managedConn); if (config.IsStaleConnectionCheckEnabled()) { // validate connection if (managedConn.IsOpen()) { this.log.Debug("Stale connection check"); if (managedConn.IsStale()) { this.log.Debug("Stale connection detected"); managedConn.Close(); } } } ConnectionHolder connHolder = new ConnectionHolder(this.log, this.connManager, managedConn ); try { if (execAware != null) { execAware.SetCancellable(connHolder); } HttpResponse response; for (int execCount = 1; ; execCount++) { if (execCount > 1 && !Proxies.IsRepeatable(request)) { throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity." ); } if (execAware != null && execAware.IsAborted()) { throw new RequestAbortedException("Request aborted"); } if (!managedConn.IsOpen()) { this.log.Debug("Opening connection " + route); try { EstablishRoute(proxyAuthState, managedConn, route, request, context); } catch (TunnelRefusedException ex) { if (this.log.IsDebugEnabled()) { this.log.Debug(ex.Message); } response = ex.GetResponse(); break; } } int timeout = config.GetSocketTimeout(); if (timeout >= 0) { managedConn.SetSocketTimeout(timeout); } if (execAware != null && execAware.IsAborted()) { throw new RequestAbortedException("Request aborted"); } if (this.log.IsDebugEnabled()) { this.log.Debug("Executing request " + request.GetRequestLine()); } if (!request.ContainsHeader(AUTH.WwwAuthResp)) { if (this.log.IsDebugEnabled()) { this.log.Debug("Target auth state: " + targetAuthState.GetState()); } this.authenticator.GenerateAuthResponse(request, targetAuthState, context); } if (!request.ContainsHeader(AUTH.ProxyAuthResp) && !route.IsTunnelled()) { if (this.log.IsDebugEnabled()) { this.log.Debug("Proxy auth state: " + proxyAuthState.GetState()); } this.authenticator.GenerateAuthResponse(request, proxyAuthState, context); } response = requestExecutor.Execute(request, managedConn, context); // The connection is in or can be brought to a re-usable state. if (reuseStrategy.KeepAlive(response, context)) { // Set the idle duration of this connection long duration = keepAliveStrategy.GetKeepAliveDuration(response, context); if (this.log.IsDebugEnabled()) { string s; if (duration > 0) { s = "for " + duration + " " + TimeUnit.Milliseconds; } else { s = "indefinitely"; } this.log.Debug("Connection can be kept alive " + s); } connHolder.SetValidFor(duration, TimeUnit.Milliseconds); connHolder.MarkReusable(); } else { connHolder.MarkNonReusable(); } if (NeedAuthentication(targetAuthState, proxyAuthState, route, response, context)) { // Make sure the response body is fully consumed, if present HttpEntity entity = response.GetEntity(); if (connHolder.IsReusable()) { EntityUtils.Consume(entity); } else { managedConn.Close(); if (proxyAuthState.GetState() == AuthProtocolState.Success && proxyAuthState.GetAuthScheme () != null && proxyAuthState.GetAuthScheme().IsConnectionBased()) { this.log.Debug("Resetting proxy auth state"); proxyAuthState.Reset(); } if (targetAuthState.GetState() == AuthProtocolState.Success && targetAuthState.GetAuthScheme () != null && targetAuthState.GetAuthScheme().IsConnectionBased()) { this.log.Debug("Resetting target auth state"); targetAuthState.Reset(); } } // discard previous auth headers IHttpRequest original = request.GetOriginal(); if (!original.ContainsHeader(AUTH.WwwAuthResp)) { request.RemoveHeaders(AUTH.WwwAuthResp); } if (!original.ContainsHeader(AUTH.ProxyAuthResp)) { request.RemoveHeaders(AUTH.ProxyAuthResp); } } else { break; } } if (userToken == null) { userToken = userTokenHandler.GetUserToken(context); context.SetAttribute(HttpClientContext.UserToken, userToken); } if (userToken != null) { connHolder.SetState(userToken); } // check for entity, release connection if possible HttpEntity entity_1 = response.GetEntity(); if (entity_1 == null || !entity_1.IsStreaming()) { // connection not needed and (assumed to be) in re-usable state connHolder.ReleaseConnection(); return(Proxies.EnhanceResponse(response, null)); } else { return(Proxies.EnhanceResponse(response, connHolder)); } } catch (ConnectionShutdownException ex) { ThreadInterruptedException ioex = new ThreadInterruptedException("Connection has been shut down" ); Sharpen.Extensions.InitCause(ioex, ex); throw ioex; } catch (HttpException ex) { connHolder.AbortConnection(); throw; } catch (IOException ex) { connHolder.AbortConnection(); throw; } catch (RuntimeException ex) { connHolder.AbortConnection(); throw; } }
public NegativeScenariosSteps(HttpClientContext clientContext) { this._clientContext = clientContext; }