Search in sources :

Example 26 with HttpRoute

use of org.apache.http.conn.routing.HttpRoute in project XobotOS by xamarin.

the class DefaultRequestDirector method execute.

// non-javadoc, see interface ClientRequestDirector
public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException, IOException {
    HttpRequest orig = request;
    RequestWrapper origWrapper = wrapRequest(orig);
    origWrapper.setParams(params);
    HttpRoute origRoute = determineRoute(target, origWrapper, context);
    RoutedRequest roureq = new RoutedRequest(origWrapper, origRoute);
    long timeout = ConnManagerParams.getTimeout(params);
    int execCount = 0;
    boolean reuse = false;
    HttpResponse response = null;
    boolean done = false;
    try {
        while (!done) {
            // In this loop, the RoutedRequest may be replaced by a
            // followup request and route. The request and route passed
            // in the method arguments will be replaced. The original
            // request is still available in 'orig'.
            RequestWrapper wrapper = roureq.getRequest();
            HttpRoute route = roureq.getRoute();
            // See if we have a user token bound to the execution context
            Object userToken = context.getAttribute(ClientContext.USER_TOKEN);
            // Allocate connection if needed
            if (managedConn == null) {
                ClientConnectionRequest connRequest = connManager.requestConnection(route, userToken);
                if (orig instanceof AbortableHttpRequest) {
                    ((AbortableHttpRequest) orig).setConnectionRequest(connRequest);
                }
                try {
                    managedConn = connRequest.getConnection(timeout, TimeUnit.MILLISECONDS);
                } catch (InterruptedException interrupted) {
                    InterruptedIOException iox = new InterruptedIOException();
                    iox.initCause(interrupted);
                    throw iox;
                }
                if (HttpConnectionParams.isStaleCheckingEnabled(params)) {
                    // validate connection
                    this.log.debug("Stale connection check");
                    if (managedConn.isStale()) {
                        this.log.debug("Stale connection detected");
                        // BEGIN android-changed
                        try {
                            managedConn.close();
                        } catch (IOException ignored) {
                        // SSLSocket's will throw IOException
                        // because they can't send a "close
                        // notify" protocol message to the
                        // server. Just supresss any
                        // exceptions related to closing the
                        // stale connection.
                        }
                    // END android-changed
                    }
                }
            }
            if (orig instanceof AbortableHttpRequest) {
                ((AbortableHttpRequest) orig).setReleaseTrigger(managedConn);
            }
            // Reopen connection if needed
            if (!managedConn.isOpen()) {
                managedConn.open(route, context, params);
            } else // BEGIN android-added
            {
                // b/3241899 set the per request timeout parameter on reused connections
                managedConn.setSocketTimeout(HttpConnectionParams.getSoTimeout(params));
            }
            try {
                establishRoute(route, context);
            } catch (TunnelRefusedException ex) {
                if (this.log.isDebugEnabled()) {
                    this.log.debug(ex.getMessage());
                }
                response = ex.getResponse();
                break;
            }
            // Reset headers on the request wrapper
            wrapper.resetHeaders();
            // Re-write request URI if needed
            rewriteRequestURI(wrapper, route);
            // Use virtual host if set
            target = (HttpHost) wrapper.getParams().getParameter(ClientPNames.VIRTUAL_HOST);
            if (target == null) {
                target = route.getTargetHost();
            }
            HttpHost proxy = route.getProxyHost();
            // Populate the execution context
            context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, target);
            context.setAttribute(ExecutionContext.HTTP_PROXY_HOST, proxy);
            context.setAttribute(ExecutionContext.HTTP_CONNECTION, managedConn);
            context.setAttribute(ClientContext.TARGET_AUTH_STATE, targetAuthState);
            context.setAttribute(ClientContext.PROXY_AUTH_STATE, proxyAuthState);
            // Run request protocol interceptors
            requestExec.preProcess(wrapper, httpProcessor, context);
            context.setAttribute(ExecutionContext.HTTP_REQUEST, wrapper);
            boolean retrying = true;
            while (retrying) {
                // Increment total exec count (with redirects)
                execCount++;
                // Increment exec count for this particular request
                wrapper.incrementExecCount();
                if (wrapper.getExecCount() > 1 && !wrapper.isRepeatable()) {
                    throw new NonRepeatableRequestException("Cannot retry request " + "with a non-repeatable request entity");
                }
                try {
                    if (this.log.isDebugEnabled()) {
                        this.log.debug("Attempt " + execCount + " to execute request");
                    }
                    response = requestExec.execute(wrapper, managedConn, context);
                    retrying = false;
                } catch (IOException ex) {
                    this.log.debug("Closing the connection.");
                    managedConn.close();
                    if (retryHandler.retryRequest(ex, execCount, context)) {
                        if (this.log.isInfoEnabled()) {
                            this.log.info("I/O exception (" + ex.getClass().getName() + ") caught when processing request: " + ex.getMessage());
                        }
                        if (this.log.isDebugEnabled()) {
                            this.log.debug(ex.getMessage(), ex);
                        }
                        this.log.info("Retrying request");
                    } else {
                        throw ex;
                    }
                    // just re-open connection and re-try the request
                    if (route.getHopCount() == 1) {
                        this.log.debug("Reopening the direct connection.");
                        managedConn.open(route, context, params);
                    } else {
                        // otherwise give up
                        throw ex;
                    }
                }
            }
            // Run response protocol interceptors
            response.setParams(params);
            requestExec.postProcess(response, httpProcessor, context);
            // The connection is in or can be brought to a re-usable state.
            reuse = reuseStrategy.keepAlive(response, context);
            if (reuse) {
                // Set the idle duration of this connection
                long duration = keepAliveStrategy.getKeepAliveDuration(response, context);
                managedConn.setIdleDuration(duration, TimeUnit.MILLISECONDS);
            }
            RoutedRequest followup = handleResponse(roureq, response, context);
            if (followup == null) {
                done = true;
            } else {
                if (reuse) {
                    this.log.debug("Connection kept alive");
                    // Make sure the response body is fully consumed, if present
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        entity.consumeContent();
                    }
                    // entity consumed above is not an auto-release entity,
                    // need to mark the connection re-usable explicitly
                    managedConn.markReusable();
                } else {
                    managedConn.close();
                }
                // check if we can use the same connection for the followup
                if (!followup.getRoute().equals(roureq.getRoute())) {
                    releaseConnection();
                }
                roureq = followup;
            }
            userToken = this.userTokenHandler.getUserToken(context);
            context.setAttribute(ClientContext.USER_TOKEN, userToken);
            if (managedConn != null) {
                managedConn.setState(userToken);
            }
        }
        // check for entity, release connection if possible
        if ((response == null) || (response.getEntity() == null) || !response.getEntity().isStreaming()) {
            // connection not needed and (assumed to be) in re-usable state
            if (reuse)
                managedConn.markReusable();
            releaseConnection();
        } else {
            // install an auto-release entity
            HttpEntity entity = response.getEntity();
            entity = new BasicManagedEntity(entity, managedConn, reuse);
            response.setEntity(entity);
        }
        return response;
    } catch (HttpException ex) {
        abortConnection();
        throw ex;
    } catch (IOException ex) {
        abortConnection();
        throw ex;
    } catch (RuntimeException ex) {
        abortConnection();
        throw ex;
    }
}
Also used : HttpRequest(org.apache.http.HttpRequest) BasicHttpRequest(org.apache.http.message.BasicHttpRequest) AbortableHttpRequest(org.apache.http.client.methods.AbortableHttpRequest) AbortableHttpRequest(org.apache.http.client.methods.AbortableHttpRequest) InterruptedIOException(java.io.InterruptedIOException) HttpEntity(org.apache.http.HttpEntity) BufferedHttpEntity(org.apache.http.entity.BufferedHttpEntity) HttpResponse(org.apache.http.HttpResponse) ClientConnectionRequest(org.apache.http.conn.ClientConnectionRequest) InterruptedIOException(java.io.InterruptedIOException) IOException(java.io.IOException) HttpRoute(org.apache.http.conn.routing.HttpRoute) BasicManagedEntity(org.apache.http.conn.BasicManagedEntity) HttpHost(org.apache.http.HttpHost) HttpException(org.apache.http.HttpException) NonRepeatableRequestException(org.apache.http.client.NonRepeatableRequestException)

