/// <exception cref="System.IO.IOException"></exception> public virtual void Upgrade(HttpClientConnection conn, HttpRoute route, HttpContext context) { Args.NotNull(conn, "Connection"); Args.NotNull(route, "HTTP route"); Asserts.Check(conn == this.conn, "Connection not obtained from this manager"); this.connectionOperator.Upgrade(this.conn, route.GetTargetHost(), context); }
private bool NeedAuthentication(AuthState targetAuthState, AuthState proxyAuthState , HttpRoute route, HttpResponse response, HttpClientContext context) { RequestConfig config = context.GetRequestConfig(); if (config.IsAuthenticationEnabled()) { HttpHost target = context.GetTargetHost(); if (target == null) { target = route.GetTargetHost(); } if (target.GetPort() < 0) { target = new HttpHost(target.GetHostName(), route.GetTargetHost().GetPort(), target .GetSchemeName()); } if (this.authenticator.IsAuthenticationRequested(target, response, this.targetAuthStrategy , targetAuthState, context)) { return(this.authenticator.HandleAuthChallenge(target, response, this.targetAuthStrategy , targetAuthState, context)); } HttpHost proxy = route.GetProxyHost(); if (this.authenticator.IsAuthenticationRequested(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)) { // if proxy is not set use target host instead if (proxy == null) { proxy = route.GetTargetHost(); } return(this.authenticator.HandleAuthChallenge(proxy, response, this.proxyAuthStrategy , proxyAuthState, context)); } } return(false); }
/// <exception cref="Apache.Http.ProtocolException"></exception> internal virtual void RewriteRequestURI(HttpRequestWrapper request, HttpRoute route ) { try { URI uri = request.GetURI(); if (uri != null) { if (route.GetProxyHost() != null && !route.IsTunnelled()) { // Make sure the request URI is absolute if (!uri.IsAbsolute()) { HttpHost target = route.GetTargetHost(); uri = URIUtils.RewriteURI(uri, target, true); } else { uri = URIUtils.RewriteURI(uri); } } else { // Make sure the request URI is relative if (uri.IsAbsolute()) { uri = URIUtils.RewriteURI(uri, null, true); } else { uri = URIUtils.RewriteURI(uri); } } request.SetURI(uri); } } catch (URISyntaxException ex) { throw new ProtocolException("Invalid URI: " + request.GetRequestLine().GetUri(), ex); } }
/// <exception cref="System.IO.IOException"></exception> public virtual void Connect(HttpClientConnection conn, HttpRoute route, int connectTimeout , HttpContext context) { Args.NotNull(conn, "Connection"); Args.NotNull(route, "HTTP route"); Asserts.Check(conn == this.conn, "Connection not obtained from this manager"); HttpHost host; if (route.GetProxyHost() != null) { host = route.GetProxyHost(); } else { host = route.GetTargetHost(); } IPEndPoint localAddress = route.GetLocalSocketAddress(); this.connectionOperator.Connect(this.conn, host, localAddress, connectTimeout, this .socketConfig, context); }
/// <exception cref="Apache.Http.Auth.AuthenticationException"></exception> public override Header Authenticate(Credentials credentials, IHttpRequest request , HttpContext context) { Args.NotNull(request, "HTTP request"); switch (state) { case GGSSchemeBase.State.Uninitiated: { throw new AuthenticationException(GetSchemeName() + " authentication has not been initiated" ); } case GGSSchemeBase.State.Failed: { throw new AuthenticationException(GetSchemeName() + " authentication has failed"); } case GGSSchemeBase.State.ChallengeReceived: { try { HttpRoute route = (HttpRoute)context.GetAttribute(HttpClientContext.HttpRoute); if (route == null) { throw new AuthenticationException("Connection route is not available"); } HttpHost host; if (IsProxy()) { host = route.GetProxyHost(); if (host == null) { host = route.GetTargetHost(); } } else { host = route.GetTargetHost(); } string authServer; if (!this.stripPort && host.GetPort() > 0) { authServer = host.ToHostString(); } else { authServer = host.GetHostName(); } if (log.IsDebugEnabled()) { log.Debug("init " + authServer); } token = GenerateToken(token, authServer); state = GGSSchemeBase.State.TokenGenerated; } catch (GSSException gsse) { state = GGSSchemeBase.State.Failed; if (gsse.GetMajor() == GSSException.DefectiveCredential || gsse.GetMajor() == GSSException .CredentialsExpired) { throw new InvalidCredentialsException(gsse.Message, gsse); } if (gsse.GetMajor() == GSSException.NoCred) { throw new InvalidCredentialsException(gsse.Message, gsse); } if (gsse.GetMajor() == GSSException.DefectiveToken || gsse.GetMajor() == GSSException .DuplicateToken || gsse.GetMajor() == GSSException.OldToken) { throw new AuthenticationException(gsse.Message, gsse); } // other error throw new AuthenticationException(gsse.Message); } goto case GGSSchemeBase.State.TokenGenerated; } case GGSSchemeBase.State.TokenGenerated: { string tokenstr = Sharpen.Runtime.GetStringForBytes(base64codec.Encode(token)); if (log.IsDebugEnabled()) { log.Debug("Sending response '" + tokenstr + "' back to the auth server"); } CharArrayBuffer buffer = new CharArrayBuffer(32); if (IsProxy()) { buffer.Append(AUTH.ProxyAuthResp); } else { buffer.Append(AUTH.WwwAuthResp); } buffer.Append(": Negotiate "); buffer.Append(tokenstr); return(new BufferedHeader(buffer)); } default: { throw new InvalidOperationException("Illegal state: " + state); } } }
/// <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"); IHttpRequest original = request.GetOriginal(); URI uri = null; if (original is IHttpUriRequest) { uri = ((IHttpUriRequest)original).GetURI(); } else { string uriString = original.GetRequestLine().GetUri(); try { uri = URI.Create(uriString); } catch (ArgumentException ex) { if (this.log.IsDebugEnabled()) { this.log.Debug("Unable to parse '" + uriString + "' as a valid URI; " + "request URI and Host header may be inconsistent" , ex); } } } request.SetURI(uri); // Re-write request URI if needed RewriteRequestURI(request, route); HttpParams @params = request.GetParams(); HttpHost virtualHost = (HttpHost)@params.GetParameter(ClientPNames.VirtualHost); // HTTPCLIENT-1092 - add the port if necessary if (virtualHost != null && virtualHost.GetPort() == -1) { int port = route.GetTargetHost().GetPort(); if (port != -1) { virtualHost = new HttpHost(virtualHost.GetHostName(), port, virtualHost.GetSchemeName ()); } if (this.log.IsDebugEnabled()) { this.log.Debug("Using virtual host" + virtualHost); } } HttpHost target = null; if (virtualHost != null) { target = virtualHost; } else { if (uri != null && uri.IsAbsolute() && uri.GetHost() != null) { target = new HttpHost(uri.GetHost(), uri.GetPort(), uri.GetScheme()); } } if (target == null) { target = route.GetTargetHost(); } // Get user info from the URI if (uri != null) { string userinfo = uri.GetUserInfo(); if (userinfo != null) { CredentialsProvider credsProvider = context.GetCredentialsProvider(); if (credsProvider == null) { credsProvider = new BasicCredentialsProvider(); context.SetCredentialsProvider(credsProvider); } credsProvider.SetCredentials(new AuthScope(target), new UsernamePasswordCredentials (userinfo)); } } // Run request protocol interceptors context.SetAttribute(HttpClientContext.HttpTargetHost, target); context.SetAttribute(HttpClientContext.HttpRoute, route); context.SetAttribute(HttpClientContext.HttpRequest, request); this.httpProcessor.Process(request, context); CloseableHttpResponse response = this.requestExecutor.Execute(route, request, context , execAware); try { // Run response protocol interceptors context.SetAttribute(HttpClientContext.HttpResponse, response); this.httpProcessor.Process(response, context); return(response); } catch (RuntimeException ex) { response.Close(); throw; } catch (IOException ex) { response.Close(); throw; } catch (HttpException ex) { response.Close(); throw; } }
/// <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"); ConnectionRequest connRequest = connManager.RequestConnection(route, null); 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); } ConnectionHolder releaseTrigger = new ConnectionHolder(log, connManager, managedConn ); try { if (execAware != null) { if (execAware.IsAborted()) { releaseTrigger.Close(); throw new RequestAbortedException("Request aborted"); } else { execAware.SetCancellable(releaseTrigger); } } if (!managedConn.IsOpen()) { int timeout = config.GetConnectTimeout(); this.connManager.Connect(managedConn, route, timeout > 0 ? timeout : 0, context); this.connManager.RouteComplete(managedConn, route, context); } int timeout_1 = config.GetSocketTimeout(); if (timeout_1 >= 0) { managedConn.SetSocketTimeout(timeout_1); } HttpHost target = null; IHttpRequest original = request.GetOriginal(); if (original is IHttpUriRequest) { URI uri = ((IHttpUriRequest)original).GetURI(); if (uri.IsAbsolute()) { target = new HttpHost(uri.GetHost(), uri.GetPort(), uri.GetScheme()); } } if (target == null) { target = route.GetTargetHost(); } context.SetAttribute(HttpClientContext.HttpTargetHost, target); context.SetAttribute(HttpClientContext.HttpRequest, request); context.SetAttribute(HttpClientContext.HttpConnection, managedConn); context.SetAttribute(HttpClientContext.HttpRoute, route); httpProcessor.Process(request, context); HttpResponse response = requestExecutor.Execute(request, managedConn, context); httpProcessor.Process(response, 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); releaseTrigger.SetValidFor(duration, TimeUnit.Milliseconds); releaseTrigger.MarkReusable(); } else { releaseTrigger.MarkNonReusable(); } // check for entity, release connection if possible HttpEntity entity = response.GetEntity(); if (entity == null || !entity.IsStreaming()) { // connection not needed and (assumed to be) in re-usable state releaseTrigger.ReleaseConnection(); return(Proxies.EnhanceResponse(response, null)); } else { return(Proxies.EnhanceResponse(response, releaseTrigger)); } } catch (ConnectionShutdownException ex) { ThreadInterruptedException ioex = new ThreadInterruptedException("Connection has been shut down" ); Sharpen.Extensions.InitCause(ioex, ex); throw ioex; } catch (HttpException ex) { releaseTrigger.AbortConnection(); throw; } catch (IOException ex) { releaseTrigger.AbortConnection(); throw; } catch (RuntimeException ex) { releaseTrigger.AbortConnection(); throw; } }
/// <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"); IList <URI> redirectLocations = context.GetRedirectLocations(); if (redirectLocations != null) { redirectLocations.Clear(); } RequestConfig config = context.GetRequestConfig(); int maxRedirects = config.GetMaxRedirects() > 0 ? config.GetMaxRedirects() : 50; HttpRoute currentRoute = route; HttpRequestWrapper currentRequest = request; for (int redirectCount = 0; ;) { CloseableHttpResponse response = requestExecutor.Execute(currentRoute, currentRequest , context, execAware); try { if (config.IsRedirectsEnabled() && this.redirectStrategy.IsRedirected(currentRequest , response, context)) { if (redirectCount >= maxRedirects) { throw new RedirectException("Maximum redirects (" + maxRedirects + ") exceeded"); } redirectCount++; IHttpRequest redirect = this.redirectStrategy.GetRedirect(currentRequest, response , context); if (!redirect.HeaderIterator().HasNext()) { IHttpRequest original = request.GetOriginal(); redirect.SetHeaders(original.GetAllHeaders()); } currentRequest = HttpRequestWrapper.Wrap(redirect); if (currentRequest is HttpEntityEnclosingRequest) { Proxies.EnhanceEntity((HttpEntityEnclosingRequest)currentRequest); } URI uri = currentRequest.GetURI(); HttpHost newTarget = URIUtils.ExtractHost(uri); if (newTarget == null) { throw new ProtocolException("Redirect URI does not specify a valid host name: " + uri); } // Reset virtual host and auth states if redirecting to another host if (!currentRoute.GetTargetHost().Equals(newTarget)) { AuthState targetAuthState = context.GetTargetAuthState(); if (targetAuthState != null) { this.log.Debug("Resetting target auth state"); targetAuthState.Reset(); } AuthState proxyAuthState = context.GetProxyAuthState(); if (proxyAuthState != null) { AuthScheme authScheme = proxyAuthState.GetAuthScheme(); if (authScheme != null && authScheme.IsConnectionBased()) { this.log.Debug("Resetting proxy auth state"); proxyAuthState.Reset(); } } } currentRoute = this.routePlanner.DetermineRoute(newTarget, currentRequest, context ); if (this.log.IsDebugEnabled()) { this.log.Debug("Redirecting to '" + uri + "' via " + currentRoute); } EntityUtils.Consume(response.GetEntity()); response.Close(); } else { return(response); } } catch (RuntimeException ex) { response.Close(); throw; } catch (IOException ex) { response.Close(); throw; } catch (HttpException ex) { // Protocol exception related to a direct. // The underlying connection may still be salvaged. try { EntityUtils.Consume(response.GetEntity()); } catch (IOException ioex) { this.log.Debug("I/O error while releasing connection", ioex); } finally { response.Close(); } throw; } } }
/// <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); }