Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * JBoss, Home of Professional Open Source.
    * Copyright 2012 Red Hat, Inc., and individual contributors
    * as indicated by the @author tags.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package org.apache.coyote.http11;
  
  import java.net.Socket;
  import java.util.Locale;
  
Processes HTTP requests.

Author(s):
Remy Maucherat
  
  public class Http11Processor implements ActionHook {
  
  
      protected static final boolean CHUNK_ON_CLOSE = 
          Boolean.valueOf(System.getProperty("org.apache.coyote.http11.Http11Processor.CHUNK_ON_CLOSE""false")).booleanValue();
      
      // ------------------------------------------------------------ Constructor
  
  
      public Http11Processor(int headerBufferSizeJIoEndpoint endpoint) {
  
          this. = endpoint;
          
           = new Request();
           = new InternalInputBuffer(headerBufferSize);
          .setInputBuffer();
  
           = new Response();
          .setHook(this);
           = new InternalOutputBuffer(headerBufferSize);
          .setResponse();
  
          initializeFilters();
  
          // Cause loading of HexUtils
          int foo = .[0];
  
          // Cause loading of FastHttpDateFormat
          FastHttpDateFormat.getCurrentDate();
  
      }
  
  
      // ----------------------------------------------------- Instance Variables
  

    
Associated adapter.
 
     protected Adapter adapter = null;


    
Request object.
 
     protected Request request = null;


    
Response object.
 
     protected Response response = null;


    
Input.
 
     protected InternalInputBuffer inputBuffer = null;


    
Output.
 
     protected InternalOutputBuffer outputBuffer = null;


    
Error flag.
 
     protected boolean error = false;


    
Keep-alive.
 
     protected boolean keepAlive = true;


    
HTTP/1.1 flag.
 
     protected boolean http11 = true;


    
HTTP/0.9 flag.
 
     protected boolean http09 = false;


    
Content delimitator for the request (if false, the connection will be closed at the end of the request).
 
     protected boolean contentDelimitation = true;


    
Is there an expectation ?
 
     protected boolean expectation = false;


    
List of restricted user agents.
 
     protected Pattern[] restrictedUserAgents = null;


    
Maximum number of Keep-Alive requests to honor.
 
     protected int maxKeepAliveRequests = -1;

    
The number of seconds Tomcat will wait for a subsequent request before closing the connection.
 
     protected int keepAliveTimeout = -1;


    
SSL information.
 
     protected SSLSupport sslSupport;


    
Socket associated with the current connection.
 
     protected Socket socket;


    
Remote Address associated with the current connection.
 
     protected String remoteAddr = null;


    
Remote Host associated with the current connection.
 
     protected String remoteHost = null;


    
Local Host associated with the current connection.
 
     protected String localName = null;



    
Local port to which the socket is connected
 
     protected int localPort = -1;


    
Remote port to which the socket is connected
 
     protected int remotePort = -1;


    
The local Host address.
 
     protected String localAddr = null;


    
Flag to disable setting a different time-out on uploads.
 
     protected boolean disableUploadTimeout = true;


    
Allowed compression level.
 
     protected int compressionLevel = 0;


    
Minimum contentsize to make compression.
 
     protected int compressionMinSize = 2048;


    
Socket buffering.
 
     protected int socketBuffer = -1;


    
Max saved post size.
 
     protected int maxSavePostSize = 4 * 1024;


    
List of user agents to not use gzip with
 
     protected Pattern noCompressionUserAgents[] = null;

    
List of MIMES which could be gzipped
 
     protected String[] compressableMimeTypes =
     { "text/html""text/xml""text/plain" };


    
Host name (used to avoid useless B2C conversion on the host name).
 
     protected char[] hostNameC = new char[0];


    
Associated endpoint.
 
     protected JIoEndpoint endpoint;


    
Allow a customized the server header for the tin-foil hat folks.
 
     protected String server = null;

    
    
Event used.
 
     protected boolean event = false;


    
True if a resume has been requested.
 
     protected boolean resumeNotification = false;


    
Event processing.
 
     protected boolean eventProcessing = true;
     public void startProcessing() {  = true; }
     public void endProcessing() {  = false; }
 
 
     // ------------------------------------------------------------- Properties
 

    
Return compression level.
 
     public String getCompression() {
         switch () {
         case 0:
             return "off";
         case 1:
             return "on";
         case 2:
             return "force";
         }
         return "off";
     }


    
Set compression level.
 
     public void setCompression(String compression) {
         if (compression.equals("on")) {
             this. = 1;
         } else if (compression.equals("force")) {
             this. = 2;
         } else if (compression.equals("off")) {
             this. = 0;
         } else {
             try {
                 // Try to parse compression as an int, which would give the
                 // minimum compression size
                  = Integer.parseInt(compression);
                 this. = 1;
             } catch (Exception e) {
                 this. = 0;
             }
         }
     }

    
Set Minimum size to trigger compression.
 
     public void setCompressionMinSize(int compressionMinSize) {
         this. = compressionMinSize;
     }


    
Add user-agent for which gzip compression didn't works The user agent String given will be exactly matched to the user-agent header submitted by the client.

Parameters:
userAgent user-agent string
 
     public void addNoCompressionUserAgent(String userAgent) {
         try {
             Pattern nRule = Pattern.compile(userAgent);
              =
                 addREArray(nRule);
         } catch (PatternSyntaxException pse) {
             ..errorParsingRegexp(userAgentpse);
         }
     }


    
Set no compression user agent list (this method is best when used with a large number of connectors, where it would be better to have all of them referenced a single array).
 
     public void setNoCompressionUserAgents(Pattern[] noCompressionUserAgents) {
         this. = noCompressionUserAgents;
     }


    
Set no compression user agent list. List contains users agents separated by ',' : ie: "gorilla,desesplorer,tigrus"
 
     public void setNoCompressionUserAgents(String noCompressionUserAgents) {
         if (noCompressionUserAgents != null) {
             StringTokenizer st = new StringTokenizer(noCompressionUserAgents",");
 
             while (st.hasMoreTokens()) {
                 addNoCompressionUserAgent(st.nextToken().trim());
             }
         }
     }

    
Add a mime-type which will be compressable The mime-type String will be exactly matched in the response mime-type header .

Parameters:
mimeType mime-type string
 
     public void addCompressableMimeType(String mimeType) {
          =
             addStringArray(mimeType);
     }


    
Set compressable mime-type list (this method is best when used with a large number of connectors, where it would be better to have all of them referenced a single array).
 
     public void setCompressableMimeTypes(String[] compressableMimeTypes) {
         this. = compressableMimeTypes;
     }


    
Set compressable mime-type list List contains users agents separated by ',' : ie: "text/html,text/xml,text/plain"
 
     public void setCompressableMimeTypes(String compressableMimeTypes) {
         if (compressableMimeTypes != null) {
             this. = null;
             StringTokenizer st = new StringTokenizer(compressableMimeTypes",");
             while (st.hasMoreTokens()) {
                 addCompressableMimeType(st.nextToken().trim());
             }
         }
     }


    
Return the list of restricted user agents.
 
     public String[] findCompressableMimeTypes() {
         return ();
     }


    
Timeout.
 
     protected int timeout = -1;
     public void setTimeout(int timeout) { this. = timeout; }
     public int getTimeout() { return ; }
 
 
     // --------------------------------------------------------- Public Methods
 

    
Add input or output filter.

Parameters:
className class name of the filter
 
     protected void addFilter(String className) {
         try {
             Class<?> clazz = Class.forName(className);
             Object obj = clazz.newInstance();
             if (obj instanceof InputFilter) {
                 .addFilter((InputFilterobj);
             } else if (obj instanceof OutputFilter) {
                 .addFilter((OutputFilterobj);
             } else {
                 ..unknownFilter(className);
             }
         } catch (Exception e) {
             ..errorInitializingFilter(classNamee);
         }
     }


    
General use method

Parameters:
sArray the StringArray
value string
 
     private String[] addStringArray(String sArray[], String value) {
         String[] result = null;
         if (sArray == null) {
             result = new String[1];
             result[0] = value;
         }
         else {
             result = new String[sArray.length + 1];
             for (int i = 0; i < sArray.lengthi++)
                 result[i] = sArray[i];
             result[sArray.length] = value;
         }
         return result;
     }


    
General use method

Parameters:
rArray the REArray
value Obj
 
     private Pattern[] addREArray(Pattern rArray[], Pattern value) {
         Pattern[] result = null;
         if (rArray == null) {
             result = new Pattern[1];
             result[0] = value;
         }
         else {
             result = new Pattern[rArray.length + 1];
             for (int i = 0; i < rArray.lengthi++)
                 result[i] = rArray[i];
             result[rArray.length] = value;
         }
         return result;
     }


    
Checks if any entry in the string array starts with the specified value

Parameters:
sArray the StringArray
value string
 
     private boolean startsWithStringArray(String sArray[], String value) {
         if (value == null)
            return false;
         for (int i = 0; i < sArray.lengthi++) {
             if (value.startsWith(sArray[i])) {
                 return true;
             }
         }
         return false;
     }


    
Add restricted user-agent (which will downgrade the connector to HTTP/1.0 mode). The user agent String given will be matched via regexp to the user-agent header submitted by the client.

Parameters:
userAgent user-agent string
 
     public void addRestrictedUserAgent(String userAgent) {
         try {
             Pattern nRule = Pattern.compile(userAgent);
              = addREArray(nRule);
         } catch (PatternSyntaxException pse) {
             ..errorParsingRegexp(userAgentpse);
         }
     }


    
Set restricted user agent list (this method is best when used with a large number of connectors, where it would be better to have all of them referenced a single array).
 
     public void setRestrictedUserAgents(Pattern[] restrictedUserAgents) {
         this. = restrictedUserAgents;
     }


    
Set restricted user agent list (which will downgrade the connector to HTTP/1.0 mode). List contains users agents separated by ',' : ie: "gorilla,desesplorer,tigrus"
 
     public void setRestrictedUserAgents(String restrictedUserAgents) {
         if (restrictedUserAgents != null) {
             StringTokenizer st =
                 new StringTokenizer(restrictedUserAgents",");
             while (st.hasMoreTokens()) {
                 addRestrictedUserAgent(st.nextToken().trim());
             }
         }
     }


    
Return the list of restricted user agents.
 
     public String[] findRestrictedUserAgents() {
         String[] sarr = new String [.];
 
         for (int i = 0; i < .i++)
             sarr[i] = [i].toString();
 
         return (sarr);
     }


    
Set the maximum number of Keep-Alive requests to honor. This is to safeguard from DoS attacks. Setting to a negative value disables the check.
 
     public void setMaxKeepAliveRequests(int mkar) {
          = mkar;
     }


    
Return the number of Keep-Alive requests that we will honor.
 
     public int getMaxKeepAliveRequests() {
         return ;
     }

    
Set the Keep-Alive timeout.
 
     public void setKeepAliveTimeout(int timeout) {
          = timeout;
     }


    
Return the number Keep-Alive timeout.
 
     public int getKeepAliveTimeout() {
         return ;
     }


    
Set the maximum size of a POST which will be buffered in SSL mode.
 
     public void setMaxSavePostSize(int msps) {
          = msps;
     }


    
Return the maximum size of a POST which will be buffered in SSL mode.
 
     public int getMaxSavePostSize() {
         return ;
     }


    
Set the SSL information for this HTTP connection.
 
     public void setSSLSupport(SSLSupport sslSupport) {
         this. = sslSupport;
     }


    
Set the flag to control upload time-outs.
 
     public void setDisableUploadTimeout(boolean isDisabled) {
          = isDisabled;
     }

    
Get the flag that controls upload time-outs.
 
     public boolean getDisableUploadTimeout() {
         return ;
     }
 
     public boolean getResumeNotification() {
         return ;
     }
    

    
Set the socket buffer flag.
 
     public void setSocketBuffer(int socketBuffer) {
         this. = socketBuffer;
         .setSocketBuffer(socketBuffer);
     }

    
Get the socket buffer flag.
 
     public int getSocketBuffer() {
         return ;
     }


    
Set the server header name.
 
     public void setServerString server ) {
         if (server==null || server.equals("")) {
             this. = null;
         } else {
             this. = server;
         }
     }

    
Get the server header name.
 
     public String getServer() {
         return ;
     }


    
Get the request associated with this processor.

Returns:
The request
 
     public Request getRequest() {
         return ;
     }
 
     public SocketState event(SocketStatus status)
     throws IOException {
 
         RequestInfo rp = .getRequestProcessor();
         try {
             if (status == .) {
                 // The resume notification is now done
                  = false;
             } else if (status == .) {
                 // Set error flag right away
                  = true;
             }
             rp.setStage(....);
              = !.event(status);
         } catch (InterruptedIOException e) {
              = true;
         } catch (Throwable t) {
             ..errorProcessingRequest(t);
             // 500 - Internal Server Error
             .setStatus(500);
              = true;
         }
 
 
         if () {
             .nextRequest();
             .nextRequest();
             recycle();
             return .;
         } else if (!) {
             endRequest();
             boolean pipelined = .nextRequest();
             .nextRequest();
             recycle();
             return (pipelined || !) ? . : .;
         } else {
             return .;
         }
     }

    
Process pipelined HTTP requests on the specified socket.

Parameters:
socket Socket from which the HTTP requests will be read and the HTTP responses will be written.
Throws:
java.io.IOException error during an I/O operation
 
     public SocketState process(Socket socket)
         throws IOException {
         RequestInfo rp = .getRequestProcessor();
 
         // Set the remote address
          = null;
          = null;
          = null;
          = null;
          = -1;
          = -1;
 
         // Setting up the I/O
         this. = socket;
         .setInputStream(socket.getInputStream());
         .setOutputStream(socket.getOutputStream());
 
         // Error flag
          = false;
          = true;
 
         int keepAliveLeft = ;
         int soTimeout = socket.getSoTimeout();
 
         int threadRatio = (.getCurrentThreadsBusy() * 100)
                 / .getMaxThreads();
         if (threadRatio > 75) {
             keepAliveLeft = 1;
         }
         
         boolean keptAlive = false;
 
         while (! &&  && !) {
 
             // Parsing the request header
             try {
                 if (keptAlive) {
                     if ( > 0) {
                         socket.setSoTimeout();
                     } else if (soTimeout > 0) {
                         socket.setSoTimeout(soTimeout);
                     }
                 }
                 .parseRequestLine();
                 .setStartTime(System.currentTimeMillis());
                 keptAlive = true;
                 if (! && soTimeout > 0) {
                     socket.setSoTimeout(soTimeout);
                 }
                 .parseHeaders();
             } catch (IOException e) {
                  = true;
                 break;
             } catch (Throwable t) {
                 ..errorParsingHeader(t);
                 // 400 - Bad Request
                 .setStatus(400);
                  = true;
             }
 
             // Setting up filters, and parse some request headers
             rp.setStage(....);
             try {
                 prepareRequest();
             } catch (Throwable t) {
                 ..errorPreparingRequest(t);
                 // 400 - Internal Server Error
                 .setStatus(400);
                  = true;
             }
 
             if ( > 0 && --keepAliveLeft == 0)
                  = false;
 
             // Process the request in the adapter
             if (!) {
                 try {
                     rp.setStage(....);
                     .service();
                     // Handle when the response was committed before a serious
                     // error occurred.  Throwing a ServletException should both
                     // set the status to 500 and set the errorException.
                     // If we fail here, then the response is likely already
                     // committed, so we can't try and set headers.
                     if( && !) { // Avoid checking twice.
                          = .getErrorException() != null ||
                                 statusDropsConnection(.getStatus());
                     }
 
                 } catch (InterruptedIOException e) {
                      = true;
                 } catch (Throwable t) {
                     ..errorProcessingRequest(t);
                     // 500 - Internal Server Error
                     .setStatus(500);
                      = true;
                 }
             }
 
             // Finish the handling of the request
             if () {
                 // If there is an unspecified error, the connection will be closed
                 .setSwallowInput(false);
             }
             if (!) {
                 endRequest();
             }
 
             // If there was an error, make sure the request is counted as
             // and error, and update the statistics counter
             if () {
                 .setStatus(500);
             }
             .updateCounters();
 
             if (!) {
                 // Next request
                 .nextRequest();
                 .nextRequest();
             }
 
             rp.setStage(....);
 
         }
 
 
         if () {
             if () {
                 .nextRequest();
                 .nextRequest();
                 recycle();
                 return .;
             } else {
                  = false;
                 return .;
             }
         } else {
             recycle();
             return .;
         }
 
     }
 
 
     public void endRequest() {
         
         // Finish the handling of the request
         try {
             .endRequest();
         } catch (IOException e) {
              = true;
         } catch (Throwable t) {
             ..errorFinishingRequest(t);
             // 500 - Internal Server Error
             .setStatus(500);
              = true;
         }
         try {
             .endRequest();
         } catch (IOException e) {
              = true;
         } catch (Throwable t) {
             ..errorFinishingResponse(t);
              = true;
         }
 
     }
     
     
     public void recycle() {
         .recycle();
         .recycle();
         this. = null;
          = null;
          = -1;
          = false;
          = true;
     }
 
 
     // ----------------------------------------------------- ActionHook Methods
 

    
Send an action to the connector.

Parameters:
actionCode Type of the action
param Action parameter
 
     public void action(ActionCode actionCodeObject param) {
 
         if (actionCode == .) {
             // Commit current response
 
             if (.isCommitted())
                 return;
 
             // Validate and write response headers
             prepareResponse();
             try {
                 .commit();
             } catch (IOException e) {
                 // Set error flag
                  = true;
             }
 
         } else if (actionCode == .) {
 
             // Acknowlege request
 
             // Send a 100 status back if it makes sense (response not committed
             // yet, and client specified an expectation for 100-continue)
 
             if ((.isCommitted()) || !)
                 return;
 
             .setSwallowInput(true);
             try {
                 .sendAck();
             } catch (IOException e) {
                 // Set error flag
                  = true;
             }
        } else if (actionCode == .) {
            try {
                .flush();
            } catch (IOException e) {
                // Set error flag
                 = true;
                .setErrorException(e);
            }
        } else if (actionCode == .) {
            // Close
            // End the processing of the current request, and stop any further
            // transactions with the client
            try {
                .endRequest();
            } catch (IOException e) {
                // Set error flag
                 = true;
            }
        } else if (actionCode == .) {
            // Do nothing
        } else if (actionCode == . ) {
            try {
                if ( != null) {
                    Object sslO = .getCipherSuite();
                    if (sslO != null)
                        .setAttribute
                            (......sslO);
                    sslO = .getPeerCertificateChain(false);
                    if (sslO != null)
                        .setAttribute
                            (......sslO);
                    sslO = .getKeySize();
                    if (sslO != null)
                        .setAttribute
                            (......sslO);
                    sslO = .getSessionId();
                    if (sslO != null)
                        .setAttribute
                            (......sslO);
                }
            } catch (Exception e) {
                ..errorGettingSslAttributes(e);
            }
        } else if (actionCode == .) {
            if (( == null) && ( != null)) {
                InetAddress inetAddr = .getInetAddress();
                if (inetAddr != null) {
                     = inetAddr.getHostAddress();
                }
            }
            .remoteAddr().setString();
        } else if (actionCode == .) {
            if (( == null) && ( != null)) {
                InetAddress inetAddr = .getLocalAddress();
                if (inetAddr != null) {
                     = inetAddr.getHostName();
                }
            }
            .localName().setString();
        } else if (actionCode == .) {
            if (( == null) && ( != null)) {
                InetAddress inetAddr = .getInetAddress();
                if (inetAddr != null) {
                     = inetAddr.getHostName();
                }
                if( == null) {
                    if( != null) {
                         = ;
                    } else { // all we can do is punt
                        .remoteHost().recycle();
                    }
                }
            }
            .remoteHost().setString();
        } else if (actionCode == .) {
            if ( == null)
                = .getLocalAddress().getHostAddress();
            .localAddr().setString();
        } else if (actionCode == .) {
            if (( == -1 ) && ( !=null)) {
                 = .getPort();
            }
            .setRemotePort();
        } else if (actionCode == .) {
            if (( == -1 ) && ( !=null)) {
                 = .getLocalPort();
            }
            .setLocalPort();
        } else if (actionCode == .) {
            if != null) {
                // Consume and buffer the request body, so that it does not
                // interfere with the client's handshake messages
                if ( != 0) {
                    BufferedInputFilter buffredInputFilter = new BufferedInputFilter();
                    buffredInputFilter.setLimit();
                    .addActiveFilter(buffredInputFilter);
                }
                try {
                    Object sslO = .getPeerCertificateChain(true);
                    ifsslO != null) {
                        .setAttribute
                            (......sslO);
                    }
                } catch (Exception e) {
                    ..errorGettingSslAttributes(e);
                }
            }
        } else if (actionCode == .) {
            ByteChunk body = (ByteChunkparam;
            
            InputFilter savedBody = new SavedRequestInputFilter(body);
            savedBody.setRequest();
            InternalInputBuffer internalBuffer = (InternalInputBuffer)
                .getInputBuffer();
            internalBuffer.addActiveFilter(savedBody);
        } else if (actionCode == .) {
             = true;
        } else if (actionCode == .) {
             = false;
        } else if (actionCode == .) {
            // No action needed
        } else if (actionCode == .) {
            // An event is being processed already: adding for resume will be done
            // when the socket gets back to the poller
            if (! && !) {
                .getEventPoller().add(truetrue);
            }
             = true;
        } else if (actionCode == .) {
             = ((Integerparam).intValue();
        }
    }
    // ------------------------------------------------------ Connector Methods


    
Set the associated adapter.

Parameters:
adapter the new adapter
    public void setAdapter(Adapter adapter) {
        this. = adapter;
    }


    
Get the associated adapter.

Returns:
the associated adapter
    public Adapter getAdapter() {
        return ;
    }
    // ------------------------------------------------------ Protected Methods


    
After reading the request headers, we have to setup the request filters.
    protected void prepareRequest() {
         = true;
         = false;
         = false;
         = false;
        if ( != null) {
            .scheme().setString("https");
        }
        MessageBytes protocolMB = .protocol();
        if (protocolMB.equals(.)) {
             = true;
            protocolMB.setString(.);
        } else if (protocolMB.equals(.)) {
             = false;
             = false;
            protocolMB.setString(.);
        } else if (protocolMB.equals("")) {
            // HTTP/0.9
             = true;
             = false;
             = false;
        } else {
            // Unsupported protocol
             = false;
             = true;
            // Send 505; Unsupported HTTP version
            .setStatus(505);
        }
        MessageBytes methodMB = .method();
        if (methodMB.equals(.)) {
            methodMB.setString(.);
        } else if (methodMB.equals(.)) {
            methodMB.setString(.);
        }
        MimeHeaders headers = .getMimeHeaders();
        // Check connection header
        MessageBytes connectionValueMB = headers.getValue("connection");
        if (connectionValueMB != null) {
            ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
            if (findBytes(connectionValueBC.) != -1) {
                 = false;
            } else if (findBytes(connectionValueBC,
                                 .) != -1) {
                 = true;
            }
        }
        MessageBytes expectMB = null;
        if ()
            expectMB = headers.getValue("expect");
        if ((expectMB != null)
            && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) {
            .setSwallowInput(false);
             = true;
        }
        // Check user-agent header
        if (( != null) && (() || ())) {
            MessageBytes userAgentValueMB = headers.getValue("user-agent");
            // Check in the restricted list, and adjust the http11
            // and keepAlive flags accordingly
            if(userAgentValueMB != null) {
                String userAgentValue = userAgentValueMB.toString();
                for (int i = 0; i < .i++) {
                    if ([i].matcher(userAgentValue).matches()) {
                         = false;
                         = false;
                        break;
                    }
                }
            }
        }
        // Check for a full URI (including protocol://host:port/)
        ByteChunk uriBC = .requestURI().getByteChunk();
        if (uriBC.startsWithIgnoreCase("http", 0)) {
            int pos = uriBC.indexOf("://", 0, 3, 4);
            int uriBCStart = uriBC.getStart();
            int slashPos = -1;
            if (pos != -1) {
                byte[] uriB = uriBC.getBytes();
                slashPos = uriBC.indexOf('/'pos + 3);
                if (slashPos == -1) {
                    slashPos = uriBC.getLength();
                    // Set URI as "/"
                    .requestURI().setBytes
                        (uriBuriBCStart + pos + 1, 1);
                } else {
                    .requestURI().setBytes
                        (uriBuriBCStart + slashPos,
                         uriBC.getLength() - slashPos);
                }
                MessageBytes hostMB = headers.setValue("host");
                hostMB.setBytes(uriBuriBCStart + pos + 3,
                                slashPos - pos - 3);
            }
        }
        // Input filter setup
        InputFilter[] inputFilters = .getFilters();
        // Parse transfer-encoding header
        MessageBytes transferEncodingValueMB = null;
        if ()
            transferEncodingValueMB = headers.getValue("transfer-encoding");
        if (transferEncodingValueMB != null) {
            String transferEncodingValue = transferEncodingValueMB.toString();
            // Parse the comma separated list. "identity" codings are ignored
            int startPos = 0;
            int commaPos = transferEncodingValue.indexOf(',');
            String encodingName = null;
            while (commaPos != -1) {
                encodingName = transferEncodingValue.substring
                    (startPoscommaPos).toLowerCase(.).trim();
                if (!addInputFilter(inputFiltersencodingName)) {
                    // Unsupported transfer encoding
                     = true;
                    // 501 - Unimplemented
                    .setStatus(501);
                }
                startPos = commaPos + 1;
                commaPos = transferEncodingValue.indexOf(','startPos);
            }
            encodingName = transferEncodingValue.substring(startPos)
                .toLowerCase(.).trim();
            if (!addInputFilter(inputFiltersencodingName)) {
                // Unsupported transfer encoding
                 = true;
                // 501 - Unimplemented
                .setStatus(501);
            }
        }
        // Parse content-length header
        long contentLength = .getContentLengthLong();
        if (contentLength >= 0) {
            if () {
                // contentDelimitation being true at this point indicates that
                // chunked encoding is being used but chunked encoding should
                // not be used with a content length. RFC 2616, section 4.4,
                // bullet 3 states Content-Length must be ignored in this case -
                // so remove it.
                headers.removeHeader("content-length");
                .setContentLength(-1);
            } else {
                .addActiveFilter(inputFilters[.]);
                 = true;
            }
        }
        MessageBytes valueMB = headers.getValue("host");
        // Check host header
       &