Example 27 with HttpRoute

use of org.apache.http.conn.routing.HttpRoute in project XobotOS by xamarin.

the class DefaultRequestDirector method handleResponse.

/**
     * Analyzes a response to check need for a followup.
     *
     * @param roureq    the request and route. 
     * @param response  the response to analayze
     * @param context   the context used for the current request execution
     *
     * @return  the followup request and route if there is a followup, or
     *          <code>null</code> if the response should be returned as is
     *
     * @throws HttpException    in case of a problem
     * @throws IOException      in case of an IO problem
     */
protected RoutedRequest handleResponse(RoutedRequest roureq, HttpResponse response, HttpContext context) throws HttpException, IOException {
    HttpRoute route = roureq.getRoute();
    HttpHost proxy = route.getProxyHost();
    RequestWrapper request = roureq.getRequest();
    HttpParams params = request.getParams();
    if (HttpClientParams.isRedirecting(params) && this.redirectHandler.isRedirectRequested(response, context)) {
        if (redirectCount >= maxRedirects) {
            throw new RedirectException("Maximum redirects (" + maxRedirects + ") exceeded");
        }
        redirectCount++;
        URI uri = this.redirectHandler.getLocationURI(response, context);
        HttpHost newTarget = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
        HttpGet redirect = new HttpGet(uri);
        HttpRequest orig = request.getOriginal();
        redirect.setHeaders(orig.getAllHeaders());
        RequestWrapper wrapper = new RequestWrapper(redirect);
        wrapper.setParams(params);
        HttpRoute newRoute = determineRoute(newTarget, wrapper, context);
        RoutedRequest newRequest = new RoutedRequest(wrapper, newRoute);
        if (this.log.isDebugEnabled()) {
            this.log.debug("Redirecting to '" + uri + "' via " + newRoute);
        }
        return newRequest;
    }
    CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(ClientContext.CREDS_PROVIDER);
    if (credsProvider != null && HttpClientParams.isAuthenticating(params)) {
        if (this.targetAuthHandler.isAuthenticationRequested(response, context)) {
            HttpHost target = (HttpHost) context.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
            if (target == null) {
                target = route.getTargetHost();
            }
            this.log.debug("Target requested authentication");
            Map<String, Header> challenges = this.targetAuthHandler.getChallenges(response, context);
            try {
                processChallenges(challenges, this.targetAuthState, this.targetAuthHandler, response, context);
            } catch (AuthenticationException ex) {
                if (this.log.isWarnEnabled()) {
                    this.log.warn("Authentication error: " + ex.getMessage());
                    return null;
                }
            }
            updateAuthState(this.targetAuthState, target, credsProvider);
            if (this.targetAuthState.getCredentials() != null) {
                // Re-try the same request via the same route
                return roureq;
            } else {
                return null;
            }
        } else {
            // Reset target auth scope
            this.targetAuthState.setAuthScope(null);
        }
        if (this.proxyAuthHandler.isAuthenticationRequested(response, context)) {
            this.log.debug("Proxy requested authentication");
            Map<String, Header> challenges = this.proxyAuthHandler.getChallenges(response, context);
            try {
                processChallenges(challenges, this.proxyAuthState, this.proxyAuthHandler, response, context);
            } catch (AuthenticationException ex) {
                if (this.log.isWarnEnabled()) {
                    this.log.warn("Authentication error: " + ex.getMessage());
                    return null;
                }
            }
            updateAuthState(this.proxyAuthState, proxy, credsProvider);
            if (this.proxyAuthState.getCredentials() != null) {
                // Re-try the same request via the same route
                return roureq;
            } else {
                return null;
            }
        } else {
            // Reset proxy auth scope
            this.proxyAuthState.setAuthScope(null);
        }
    }
    return null;
}
Also used : HttpRequest(org.apache.http.HttpRequest) BasicHttpRequest(org.apache.http.message.BasicHttpRequest) AbortableHttpRequest(org.apache.http.client.methods.AbortableHttpRequest) AuthenticationException(org.apache.http.auth.AuthenticationException) HttpGet(org.apache.http.client.methods.HttpGet) CredentialsProvider(org.apache.http.client.CredentialsProvider) URI(java.net.URI) HttpRoute(org.apache.http.conn.routing.HttpRoute) HttpParams(org.apache.http.params.HttpParams) Header(org.apache.http.Header) HttpHost(org.apache.http.HttpHost) RedirectException(org.apache.http.client.RedirectException)

