Mark,

Thanks for your explanation.

Fabian

On Thu, Jun 25, 2020 at 3:29 PM Mark Thomas <ma...@apache.org> wrote:

> Fabian,
>
> Tomcat's behaviour is as expected and as per spec.
>
> The content-length header is used to determine the end of the request
> body. HTTP/1.1 allows pipe-linign requests. Whatever bytes on the wire
> are seen next will be treated as the next request.
>
> Mark
>
>
> On 25/06/2020 23:08, Fabian Morgan wrote:
> > Hi --
> >
> > While testing various scenarios in Tomcat 9.0.30, I’ve found Tomcat
> returns
> > different responses when the same request is issued twice in a row.  I
> have
> > three such scenarios (all related) to illustrate.  I used Postman to
> issue
> > the requests.
> >
> > First, here is some environment information:
> >
> > Operating System: Mac OS Mojave 10.14.6
> >
> > Http Client: Postman 7.24.0
> >
> > Relevant Automatic/Hidden headers for Postman:
> >
> > Cache-Control: no-cache
> >
> > Accept: */*
> >
> > Accept-Encoding: gzip, deflate, br
> >
> > Connection: keep-alive
> >
> > Java version: 1.8.0_221
> >
> > All of these scenarios are on fresh install of Tomcat 9.0.30 with default
> > port of 8080.
> >
> > Note: In each of the following scenarios, the steps must be done fairly
> > quickly one right after the other with no delay.  Please also stop and
> > restart Tomcat in between each scenario.
> >
> > Steps for First Scenario:
> >
> >    1.
> >
> >    In Postman, issue PUT request to invalid url, such as
> >    http://localhost:8080/thisisnotvalid.  Ensure Content-Length header
> is
> >    sent with value 12345.  Ensure the request has a request body that is
> a
> >    file attached with size >= 26545 bytes.  In Postman, I marked it with
> >    binary radiobutton.  I receive response with 405 (Method Not Allowed)
> >    status and HTML in the body.
> >    2.
> >
> >    In Postman, issue GET request to http://localhost:8080/thisisnotvalid
> .
> >    Ensure Content-Length header is sent with value 12345.  The request
> must
> >    NOT have a body (in Postman I marked it with none radiobutton).  I
> receive
> >    response with 404 (Not Found) status and HTML in the body.
> >    3.
> >
> >    In Postman, issue GET request to http://localhost:8080/thisisnotvalid
> .
> >    Ensure Content-Length header is sent with value 12345.  Ensure the
> request
> >    has a request body that is a file attached with size >= 26545 bytes
> (yes on
> >    a GET request).  In Postman, I marked it with binary radiobutton.
> NOTE: I
> >    receive 400 (Bad Request) response and HTML in the body.  This is NOT
> >    expected.
> >    4.
> >
> >    Issue same request in (3) again, and now I receive response with 404
> >    (Not Found) status and HTML in the body as expected.  Continuing to
> issue
> >    the request again seems to return 404 response as expected hereafter.
> >
> >
> > Note that after step (3), I see the following exception trace in
> > catalina.out:
> >
> > org.apache.coyote.http11.Http11Processor.service Error parsing HTTP
> request
> > header
> >
> >  Note: further occurrences of HTTP request parsing errors will be logged
> at
> > DEBUG level.
> >
> > java.lang.IllegalArgumentException: Invalid character found in method
> name.
> > HTTP method names must be tokens
> >
> > at
> >
> org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:415)
> >
> > at
> >
> org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:260)
> >
> > at
> >
> org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
> >
> > at
> >
> org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
> >
> > at
> > org.apache.tomcat.util.net
> .NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598)
> >
> > at
> > org.apache.tomcat.util.net
> .SocketProcessorBase.run(SocketProcessorBase.java:49)
> >
> > at
> >
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
> >
> > at
> >
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
> >
> > at
> >
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> >
> > at java.lang.Thread.run(Thread.java:748)
> >
> > Steps for Second Scenario:
> >
> >    1.
> >
> >    In Postman, issue GET request to invalid url, such as
> >    http://localhost:8080/thisisnotvalid.  Ensure Content-Length header
> is
> >    sent with value 1.  Ensure the request has a request body that is a
> text
> >    file attached containing 4 a’s in it as the only content (yes on a GET
> >    request).  I receive response with 404 (Not Found) status and HTML in
> the
> >    body.
> >    2.
> >
> >    Issue same request in (1) again, and now the server responds with 501
> >    (Not Implemented) status and HTML in the body.  This is NOT expected.
> >    3.
> >
> >    Issue same request in (1) again, and now it responds again with 404
> >    error as expected. Continuing to issue the same request will continue
> to
> >    alternate server responding with 404 and 501.
> >
> >
> > Note: The alternating responses don’t occur when Content-Length header is
> > not present.
> >
> > Note: The following lines can be seen in localhost_access_log:
> >
> > 0:0:0:0:0:0:0:1 - - [25/Jun/2020:13:51:17 -0700] "GET /thisisnotvalid
> > HTTP/1.1" 404 723
> >
> > 0:0:0:0:0:0:0:1 - - [25/Jun/2020:13:51:18 -0700] "aaaGET /thisisnotvalid
> > HTTP/1.1" 501 731
> >
> > 0:0:0:0:0:0:0:1 - - [25/Jun/2020:13:51:21 -0700] "GET /thisisnotvalid
> > HTTP/1.1" 404 723
> >
> > 0:0:0:0:0:0:0:1 - - [25/Jun/2020:13:51:22 -0700] "aaaGET /thisisnotvalid
> > HTTP/1.1" 501 731
> >
> >
> > Steps for Third Scenario:
> >
> >    1.
> >
> >    In Postman, issue GET request to invalid url, such as
> >    http://localhost:8080/thisisnotvalid.  Ensure Content-Length header
> is
> >    sent with value 12345.  The request must NOT have a body (in Postman I
> >    marked it with none radiobutton).  I receive response with 404 (Not
> Found)
> >    status and HTML in the body.
> >    2.
> >
> >    Issue same request in (1) again, and now the server does not respond.
> >    This is NOT expected.
> >    3.
> >
> >    Issue same request in (1) again, and now it responds again with 404
> >    error as expected. Continuing to issue the same request will continue
> to
> >    alternate server not responding and server returning 404 error.
> >
> >
> > Note: The alternating responses don’t seem to occur when Content-Length
> > header is not present.
> >
> > I’ve debugged the code numerous times, and while not claiming to fully
> > understand it, the following proposed change seems to alleviate the
> > unexpected results from the scenarios above.
> >
> > Proposed change:
> >
> >    1.
> >
> >    In conf/server.xml, change the original 8080 Connector configuration
> to
> >    use a custom protocol class.
> >
> >    The original Connector configuration is:
> >    <Connector port="8080" protocol="HTTP/1.1"
> >
> >           connectionTimeout="20000"
> >
> >           redirectPort="8443" />
> >
> >
> > The updated Connector configuration:
> > <Connector port="8080"
> > protocol="org.apache.coyote.http11.MyHttp11Nio2Protocol"
> >
> >           connectionTimeout="20000" />
> >
> >
> >    1.
> >
> >    Create a Java web application with a module called mytomcat.  In the
> src
> >    folder, create org.apache.coyote.http11 package with three classes:
> >    MyHttp11InputBuffer, MyHttp11Nio2Protocol, and MyHttp11Processor.
> Note:
> >    The overridden endRequest() method in MyHttp11InputBuffer seems to
> >    alleviate the unexpected results.  Note that MyHttp11Processor is
> >    essentially the same as Http11Processor (it was decompiled by the IDE
> from
> >    the jar), except one difference: the inputBuffer in the constructor
> is set
> >    to an instance of MyHttp11InputBuffer.  The source for these files are
> >    below at the end of the message.
> >
> >    2.
> >
> >    Ensure the class files for the source files in step (2) get placed in
> >
> PATHTOAPACHE/apache-tomcat-9.0.30/webapps/reproducer/WEB-INF/mytomcat_classes.
> >    PATHTOAPACHE must be replaced with the parent directory of
> >    apache-tomcat-9.0.30 folder, and the folders in the path must be
> created as
> >    necessary.
> >    3.
> >
> >    Edit conf/catalina.properties to update common.loader property.  Add
> >
> "PATHTOAPACHE/apache-tomcat-9.0.30/webapps/reproducer/WEB-INF/mytomcat_classes"
> >    at the end and save.  PATHTOAPACHE must be substituted as in step (3).
> >    4.
> >
> >    Shutdown and restart Tomcat.
> >
> >
> > With the changes above, rerunning the scenarios now give expected
> results.
> >
> > Scenario One with proposed change:
> >
> >    1.
> >
> >    I receive response with 405 (Method Not Allowed) status and HTML in
> the
> >    body
> >    2.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >    3.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >    Note that this result is updated
> >    4.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >
> >
> > Scenario Two with proposed change:
> >
> >    1.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >    2.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >    Note that this result is updated
> >    3.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >
> >
> > Scenario Three with proposed change:
> >
> >    1.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >    2.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >    Note that this result is updated
> >    3.
> >
> >    I receive response with 404 (Not Found) status and HTML in the body.
> >
> >
> > Would you please give guidance on whether the scenarios outlined are
> indeed
> > unexpected, whether the proposed change is appropriate, etc?
> >
> > Thanks,
> >
> > Fabian
> >
> > ==========================
> >
> > Source file for MyHttp11InputBuffer:
> >
> > package org.apache.coyote.http11;
> >
> > import org.apache.coyote.Request;
> > import org.apache.tomcat.util.http.parser.HttpParser;
> >
> > import java.io.IOException;
> >
> > public class MyHttp11InputBuffer extends Http11InputBuffer {
> > private final MyHttp11Processor processor;
> >
> > public MyHttp11InputBuffer(MyHttp11Processor processor,
> > Request request,
> > int headerBufferSize,
> > boolean rejectIllegalHeaderName,
> > HttpParser httpParser) {
> > super(request, headerBufferSize, rejectIllegalHeaderName, httpParser);
> >
> > this.processor = processor;
> > }
> >
> > @Override
> > void endRequest() throws IOException {
> > getByteBuffer().limit(0).position(0);
> > }
> > }
> > ==========================
> >
> > Source file for MyHttp11Nio2Protocol:
> >
> > package org.apache.coyote.http11;
> >
> > import org.apache.coyote.Processor;
> >
> > public class MyHttp11Nio2Protocol extends Http11Nio2Protocol {
> >     @Override
> >     protected Processor createProcessor() {
> >         return new MyHttp11Processor(this, this.adapter);
> >     }
> > }
> >
> > ==========================
> >
> > Source file for MyHttp11Processor:
> >
> > //
> > // Source code recreated from a .class file by IntelliJ IDEA
> > // (powered by Fernflower decompiler)
> > //
> >
> > package org.apache.coyote.http11;
> >
> > import java.io.IOException;
> > import java.io.InterruptedIOException;
> > import java.nio.ByteBuffer;
> > import java.util.ArrayList;
> > import java.util.HashSet;
> > import java.util.Iterator;
> > import java.util.List;
> > import java.util.Set;
> > import java.util.regex.Pattern;
> > import org.apache.coyote.AbstractProcessor;
> > import org.apache.coyote.ActionCode;
> > import org.apache.coyote.Adapter;
> > import org.apache.coyote.ErrorState;
> > import org.apache.coyote.Request;
> > import org.apache.coyote.RequestInfo;
> > import org.apache.coyote.UpgradeProtocol;
> > import org.apache.coyote.UpgradeToken;
> > import org.apache.coyote.http11.filters.BufferedInputFilter;
> > import org.apache.coyote.http11.filters.ChunkedInputFilter;
> > import org.apache.coyote.http11.filters.ChunkedOutputFilter;
> > import org.apache.coyote.http11.filters.GzipOutputFilter;
> > import org.apache.coyote.http11.filters.IdentityInputFilter;
> > import org.apache.coyote.http11.filters.IdentityOutputFilter;
> > import org.apache.coyote.http11.filters.SavedRequestInputFilter;
> > import org.apache.coyote.http11.filters.VoidInputFilter;
> > import org.apache.coyote.http11.filters.VoidOutputFilter;
> > import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler;
> > import org.apache.juli.logging.Log;
> > import org.apache.juli.logging.LogFactory;
> > import org.apache.tomcat.ContextBind;
> > import org.apache.tomcat.InstanceManager;
> > import org.apache.tomcat.util.ExceptionUtils;
> > import org.apache.tomcat.util.buf.ByteChunk;
> > import org.apache.tomcat.util.buf.MessageBytes;
> > import org.apache.tomcat.util.http.FastHttpDateFormat;
> > import org.apache.tomcat.util.http.MimeHeaders;
> > import org.apache.tomcat.util.http.parser.HttpParser;
> > import org.apache.tomcat.util.http.parser.TokenList;
> > import org.apache.tomcat.util.log.UserDataHelper.Mode;
> > import org.apache.tomcat.util.net.SendfileDataBase;
> > import org.apache.tomcat.util.net.SendfileKeepAliveState;
> > import org.apache.tomcat.util.net.SendfileState;
> > import org.apache.tomcat.util.net.SocketWrapperBase;
> > import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
> > import org.apache.tomcat.util.res.StringManager;
> >
> > public class MyHttp11Processor extends AbstractProcessor {
> >     private static final Log log =
> LogFactory.getLog(Http11Processor.class);
> >     private static final StringManager sm =
> > StringManager.getManager(Http11Processor.class);
> >     private final AbstractHttp11Protocol<?> protocol;
> >     private final Http11InputBuffer inputBuffer;
> >     private final Http11OutputBuffer outputBuffer;
> >     private final HttpParser httpParser;
> >     private int pluggableFilterIndex = 2147483647;
> >     private volatile boolean keepAlive = true;
> >     private boolean openSocket = false;
> >     private boolean readComplete = true;
> >     private boolean http11 = true;
> >     private boolean http09 = false;
> >     private boolean contentDelimitation = true;
> >     private UpgradeToken upgradeToken = null;
> >     private SendfileDataBase sendfileData = null;
> >
> >     public MyHttp11Processor(AbstractHttp11Protocol<?> protocol, Adapter
> > adapter) {
> >         super(adapter);
> >         this.protocol = protocol;
> >         this.httpParser = new HttpParser(protocol.getRelaxedPathChars(),
> > protocol.getRelaxedQueryChars());
> >         this.inputBuffer = new MyHttp11InputBuffer(this, this.request,
> > protocol.getMaxHttpHeaderSize(), protocol.getRejectIllegalHeaderName(),
> > this.httpParser);
> >         this.request.setInputBuffer(this.inputBuffer);
> >         this.outputBuffer = new Http11OutputBuffer(this.response,
> > protocol.getMaxHttpHeaderSize());
> >         this.response.setOutputBuffer(this.outputBuffer);
> >         this.inputBuffer.addFilter(new
> > IdentityInputFilter(protocol.getMaxSwallowSize()));
> >         this.outputBuffer.addFilter(new IdentityOutputFilter());
> >         this.inputBuffer.addFilter(new
> > ChunkedInputFilter(protocol.getMaxTrailerSize(),
> > protocol.getAllowedTrailerHeadersInternal(),
> > protocol.getMaxExtensionSize(), protocol.getMaxSwallowSize()));
> >         this.outputBuffer.addFilter(new ChunkedOutputFilter());
> >         this.inputBuffer.addFilter(new VoidInputFilter());
> >         this.outputBuffer.addFilter(new VoidOutputFilter());
> >         this.inputBuffer.addFilter(new BufferedInputFilter());
> >         this.outputBuffer.addFilter(new GzipOutputFilter());
> >         this.pluggableFilterIndex = this.inputBuffer.getFilters().length;
> >     }
> >
> >     private static boolean statusDropsConnection(int status) {
> >         return status == 400 || status == 408 || status == 411 || status
> ==
> > 413 || status == 414 || status == 500 || status == 503 || status == 501;
> >     }
> >
> >     private void addInputFilter(InputFilter[] inputFilters, String
> > encodingName) {
> >         if (!encodingName.equals("identity")) {
> >             if (encodingName.equals("chunked")) {
> >                 this.inputBuffer.addActiveFilter(inputFilters[1]);
> >                 this.contentDelimitation = true;
> >             } else {
> >                 for(int i = this.pluggableFilterIndex; i <
> > inputFilters.length; ++i) {
> >                     if
> > (inputFilters[i].getEncodingName().toString().equals(encodingName)) {
> >
>  this.inputBuffer.addActiveFilter(inputFilters[i]);
> >                         return;
> >                     }
> >                 }
> >
> >                 this.response.setStatus(501);
> >                 this.setErrorState(ErrorState.CLOSE_CLEAN,
> (Throwable)null);
> >                 if (log.isDebugEnabled()) {
> >
> > log.debug(sm.getString("http11processor.request.prepare") + " Unsupported
> > transfer encoding [" + encodingName + "]");
> >                 }
> >             }
> >         }
> >
> >     }
> >
> >     public SocketState service(SocketWrapperBase<?> socketWrapper) throws
> > IOException {
> >         RequestInfo rp = this.request.getRequestProcessor();
> >         rp.setStage(1);
> >         this.setSocketWrapper(socketWrapper);
> >         this.keepAlive = true;
> >         this.openSocket = false;
> >         this.readComplete = true;
> >         boolean keptAlive = false;
> >
> >         SendfileState sendfileState;
> >         for(sendfileState = SendfileState.DONE;
> > !this.getErrorState().isError() && this.keepAlive && !this.isAsync() &&
> > this.upgradeToken == null && sendfileState == SendfileState.DONE &&
> > !this.protocol.isPaused(); sendfileState =
> > this.processSendfile(socketWrapper)) {
> >             try {
> >                 if (!this.inputBuffer.parseRequestLine(keptAlive,
> > this.protocol.getConnectionTimeout(),
> this.protocol.getKeepAliveTimeout()))
> > {
> >                     if (this.inputBuffer.getParsingRequestLinePhase() ==
> > -1) {
> >                         return SocketState.UPGRADING;
> >                     }
> >
> >                     if (this.handleIncompleteRequestLineRead()) {
> >                         break;
> >                     }
> >                 }
> >
> >                 if (this.protocol.isPaused()) {
> >                     this.response.setStatus(503);
> >                     this.setErrorState(ErrorState.CLOSE_CLEAN,
> > (Throwable)null);
> >                 } else {
> >                     keptAlive = true;
> >
> >
> this.request.getMimeHeaders().setLimit(this.protocol.getMaxHeaderCount());
> >                     if (!this.inputBuffer.parseHeaders()) {
> >                         this.openSocket = true;
> >                         this.readComplete = false;
> >                         break;
> >                     }
> >
> >                     if (!this.protocol.getDisableUploadTimeout()) {
> >
> >
> socketWrapper.setReadTimeout((long)this.protocol.getConnectionUploadTimeout());
> >                     }
> >                 }
> >             } catch (IOException var13) {
> >                 if (log.isDebugEnabled()) {
> >
>  log.debug(sm.getString("http11processor.header.parse"),
> > var13);
> >                 }
> >
> >                 this.setErrorState(ErrorState.CLOSE_CONNECTION_NOW,
> var13);
> >                 break;
> >             } catch (Throwable var14) {
> >                 ExceptionUtils.handleThrowable(var14);
> >                 Mode logMode = this.userDataHelper.getNextMode();
> >                 if (logMode != null) {
> >                     String message =
> > sm.getString("http11processor.header.parse");
> >                     switch(logMode) {
> >                         case INFO_THEN_DEBUG:
> >                             message = message +
> > sm.getString("http11processor.fallToDebug");
> >                         case INFO:
> >                             log.info(message, var14);
> >                             break;
> >                         case DEBUG:
> >                             log.debug(message, var14);
> >                     }
> >                 }
> >
> >                 this.response.setStatus(400);
> >                 this.setErrorState(ErrorState.CLOSE_CLEAN, var14);
> >             }
> >
> >             if (isConnectionToken(this.request.getMimeHeaders(),
> > "upgrade")) {
> >                 String requestedProtocol =
> > this.request.getHeader("Upgrade");
> >                 UpgradeProtocol upgradeProtocol =
> > this.protocol.getUpgradeProtocol(requestedProtocol);
> >                 if (upgradeProtocol != null &&
> > upgradeProtocol.accept(this.request)) {
> >                     this.response.setStatus(101);
> >                     this.response.setHeader("Connection", "Upgrade");
> >                     this.response.setHeader("Upgrade",
> requestedProtocol);
> >                     this.action(ActionCode.CLOSE, (Object)null);
> >                     this.getAdapter().log(this.request, this.response,
> 0L);
> >                     InternalHttpUpgradeHandler upgradeHandler =
> > upgradeProtocol.getInternalUpgradeHandler(socketWrapper,
> this.getAdapter(),
> > this.cloneRequest(this.request));
> >                     UpgradeToken upgradeToken = new
> > UpgradeToken(upgradeHandler, (ContextBind)null, (InstanceManager)null);
> >                     this.action(ActionCode.UPGRADE, upgradeToken);
> >                     return SocketState.UPGRADING;
> >                 }
> >             }
> >
> >             if (this.getErrorState().isIoAllowed()) {
> >                 rp.setStage(2);
> >
> >                 try {
> >                     this.prepareRequest();
> >                 } catch (Throwable var12) {
> >                     ExceptionUtils.handleThrowable(var12);
> >                     if (log.isDebugEnabled()) {
> >
> > log.debug(sm.getString("http11processor.request.prepare"), var12);
> >                     }
> >
> >                     this.response.setStatus(500);
> >                     this.setErrorState(ErrorState.CLOSE_CLEAN, var12);
> >                 }
> >             }
> >
> >             int maxKeepAliveRequests =
> > this.protocol.getMaxKeepAliveRequests();
> >             if (maxKeepAliveRequests == 1) {
> >                 this.keepAlive = false;
> >             } else if (maxKeepAliveRequests > 0 &&
> > socketWrapper.decrementKeepAlive() <= 0) {
> >                 this.keepAlive = false;
> >             }
> >
> >             if (this.getErrorState().isIoAllowed()) {
> >                 try {
> >                     rp.setStage(3);
> >                     this.getAdapter().service(this.request,
> this.response);
> >                     if (this.keepAlive && !this.getErrorState().isError()
> > && !this.isAsync() && statusDropsConnection(this.response.getStatus())) {
> >                         this.setErrorState(ErrorState.CLOSE_CLEAN,
> > (Throwable)null);
> >                     }
> >                 } catch (InterruptedIOException var9) {
> >                     this.setErrorState(ErrorState.CLOSE_CONNECTION_NOW,
> > var9);
> >                 } catch (HeadersTooLargeException var10) {
> >
> > log.error(sm.getString("http11processor.request.process"), var10);
> >                     if (this.response.isCommitted()) {
> >                         this.setErrorState(ErrorState.CLOSE_NOW, var10);
> >                     } else {
> >                         this.response.reset();
> >                         this.response.setStatus(500);
> >                         this.setErrorState(ErrorState.CLOSE_CLEAN,
> var10);
> >                         this.response.setHeader("Connection", "close");
> >                     }
> >                 } catch (Throwable var11) {
> >                     ExceptionUtils.handleThrowable(var11);
> >
> > log.error(sm.getString("http11processor.request.process"), var11);
> >                     this.response.setStatus(500);
> >                     this.setErrorState(ErrorState.CLOSE_CLEAN, var11);
> >                     this.getAdapter().log(this.request, this.response,
> 0L);
> >                 }
> >             }
> >
> >             rp.setStage(4);
> >             if (!this.isAsync()) {
> >                 this.endRequest();
> >             }
> >
> >             rp.setStage(5);
> >             if (this.getErrorState().isError()) {
> >                 this.response.setStatus(500);
> >             }
> >
> >             if (!this.isAsync() || this.getErrorState().isError()) {
> >                 this.request.updateCounters();
> >                 if (this.getErrorState().isIoAllowed()) {
> >                     this.inputBuffer.nextRequest();
> >                     this.outputBuffer.nextRequest();
> >                 }
> >             }
> >
> >             if (!this.protocol.getDisableUploadTimeout()) {
> >                 int connectionTimeout =
> > this.protocol.getConnectionTimeout();
> >                 if (connectionTimeout > 0) {
> >
>  socketWrapper.setReadTimeout((long)connectionTimeout);
> >                 } else {
> >                     socketWrapper.setReadTimeout(0L);
> >                 }
> >             }
> >
> >             rp.setStage(6);
> >         }
> >
> >         rp.setStage(7);
> >         if (!this.getErrorState().isError() &&
> !this.protocol.isPaused()) {
> >             if (this.isAsync()) {
> >                 return SocketState.LONG;
> >             } else if (this.isUpgrade()) {
> >                 return SocketState.UPGRADING;
> >             } else if (sendfileState == SendfileState.PENDING) {
> >                 return SocketState.SENDFILE;
> >             } else if (this.openSocket) {
> >                 return this.readComplete ? SocketState.OPEN :
> > SocketState.LONG;
> >             } else {
> >                 return SocketState.CLOSED;
> >             }
> >         } else {
> >             return SocketState.CLOSED;
> >         }
> >     }
> >
> >     protected final void setSocketWrapper(SocketWrapperBase<?>
> > socketWrapper) {
> >         super.setSocketWrapper(socketWrapper);
> >         this.inputBuffer.init(socketWrapper);
> >         this.outputBuffer.init(socketWrapper);
> >     }
> >
> >     private Request cloneRequest(Request source) throws IOException {
> >         Request dest = new Request();
> >         dest.decodedURI().duplicate(source.decodedURI());
> >         dest.method().duplicate(source.method());
> >         dest.getMimeHeaders().duplicate(source.getMimeHeaders());
> >         dest.requestURI().duplicate(source.requestURI());
> >         dest.queryString().duplicate(source.queryString());
> >         return dest;
> >     }
> >
> >     private boolean handleIncompleteRequestLineRead() {
> >         this.openSocket = true;
> >         if (this.inputBuffer.getParsingRequestLinePhase() > 1) {
> >             if (this.protocol.isPaused()) {
> >                 this.response.setStatus(503);
> >                 this.setErrorState(ErrorState.CLOSE_CLEAN,
> (Throwable)null);
> >                 return false;
> >             }
> >
> >             this.readComplete = false;
> >         }
> >
> >         return true;
> >     }
> >
> >     private void checkExpectationAndResponseStatus() {
> >         if (this.request.hasExpectation() && (this.response.getStatus() <
> > 200 || this.response.getStatus() > 299)) {
> >             this.inputBuffer.setSwallowInput(false);
> >             this.keepAlive = false;
> >         }
> >
> >     }
> >
> >     private void prepareRequest() throws IOException {
> >         this.http11 = true;
> >         this.http09 = false;
> >         this.contentDelimitation = false;
> >         if (this.protocol.isSSLEnabled()) {
> >             this.request.scheme().setString("https");
> >         }
> >
> >         MessageBytes protocolMB = this.request.protocol();
> >         if (protocolMB.equals("HTTP/1.1")) {
> >             protocolMB.setString("HTTP/1.1");
> >         } else if (protocolMB.equals("HTTP/1.0")) {
> >             this.http11 = false;
> >             this.keepAlive = false;
> >             protocolMB.setString("HTTP/1.0");
> >         } else if (protocolMB.equals("")) {
> >             this.http09 = true;
> >             this.http11 = false;
> >             this.keepAlive = false;
> >         } else {
> >             this.http11 = false;
> >             this.response.setStatus(505);
> >             this.setErrorState(ErrorState.CLOSE_CLEAN, (Throwable)null);
> >             if (log.isDebugEnabled()) {
> >
>  log.debug(sm.getString("http11processor.request.prepare") +
> > " Unsupported HTTP version \"" + protocolMB + "\"");
> >             }
> >         }
> >
> >         MimeHeaders headers = this.request.getMimeHeaders();
> >         MessageBytes connectionValueMB = headers.getValue("Connection");
> >         if (connectionValueMB != null && !connectionValueMB.isNull()) {
> >             Set<String> tokens = new HashSet();
> >             TokenList.parseTokenList(headers.values("Connection"),
> tokens);
> >             if (tokens.contains("close")) {
> >                 this.keepAlive = false;
> >             } else if (tokens.contains("keep-alive")) {
> >                 this.keepAlive = true;
> >             }
> >         }
> >
> >         if (this.http11) {
> >             MessageBytes expectMB = headers.getValue("expect");
> >             if (expectMB != null && !expectMB.isNull()) {
> >                 if
> > (expectMB.toString().trim().equalsIgnoreCase("100-continue")) {
> >                     this.inputBuffer.setSwallowInput(false);
> >                     this.request.setExpectation(true);
> >                 } else {
> >                     this.response.setStatus(417);
> >                     this.setErrorState(ErrorState.CLOSE_CLEAN,
> > (Throwable)null);
> >                 }
> >             }
> >         }
> >
> >         Pattern restrictedUserAgents =
> > this.protocol.getRestrictedUserAgentsPattern();
> >         MessageBytes hostValueMB;
> >         if (restrictedUserAgents != null && (this.http11 ||
> > this.keepAlive)) {
> >             hostValueMB = headers.getValue("user-agent");
> >             if (hostValueMB != null && !hostValueMB.isNull()) {
> >                 String userAgentValue = hostValueMB.toString();
> >                 if
> (restrictedUserAgents.matcher(userAgentValue).matches())
> > {
> >                     this.http11 = false;
> >                     this.keepAlive = false;
> >                 }
> >             }
> >         }
> >
> >         hostValueMB = null;
> >
> >         try {
> >             hostValueMB = headers.getUniqueValue("host");
> >         } catch (IllegalArgumentException var16) {
> >             this.badRequest("http11processor.request.multipleHosts");
> >         }
> >
> >         if (this.http11 && hostValueMB == null) {
> >             this.badRequest("http11processor.request.noHostHeader");
> >         }
> >
> >         ByteChunk uriBC = this.request.requestURI().getByteChunk();
> >         byte[] uriB = uriBC.getBytes();
> >         int pos;
> >         if (uriBC.startsWithIgnoreCase("http", 0)) {
> >             pos = 4;
> >             if (uriBC.startsWithIgnoreCase("s", pos)) {
> >                 ++pos;
> >             }
> >
> >             if (uriBC.startsWith("://", pos)) {
> >                 pos += 3;
> >                 int uriBCStart = uriBC.getStart();
> >                 int slashPos = uriBC.indexOf('/', pos);
> >                 int atPos = uriBC.indexOf('@', pos);
> >                 if (slashPos > -1 && atPos > slashPos) {
> >                     atPos = -1;
> >                 }
> >
> >                 if (slashPos == -1) {
> >                     slashPos = uriBC.getLength();
> >                     this.request.requestURI().setBytes(uriB, uriBCStart +
> > 6, 1);
> >                 } else {
> >                     this.request.requestURI().setBytes(uriB, uriBCStart +
> > slashPos, uriBC.getLength() - slashPos);
> >                 }
> >
> >                 if (atPos != -1) {
> >                     while(pos < atPos) {
> >                         byte c = uriB[uriBCStart + pos];
> >                         if (!HttpParser.isUserInfo(c)) {
> >
> > this.badRequest("http11processor.request.invalidUserInfo");
> >                             break;
> >                         }
> >
> >                         ++pos;
> >                     }
> >
> >                     pos = atPos + 1;
> >                 }
> >
> >                 if (this.http11) {
> >                     if (hostValueMB != null &&
> > !hostValueMB.getByteChunk().equals(uriB, uriBCStart + pos, slashPos -
> pos))
> > {
> >                         if (this.protocol.getAllowHostHeaderMismatch()) {
> >                             hostValueMB = headers.setValue("host");
> >                             hostValueMB.setBytes(uriB, uriBCStart + pos,
> > slashPos - pos);
> >                         } else {
> >
> > this.badRequest("http11processor.request.inconsistentHosts");
> >                         }
> >                     }
> >                 } else {
> >                     try {
> >                         hostValueMB = headers.setValue("host");
> >                         hostValueMB.setBytes(uriB, uriBCStart + pos,
> > slashPos - pos);
> >                     } catch (IllegalStateException var15) {
> >                     }
> >                 }
> >             } else {
> >                 this.badRequest("http11processor.request.invalidScheme");
> >             }
> >         }
> >
> >         for(pos = uriBC.getStart(); pos < uriBC.getEnd(); ++pos) {
> >             if (!this.httpParser.isAbsolutePathRelaxed(uriB[pos])) {
> >                 this.badRequest("http11processor.request.invalidUri");
> >                 break;
> >             }
> >         }
> >
> >         InputFilter[] inputFilters = this.inputBuffer.getFilters();
> >         if (this.http11) {
> >             MessageBytes transferEncodingValueMB =
> > headers.getValue("transfer-encoding");
> >             if (transferEncodingValueMB != null) {
> >                 List<String> encodingNames = new ArrayList();
> >
> > TokenList.parseTokenList(headers.values("transfer-encoding"),
> > encodingNames);
> >                 Iterator var24 = encodingNames.iterator();
> >
> >                 while(var24.hasNext()) {
> >                     String encodingName = (String)var24.next();
> >                     this.addInputFilter(inputFilters, encodingName);
> >                 }
> >             }
> >         }
> >
> >         long contentLength = -1L;
> >
> >         try {
> >             contentLength = this.request.getContentLengthLong();
> >         } catch (NumberFormatException var13) {
> >
> > this.badRequest("http11processor.request.nonNumericContentLength");
> >         } catch (IllegalArgumentException var14) {
> >
> > this.badRequest("http11processor.request.multipleContentLength");
> >         }
> >
> >         if (contentLength >= 0L) {
> >             if (this.contentDelimitation) {
> >                 headers.removeHeader("content-length");
> >                 this.request.setContentLength(-1L);
> >             } else {
> >                 this.inputBuffer.addActiveFilter(inputFilters[0]);
> >                 this.contentDelimitation = true;
> >             }
> >         }
> >
> >         this.parseHost(hostValueMB);
> >         if (!this.contentDelimitation) {
> >             this.inputBuffer.addActiveFilter(inputFilters[2]);
> >             this.contentDelimitation = true;
> >         }
> >
> >         if (!this.getErrorState().isIoAllowed()) {
> >             this.getAdapter().log(this.request, this.response, 0L);
> >         }
> >
> >     }
> >
> >     private void badRequest(String errorKey) {
> >         this.response.setStatus(400);
> >         this.setErrorState(ErrorState.CLOSE_CLEAN, (Throwable)null);
> >         if (log.isDebugEnabled()) {
> >             log.debug(sm.getString(errorKey));
> >         }
> >
> >     }
> >
> >     protected final void prepareResponse() throws IOException {
> >         boolean entityBody = true;
> >         this.contentDelimitation = false;
> >         OutputFilter[] outputFilters = this.outputBuffer.getFilters();
> >         if (this.http09) {
> >             this.outputBuffer.addActiveFilter(outputFilters[0]);
> >             this.outputBuffer.commit();
> >         } else {
> >             int statusCode = this.response.getStatus();
> >             if (statusCode < 200 || statusCode == 204 || statusCode ==
> 205
> > || statusCode == 304) {
> >                 this.outputBuffer.addActiveFilter(outputFilters[2]);
> >                 entityBody = false;
> >                 this.contentDelimitation = true;
> >                 if (statusCode == 205) {
> >                     this.response.setContentLength(0L);
> >                 } else {
> >                     this.response.setContentLength(-1L);
> >                 }
> >             }
> >
> >             MessageBytes methodMB = this.request.method();
> >             if (methodMB.equals("HEAD")) {
> >                 this.outputBuffer.addActiveFilter(outputFilters[2]);
> >                 this.contentDelimitation = true;
> >             }
> >
> >             if (this.protocol.getUseSendfile()) {
> >                 this.prepareSendfile(outputFilters);
> >             }
> >
> >             boolean useCompression = false;
> >             if (entityBody && this.sendfileData == null) {
> >                 useCompression =
> this.protocol.useCompression(this.request,
> > this.response);
> >             }
> >
> >             MimeHeaders headers = this.response.getMimeHeaders();
> >             if (entityBody || statusCode == 204) {
> >                 String contentType = this.response.getContentType();
> >                 if (contentType != null) {
> >
>  headers.setValue("Content-Type").setString(contentType);
> >                 }
> >
> >                 String contentLanguage =
> this.response.getContentLanguage();
> >                 if (contentLanguage != null) {
> >
> > headers.setValue("Content-Language").setString(contentLanguage);
> >                 }
> >             }
> >
> >             long contentLength = this.response.getContentLengthLong();
> >             boolean connectionClosePresent = isConnectionToken(headers,
> > "close");
> >             if (this.http11 && this.response.getTrailerFields() != null)
> {
> >                 this.outputBuffer.addActiveFilter(outputFilters[1]);
> >                 this.contentDelimitation = true;
> >
>  headers.addValue("Transfer-Encoding").setString("chunked");
> >             } else if (contentLength != -1L) {
> >
>  headers.setValue("Content-Length").setLong(contentLength);
> >                 this.outputBuffer.addActiveFilter(outputFilters[0]);
> >                 this.contentDelimitation = true;
> >             } else if (this.http11 && entityBody &&
> > !connectionClosePresent) {
> >                 this.outputBuffer.addActiveFilter(outputFilters[1]);
> >                 this.contentDelimitation = true;
> >
>  headers.addValue("Transfer-Encoding").setString("chunked");
> >             } else {
> >                 this.outputBuffer.addActiveFilter(outputFilters[0]);
> >             }
> >
> >             if (useCompression) {
> >                 this.outputBuffer.addActiveFilter(outputFilters[3]);
> >             }
> >
> >             if (headers.getValue("Date") == null) {
> >
> > headers.addValue("Date").setString(FastHttpDateFormat.getCurrentDate());
> >             }
> >
> >             if (entityBody && !this.contentDelimitation) {
> >                 this.keepAlive = false;
> >             }
> >
> >             this.checkExpectationAndResponseStatus();
> >             if (this.keepAlive && statusDropsConnection(statusCode)) {
> >                 this.keepAlive = false;
> >             }
> >
> >             int keepAliveTimeout;
> >             if (!this.keepAlive) {
> >                 if (!connectionClosePresent) {
> >                     headers.addValue("Connection").setString("close");
> >                 }
> >             } else if (!this.getErrorState().isError()) {
> >                 if (!this.http11) {
> >
>  headers.addValue("Connection").setString("keep-alive");
> >                 }
> >
> >                 if (this.protocol.getUseKeepAliveResponseHeader()) {
> >                     boolean connectionKeepAlivePresent =
> > isConnectionToken(this.request.getMimeHeaders(), "keep-alive");
> >                     if (connectionKeepAlivePresent) {
> >                         keepAliveTimeout =
> > this.protocol.getKeepAliveTimeout();
> >                         if (keepAliveTimeout > 0) {
> >                             String value = "timeout=" +
> > (long)keepAliveTimeout / 1000L;
> >
>  headers.setValue("Keep-Alive").setString(value);
> >                             if (this.http11) {
> >                                 MessageBytes connectionHeaderValue =
> > headers.getValue("Connection");
> >                                 if (connectionHeaderValue == null) {
> >
> > headers.addValue("Connection").setString("keep-alive");
> >                                 } else {
> >
> > connectionHeaderValue.setString(connectionHeaderValue.getString() + ", "
> +
> > "keep-alive");
> >                                 }
> >                             }
> >                         }
> >                     }
> >                 }
> >             }
> >
> >             String server = this.protocol.getServer();
> >             if (server == null) {
> >                 if (this.protocol.getServerRemoveAppProvidedValues()) {
> >                     headers.removeHeader("server");
> >                 }
> >             } else {
> >                 headers.setValue("Server").setString(server);
> >             }
> >
> >             try {
> >                 this.outputBuffer.sendStatus();
> >                 keepAliveTimeout = headers.size();
> >                 int i = 0;
> >
> >                 while(true) {
> >                     if (i >= keepAliveTimeout) {
> >                         this.outputBuffer.endHeaders();
> >                         break;
> >                     }
> >
> >                     this.outputBuffer.sendHeader(headers.getName(i),
> > headers.getValue(i));
> >                     ++i;
> >                 }
> >             } catch (Throwable var14) {
> >                 ExceptionUtils.handleThrowable(var14);
> >                 this.outputBuffer.resetHeaderBuffer();
> >                 throw var14;
> >             }
> >
> >             this.outputBuffer.commit();
> >         }
> >     }
> >
> >     private static boolean isConnectionToken(MimeHeaders headers, String
> > token) throws IOException {
> >         MessageBytes connection = headers.getValue("Connection");
> >         if (connection == null) {
> >             return false;
> >         } else {
> >             Set<String> tokens = new HashSet();
> >             TokenList.parseTokenList(headers.values("Connection"),
> tokens);
> >             return tokens.contains(token);
> >         }
> >     }
> >
> >     private void prepareSendfile(OutputFilter[] outputFilters) {
> >         String fileName =
> > (String)this.request.getAttribute("org.apache.tomcat.sendfile.filename");
> >         if (fileName == null) {
> >             this.sendfileData = null;
> >         } else {
> >             this.outputBuffer.addActiveFilter(outputFilters[2]);
> >             this.contentDelimitation = true;
> >             long pos =
> > (Long)this.request.getAttribute("org.apache.tomcat.sendfile.start");
> >             long end =
> > (Long)this.request.getAttribute("org.apache.tomcat.sendfile.end");
> >             this.sendfileData =
> > this.socketWrapper.createSendfileData(fileName, pos, end - pos);
> >         }
> >
> >     }
> >
> >     protected void populatePort() {
> >         this.request.action(ActionCode.REQ_LOCALPORT_ATTRIBUTE,
> > this.request);
> >         this.request.setServerPort(this.request.getLocalPort());
> >     }
> >
> >     protected boolean flushBufferedWrite() throws IOException {
> >         if (this.outputBuffer.hasDataToWrite() &&
> > this.outputBuffer.flushBuffer(false)) {
> >             this.outputBuffer.registerWriteInterest();
> >             return true;
> >         } else {
> >             return false;
> >         }
> >     }
> >
> >     protected SocketState dispatchEndRequest() {
> >         if (!this.keepAlive) {
> >             return SocketState.CLOSED;
> >         } else {
> >             this.endRequest();
> >             this.inputBuffer.nextRequest();
> >             this.outputBuffer.nextRequest();
> >             return this.socketWrapper.isReadPending() ? SocketState.LONG
> :
> > SocketState.OPEN;
> >         }
> >     }
> >
> >     protected Log getLog() {
> >         return log;
> >     }
> >
> >     private void endRequest() {
> >         if (this.getErrorState().isError()) {
> >             this.inputBuffer.setSwallowInput(false);
> >         } else {
> >             this.checkExpectationAndResponseStatus();
> >         }
> >
> >         if (this.getErrorState().isIoAllowed()) {
> >             try {
> >                 this.inputBuffer.endRequest();
> >             } catch (IOException var4) {
> >                 this.setErrorState(ErrorState.CLOSE_CONNECTION_NOW,
> var4);
> >             } catch (Throwable var5) {
> >                 ExceptionUtils.handleThrowable(var5);
> >                 this.response.setStatus(500);
> >                 this.setErrorState(ErrorState.CLOSE_NOW, var5);
> >                 log.error(sm.getString("http11processor.request.finish"),
> > var5);
> >             }
> >         }
> >
> >         if (this.getErrorState().isIoAllowed()) {
> >             try {
> >                 this.action(ActionCode.COMMIT, (Object)null);
> >                 this.outputBuffer.end();
> >             } catch (IOException var2) {
> >                 this.setErrorState(ErrorState.CLOSE_CONNECTION_NOW,
> var2);
> >             } catch (Throwable var3) {
> >                 ExceptionUtils.handleThrowable(var3);
> >                 this.setErrorState(ErrorState.CLOSE_NOW, var3);
> >
>  log.error(sm.getString("http11processor.response.finish"),
> > var3);
> >             }
> >         }
> >
> >     }
> >
> >     protected final void finishResponse() throws IOException {
> >         this.outputBuffer.end();
> >     }
> >
> >     protected final void ack() {
> >         if (!this.response.isCommitted() &&
> this.request.hasExpectation()) {
> >             this.inputBuffer.setSwallowInput(true);
> >
> >             try {
> >                 this.outputBuffer.sendAck();
> >             } catch (IOException var2) {
> >                 this.setErrorState(ErrorState.CLOSE_CONNECTION_NOW,
> var2);
> >             }
> >         }
> >
> >     }
> >
> >     protected final void flush() throws IOException {
> >         this.outputBuffer.flush();
> >     }
> >
> >     protected final int available(boolean doRead) {
> >         return this.inputBuffer.available(doRead);
> >     }
> >
> >     protected final void setRequestBody(ByteChunk body) {
> >         InputFilter savedBody = new SavedRequestInputFilter(body);
> >         Http11InputBuffer internalBuffer =
> > (Http11InputBuffer)this.request.getInputBuffer();
> >         internalBuffer.addActiveFilter(savedBody);
> >     }
> >
> >     protected final void setSwallowResponse() {
> >         this.outputBuffer.responseFinished = true;
> >     }
> >
> >     protected final void disableSwallowRequest() {
> >         this.inputBuffer.setSwallowInput(false);
> >     }
> >
> >     protected final void sslReHandShake() throws IOException {
> >         if (this.sslSupport != null) {
> >             InputFilter[] inputFilters = this.inputBuffer.getFilters();
> >
> >
> ((BufferedInputFilter)inputFilters[3]).setLimit(this.protocol.getMaxSavePostSize());
> >             this.inputBuffer.addActiveFilter(inputFilters[3]);
> >             this.socketWrapper.doClientAuth(this.sslSupport);
> >
> >             try {
> >                 Object sslO = this.sslSupport.getPeerCertificateChain();
> >                 if (sslO != null) {
> >
> > this.request.setAttribute("javax.servlet.request.X509Certificate", sslO);
> >                 }
> >             } catch (IOException var3) {
> >                 log.warn(sm.getString("http11processor.socket.ssl"),
> var3);
> >             }
> >         }
> >
> >     }
> >
> >     protected final boolean isRequestBodyFullyRead() {
> >         return this.inputBuffer.isFinished();
> >     }
> >
> >     protected final void registerReadInterest() {
> >         this.socketWrapper.registerReadInterest();
> >     }
> >
> >     protected final boolean isReadyForWrite() {
> >         return this.outputBuffer.isReady();
> >     }
> >
> >     public UpgradeToken getUpgradeToken() {
> >         return this.upgradeToken;
> >     }
> >
> >     protected final void doHttpUpgrade(UpgradeToken upgradeToken) {
> >         this.upgradeToken = upgradeToken;
> >         this.outputBuffer.responseFinished = true;
> >     }
> >
> >     public ByteBuffer getLeftoverInput() {
> >         return this.inputBuffer.getLeftover();
> >     }
> >
> >     public boolean isUpgrade() {
> >         return this.upgradeToken != null;
> >     }
> >
> >     protected boolean isTrailerFieldsReady() {
> >         return this.inputBuffer.isChunking() ?
> > this.inputBuffer.isFinished() : true;
> >     }
> >
> >     protected boolean isTrailerFieldsSupported() {
> >         if (!this.http11) {
> >             return false;
> >         } else {
> >             return !this.response.isCommitted() ? true :
> > this.outputBuffer.isChunking();
> >         }
> >     }
> >
> >     private SendfileState processSendfile(SocketWrapperBase<?>
> > socketWrapper) {
> >         this.openSocket = this.keepAlive;
> >         SendfileState result = SendfileState.DONE;
> >         if (this.sendfileData != null &&
> !this.getErrorState().isError()) {
> >             if (this.keepAlive) {
> >                 if (this.available(false) == 0) {
> >                     this.sendfileData.keepAliveState =
> > SendfileKeepAliveState.OPEN;
> >                 } else {
> >                     this.sendfileData.keepAliveState =
> > SendfileKeepAliveState.PIPELINED;
> >                 }
> >             } else {
> >                 this.sendfileData.keepAliveState =
> > SendfileKeepAliveState.NONE;
> >             }
> >
> >             result = socketWrapper.processSendfile(this.sendfileData);
> >             switch(result) {
> >                 case ERROR:
> >                     if (log.isDebugEnabled()) {
> >
> > log.debug(sm.getString("http11processor.sendfile.error"));
> >                     }
> >
> >                     this.setErrorState(ErrorState.CLOSE_CONNECTION_NOW,
> > (Throwable)null);
> >                 default:
> >                     this.sendfileData = null;
> >             }
> >         }
> >
> >         return result;
> >     }
> >
> >     public final void recycle() {
> >         this.getAdapter().checkRecycled(this.request, this.response);
> >         super.recycle();
> >         this.inputBuffer.recycle();
> >         this.outputBuffer.recycle();
> >         this.upgradeToken = null;
> >         this.socketWrapper = null;
> >         this.sendfileData = null;
> >         this.sslSupport = null;
> >     }
> >
> >     public void pause() {
> >     }
> > }
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>

Reply via email to