mobile/android/thirdparty/ch/boye/httpclientandroidlib/protocol/HttpService.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  * ====================================================================
     3  * Licensed to the Apache Software Foundation (ASF) under one
     4  * or more contributor license agreements.  See the NOTICE file
     5  * distributed with this work for additional information
     6  * regarding copyright ownership.  The ASF licenses this file
     7  * to you under the Apache License, Version 2.0 (the
     8  * "License"); you may not use this file except in compliance
     9  * with the License.  You may obtain a copy of the License at
    10  *
    11  *   http://www.apache.org/licenses/LICENSE-2.0
    12  *
    13  * Unless required by applicable law or agreed to in writing,
    14  * software distributed under the License is distributed on an
    15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    16  * KIND, either express or implied.  See the License for the
    17  * specific language governing permissions and limitations
    18  * under the License.
    19  * ====================================================================
    20  *
    21  * This software consists of voluntary contributions made by many
    22  * individuals on behalf of the Apache Software Foundation.  For more
    23  * information on the Apache Software Foundation, please see
    24  * <http://www.apache.org/>.
    25  *
    26  */
    28 package ch.boye.httpclientandroidlib.protocol;
    30 import java.io.IOException;
    32 import ch.boye.httpclientandroidlib.ConnectionReuseStrategy;
    33 import ch.boye.httpclientandroidlib.HttpEntity;
    34 import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest;
    35 import ch.boye.httpclientandroidlib.HttpException;
    36 import ch.boye.httpclientandroidlib.HttpRequest;
    37 import ch.boye.httpclientandroidlib.HttpResponse;
    38 import ch.boye.httpclientandroidlib.HttpResponseFactory;
    39 import ch.boye.httpclientandroidlib.HttpServerConnection;
    40 import ch.boye.httpclientandroidlib.HttpStatus;
    41 import ch.boye.httpclientandroidlib.HttpVersion;
    42 import ch.boye.httpclientandroidlib.MethodNotSupportedException;
    43 import ch.boye.httpclientandroidlib.ProtocolException;
    44 import ch.boye.httpclientandroidlib.ProtocolVersion;
    45 import ch.boye.httpclientandroidlib.UnsupportedHttpVersionException;
    46 import ch.boye.httpclientandroidlib.entity.ByteArrayEntity;
    47 import ch.boye.httpclientandroidlib.params.HttpParams;
    48 import ch.boye.httpclientandroidlib.params.DefaultedHttpParams;
    49 import ch.boye.httpclientandroidlib.util.EncodingUtils;
    50 import ch.boye.httpclientandroidlib.util.EntityUtils;
    52 /**
    53  * HttpService is a server side HTTP protocol handler based in the blocking
    54  * I/O model that implements the essential requirements of the HTTP protocol
    55  * for the server side message processing as described by RFC 2616.
    56  * <br>
    57  * HttpService relies on {@link HttpProcessor} to generate mandatory protocol
    58  * headers for all outgoing messages and apply common, cross-cutting message
    59  * transformations to all incoming and outgoing messages, whereas individual
    60  * {@link HttpRequestHandler}s are expected to take care of application specific
    61  * content generation and processing.
    62  * <br>
    63  * HttpService relies on {@link HttpRequestHandler} to resolve matching request
    64  * handler for a particular request URI of an incoming HTTP request.
    65  * <br>
    66  * HttpService can use optional {@link HttpExpectationVerifier} to ensure that
    67  * incoming requests meet server's expectations.
    68  *
    69  * @since 4.0
    70  */
    71 public class HttpService {
    73     /**
    74      * TODO: make all variables final in the next major version
    75      */
    76     private volatile HttpParams params = null;
    77     private volatile HttpProcessor processor = null;
    78     private volatile HttpRequestHandlerResolver handlerResolver = null;
    79     private volatile ConnectionReuseStrategy connStrategy = null;
    80     private volatile HttpResponseFactory responseFactory = null;
    81     private volatile HttpExpectationVerifier expectationVerifier = null;
    83     /**
    84      * Create a new HTTP service.
    85      *
    86      * @param processor            the processor to use on requests and responses
    87      * @param connStrategy         the connection reuse strategy
    88      * @param responseFactory      the response factory
    89      * @param handlerResolver      the handler resolver. May be null.
    90      * @param expectationVerifier  the expectation verifier. May be null.
    91      * @param params               the HTTP parameters
    92      *
    93      * @since 4.1
    94      */
    95     public HttpService(
    96             final HttpProcessor processor,
    97             final ConnectionReuseStrategy connStrategy,
    98             final HttpResponseFactory responseFactory,
    99             final HttpRequestHandlerResolver handlerResolver,
   100             final HttpExpectationVerifier expectationVerifier,
   101             final HttpParams params) {
   102         super();
   103         if (processor == null) {
   104             throw new IllegalArgumentException("HTTP processor may not be null");
   105         }
   106         if (connStrategy == null) {
   107             throw new IllegalArgumentException("Connection reuse strategy may not be null");
   108         }
   109         if (responseFactory == null) {
   110             throw new IllegalArgumentException("Response factory may not be null");
   111         }
   112         if (params == null) {
   113             throw new IllegalArgumentException("HTTP parameters may not be null");
   114         }
   115         this.processor = processor;
   116         this.connStrategy = connStrategy;
   117         this.responseFactory = responseFactory;
   118         this.handlerResolver = handlerResolver;
   119         this.expectationVerifier = expectationVerifier;
   120         this.params = params;
   121     }
   123     /**
   124      * Create a new HTTP service.
   125      *
   126      * @param processor            the processor to use on requests and responses
   127      * @param connStrategy         the connection reuse strategy
   128      * @param responseFactory      the response factory
   129      * @param handlerResolver      the handler resolver. May be null.
   130      * @param params               the HTTP parameters
   131      *
   132      * @since 4.1
   133      */
   134     public HttpService(
   135             final HttpProcessor processor,
   136             final ConnectionReuseStrategy connStrategy,
   137             final HttpResponseFactory responseFactory,
   138             final HttpRequestHandlerResolver handlerResolver,
   139             final HttpParams params) {
   140         this(processor, connStrategy, responseFactory, handlerResolver, null, params);
   141     }
   143     /**
   144      * Create a new HTTP service.
   145      *
   146      * @param proc             the processor to use on requests and responses
   147      * @param connStrategy     the connection reuse strategy
   148      * @param responseFactory  the response factory
   149      *
   150      * @deprecated use {@link HttpService#HttpService(HttpProcessor,
   151      *  ConnectionReuseStrategy, HttpResponseFactory, HttpRequestHandlerResolver, HttpParams)}
   152      */
   153     public HttpService(
   154             final HttpProcessor proc,
   155             final ConnectionReuseStrategy connStrategy,
   156             final HttpResponseFactory responseFactory) {
   157         super();
   158         setHttpProcessor(proc);
   159         setConnReuseStrategy(connStrategy);
   160         setResponseFactory(responseFactory);
   161     }
   163     /**
   164      * @deprecated set {@link HttpProcessor} using constructor
   165      */
   166     public void setHttpProcessor(final HttpProcessor processor) {
   167         if (processor == null) {
   168             throw new IllegalArgumentException("HTTP processor may not be null");
   169         }
   170         this.processor = processor;
   171     }
   173     /**
   174      * @deprecated set {@link ConnectionReuseStrategy} using constructor
   175      */
   176     public void setConnReuseStrategy(final ConnectionReuseStrategy connStrategy) {
   177         if (connStrategy == null) {
   178             throw new IllegalArgumentException("Connection reuse strategy may not be null");
   179         }
   180         this.connStrategy = connStrategy;
   181     }
   183     /**
   184      * @deprecated set {@link HttpResponseFactory} using constructor
   185      */
   186     public void setResponseFactory(final HttpResponseFactory responseFactory) {
   187         if (responseFactory == null) {
   188             throw new IllegalArgumentException("Response factory may not be null");
   189         }
   190         this.responseFactory = responseFactory;
   191     }
   193     /**
   194      * @deprecated set {@link HttpResponseFactory} using constructor
   195      */
   196     public void setParams(final HttpParams params) {
   197         this.params = params;
   198     }
   200     /**
   201      * @deprecated set {@link HttpRequestHandlerResolver} using constructor
   202      */
   203     public void setHandlerResolver(final HttpRequestHandlerResolver handlerResolver) {
   204         this.handlerResolver = handlerResolver;
   205     }
   207     /**
   208      * @deprecated set {@link HttpExpectationVerifier} using constructor
   209      */
   210     public void setExpectationVerifier(final HttpExpectationVerifier expectationVerifier) {
   211         this.expectationVerifier = expectationVerifier;
   212     }
   214     public HttpParams getParams() {
   215         return this.params;
   216     }
   218     /**
   219      * Handles receives one HTTP request over the given connection within the
   220      * given execution context and sends a response back to the client.
   221      *
   222      * @param conn the active connection to the client
   223      * @param context the actual execution context.
   224      * @throws IOException in case of an I/O error.
   225      * @throws HttpException in case of HTTP protocol violation or a processing
   226      *   problem.
   227      */
   228     public void handleRequest(
   229             final HttpServerConnection conn,
   230             final HttpContext context) throws IOException, HttpException {
   232         context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
   234         HttpResponse response = null;
   236         try {
   238             HttpRequest request = conn.receiveRequestHeader();
   239             request.setParams(
   240                     new DefaultedHttpParams(request.getParams(), this.params));
   242             ProtocolVersion ver =
   243                 request.getRequestLine().getProtocolVersion();
   244             if (!ver.lessEquals(HttpVersion.HTTP_1_1)) {
   245                 // Downgrade protocol version if greater than HTTP/1.1
   246                 ver = HttpVersion.HTTP_1_1;
   247             }
   249             if (request instanceof HttpEntityEnclosingRequest) {
   251                 if (((HttpEntityEnclosingRequest) request).expectContinue()) {
   252                     response = this.responseFactory.newHttpResponse(ver,
   253                             HttpStatus.SC_CONTINUE, context);
   254                     response.setParams(
   255                             new DefaultedHttpParams(response.getParams(), this.params));
   257                     if (this.expectationVerifier != null) {
   258                         try {
   259                             this.expectationVerifier.verify(request, response, context);
   260                         } catch (HttpException ex) {
   261                             response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0,
   262                                     HttpStatus.SC_INTERNAL_SERVER_ERROR, context);
   263                             response.setParams(
   264                                     new DefaultedHttpParams(response.getParams(), this.params));
   265                             handleException(ex, response);
   266                         }
   267                     }
   268                     if (response.getStatusLine().getStatusCode() < 200) {
   269                         // Send 1xx response indicating the server expections
   270                         // have been met
   271                         conn.sendResponseHeader(response);
   272                         conn.flush();
   273                         response = null;
   274                         conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
   275                     }
   276                 } else {
   277                     conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
   278                 }
   279             }
   281             if (response == null) {
   282                 response = this.responseFactory.newHttpResponse(ver, HttpStatus.SC_OK, context);
   283                 response.setParams(
   284                         new DefaultedHttpParams(response.getParams(), this.params));
   286                 context.setAttribute(ExecutionContext.HTTP_REQUEST, request);
   287                 context.setAttribute(ExecutionContext.HTTP_RESPONSE, response);
   289                 this.processor.process(request, context);
   290                 doService(request, response, context);
   291             }
   293             // Make sure the request content is fully consumed
   294             if (request instanceof HttpEntityEnclosingRequest) {
   295                 HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
   296                 EntityUtils.consume(entity);
   297             }
   299         } catch (HttpException ex) {
   300             response = this.responseFactory.newHttpResponse
   301                 (HttpVersion.HTTP_1_0, HttpStatus.SC_INTERNAL_SERVER_ERROR,
   302                  context);
   303             response.setParams(
   304                     new DefaultedHttpParams(response.getParams(), this.params));
   305             handleException(ex, response);
   306         }
   308         this.processor.process(response, context);
   309         conn.sendResponseHeader(response);
   310         conn.sendResponseEntity(response);
   311         conn.flush();
   313         if (!this.connStrategy.keepAlive(response, context)) {
   314             conn.close();
   315         }
   316     }
   318     /**
   319      * Handles the given exception and generates an HTTP response to be sent
   320      * back to the client to inform about the exceptional condition encountered
   321      * in the course of the request processing.
   322      *
   323      * @param ex the exception.
   324      * @param response the HTTP response.
   325      */
   326     protected void handleException(final HttpException ex, final HttpResponse response) {
   327         if (ex instanceof MethodNotSupportedException) {
   328             response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
   329         } else if (ex instanceof UnsupportedHttpVersionException) {
   330             response.setStatusCode(HttpStatus.SC_HTTP_VERSION_NOT_SUPPORTED);
   331         } else if (ex instanceof ProtocolException) {
   332             response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
   333         } else {
   334             response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
   335         }
   336         byte[] msg = EncodingUtils.getAsciiBytes(ex.getMessage());
   337         ByteArrayEntity entity = new ByteArrayEntity(msg);
   338         entity.setContentType("text/plain; charset=US-ASCII");
   339         response.setEntity(entity);
   340     }
   342     /**
   343      * The default implementation of this method attempts to resolve an
   344      * {@link HttpRequestHandler} for the request URI of the given request
   345      * and, if found, executes its
   346      * {@link HttpRequestHandler#handle(HttpRequest, HttpResponse, HttpContext)}
   347      * method.
   348      * <p>
   349      * Super-classes can override this method in order to provide a custom
   350      * implementation of the request processing logic.
   351      *
   352      * @param request the HTTP request.
   353      * @param response the HTTP response.
   354      * @param context the execution context.
   355      * @throws IOException in case of an I/O error.
   356      * @throws HttpException in case of HTTP protocol violation or a processing
   357      *   problem.
   358      */
   359     protected void doService(
   360             final HttpRequest request,
   361             final HttpResponse response,
   362             final HttpContext context) throws HttpException, IOException {
   363         HttpRequestHandler handler = null;
   364         if (this.handlerResolver != null) {
   365             String requestURI = request.getRequestLine().getUri();
   366             handler = this.handlerResolver.lookup(requestURI);
   367         }
   368         if (handler != null) {
   369             handler.handle(request, response, context);
   370         } else {
   371             response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED);
   372         }
   373     }
   375 }

mercurial