Example 28 with HttpRoute

use of org.apache.http.conn.routing.HttpRoute in project XobotOS by xamarin.

the class DefaultRequestDirector method establishRoute.

/**
     * Establishes the target route.
     *
     * @param route     the route to establish
     * @param context   the context for the request execution
     *
     * @throws HttpException    in case of a problem
     * @throws IOException      in case of an IO problem
     */
protected void establishRoute(HttpRoute route, HttpContext context) throws HttpException, IOException {
    //@@@ how to handle CONNECT requests for tunnelling?
    //@@@ refuse to send external CONNECT via director? special handling?
    //@@@ should the request parameters already be used below?
    //@@@ probably yes, but they're not linked yet
    //@@@ will linking above cause problems with linking in reqExec?
    //@@@ probably not, because the parent is replaced
    //@@@ just make sure we don't link parameters to themselves
    HttpRouteDirector rowdy = new BasicRouteDirector();
    int step;
    do {
        HttpRoute fact = managedConn.getRoute();
        step = rowdy.nextStep(route, fact);
        switch(step) {
            case HttpRouteDirector.CONNECT_TARGET:
            case HttpRouteDirector.CONNECT_PROXY:
                managedConn.open(route, context, this.params);
                break;
            case HttpRouteDirector.TUNNEL_TARGET:
                {
                    boolean secure = createTunnelToTarget(route, context);
                    this.log.debug("Tunnel to target created.");
                    managedConn.tunnelTarget(secure, this.params);
                }
                break;
            case HttpRouteDirector.TUNNEL_PROXY:
                {
                    // 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)
                    // the hop to establish
                    final int hop = fact.getHopCount() - 1;
                    boolean secure = createTunnelToProxy(route, hop, context);
                    this.log.debug("Tunnel to proxy created.");
                    managedConn.tunnelProxy(route.getHopTarget(hop), secure, this.params);
                }
                break;
            case HttpRouteDirector.LAYER_PROTOCOL:
                managedConn.layerProtocol(context, this.params);
                break;
            case HttpRouteDirector.UNREACHABLE:
                throw new IllegalStateException("Unable to establish route." + "\nplanned = " + route + "\ncurrent = " + fact);
            case HttpRouteDirector.COMPLETE:
                // do nothing
                break;
            default:
                throw new IllegalStateException("Unknown step indicator " + step + " from RouteDirector.");
        }
    // switch
    } while (step > HttpRouteDirector.COMPLETE);
}
Also used : HttpRoute(org.apache.http.conn.routing.HttpRoute) BasicRouteDirector(org.apache.http.conn.routing.BasicRouteDirector) HttpRouteDirector(org.apache.http.conn.routing.HttpRouteDirector)

Example 29 with HttpRoute

use of org.apache.http.conn.routing.HttpRoute in project XobotOS by xamarin.

the class DefaultHttpRoutePlanner method determineRoute.

// non-javadoc, see interface HttpRoutePlanner
public HttpRoute determineRoute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
    if (request == null) {
        throw new IllegalStateException("Request must not be null.");
    }
    // If we have a forced route, we can do without a target.
    HttpRoute route = ConnRouteParams.getForcedRoute(request.getParams());
    if (route != null)
        return route;
    if (target == null) {
        throw new IllegalStateException("Target host must not be null.");
    }
    final InetAddress local = ConnRouteParams.getLocalAddress(request.getParams());
    final HttpHost proxy = ConnRouteParams.getDefaultProxy(request.getParams());
    final Scheme schm = schemeRegistry.getScheme(target.getSchemeName());
    // as it is typically used for TLS/SSL, we assume that
    // a layered scheme implies a secure connection
    final boolean secure = schm.isLayered();
    if (proxy == null) {
        route = new HttpRoute(target, local, secure);
    } else {
        route = new HttpRoute(target, local, proxy, secure);
    }
    return route;
}
Also used : HttpRoute(org.apache.http.conn.routing.HttpRoute) Scheme(org.apache.http.conn.scheme.Scheme) HttpHost(org.apache.http.HttpHost) InetAddress(java.net.InetAddress)

Example 30 with HttpRoute

use of org.apache.http.conn.routing.HttpRoute in project XobotOS by xamarin.

the class ConnPoolByRoute method deleteEntry.

/**
     * Deletes a given pool entry.
     * This closes the pooled connection and removes all references,
     * so that it can be GCed.
     * 
     * <p><b>Note:</b> Does not remove the entry from the freeConnections list.
     * It is assumed that the caller has already handled this step.</p>
     * <!-- @@@ is that a good idea? or rather fix it? -->
     * 
     * @param entry         the pool entry for the connection to delete
     */
protected void deleteEntry(BasicPoolEntry entry) {
    HttpRoute route = entry.getPlannedRoute();
    if (log.isDebugEnabled()) {
        log.debug("Deleting connection" + " [" + route + "][" + entry.getState() + "]");
    }
    poolLock.lock();
    try {
        closeConnection(entry.getConnection());
        RouteSpecificPool rospl = getRoutePool(route, true);
        rospl.deleteEntry(entry);
        numConnections--;
        if (rospl.isUnused()) {
            routeToPool.remove(route);
        }
        // not idle, but dead
        idleConnHandler.remove(entry.getConnection());
    } finally {
        poolLock.unlock();
    }
}
Also used : HttpRoute(org.apache.http.conn.routing.HttpRoute)

Aggregations

HttpRoute (org.apache.http.conn.routing.HttpRoute)33 HttpHost (org.apache.http.HttpHost)17 HttpRequest (org.apache.http.HttpRequest)9 AbortableHttpRequest (org.apache.http.client.methods.AbortableHttpRequest)8 BasicHttpRequest (org.apache.http.message.BasicHttpRequest)8 InetAddress (java.net.InetAddress)7 IOException (java.io.IOException)6 HttpException (org.apache.http.HttpException)6 Scheme (org.apache.http.conn.scheme.Scheme)6 HttpResponse (org.apache.http.HttpResponse)5 AuthenticationException (org.apache.http.auth.AuthenticationException)5 RedirectException (org.apache.http.client.RedirectException)5 ClientConnectionRequest (org.apache.http.conn.ClientConnectionRequest)5 HttpParams (org.apache.http.params.HttpParams)5 InterruptedIOException (java.io.InterruptedIOException)4 URI (java.net.URI)4 Header (org.apache.http.Header)4 HttpEntity (org.apache.http.HttpEntity)4 CredentialsProvider (org.apache.http.client.CredentialsProvider)4 NonRepeatableRequestException (org.apache.http.client.NonRepeatableRequestException)4