init
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.tomcat.util.net.AbstractJsseEndpoint;
|
||||
import org.apache.tomcat.util.net.openssl.OpenSSLImplementation;
|
||||
|
||||
public abstract class AbstractHttp11JsseProtocol<S>
|
||||
extends AbstractHttp11Protocol<S> {
|
||||
|
||||
public AbstractHttp11JsseProtocol(AbstractJsseEndpoint<S> endpoint) {
|
||||
super(endpoint);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected AbstractJsseEndpoint<S> getEndpoint() {
|
||||
// Over-ridden to add cast
|
||||
return (AbstractJsseEndpoint<S>) super.getEndpoint();
|
||||
}
|
||||
|
||||
|
||||
protected String getSslImplementationShortName() {
|
||||
if (OpenSSLImplementation.class.getName().equals(getSslImplementationName())) {
|
||||
return "openssl";
|
||||
}
|
||||
return "jsse";
|
||||
}
|
||||
|
||||
public String getSslImplementationName() { return getEndpoint().getSslImplementationName(); }
|
||||
public void setSslImplementationName(String s) { getEndpoint().setSslImplementationName(s); }
|
||||
|
||||
|
||||
public int getSniParseLimit() { return getEndpoint().getSniParseLimit(); }
|
||||
public void setSniParseLimit(int sniParseLimit) {
|
||||
getEndpoint().setSniParseLimit(sniParseLimit);
|
||||
}
|
||||
}
|
||||
1011
java/org/apache/coyote/http11/AbstractHttp11Protocol.java
Normal file
1011
java/org/apache/coyote/http11/AbstractHttp11Protocol.java
Normal file
File diff suppressed because it is too large
Load Diff
179
java/org/apache/coyote/http11/Constants.java
Normal file
179
java/org/apache/coyote/http11/Constants.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.tomcat.util.buf.ByteChunk;
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
|
||||
|
||||
|
||||
/**
|
||||
* CRLF.
|
||||
*/
|
||||
public static final String CRLF = "\r\n";
|
||||
|
||||
|
||||
/**
|
||||
* CR.
|
||||
*/
|
||||
public static final byte CR = (byte) '\r';
|
||||
|
||||
|
||||
/**
|
||||
* LF.
|
||||
*/
|
||||
public static final byte LF = (byte) '\n';
|
||||
|
||||
|
||||
/**
|
||||
* SP.
|
||||
*/
|
||||
public static final byte SP = (byte) ' ';
|
||||
|
||||
|
||||
/**
|
||||
* HT.
|
||||
*/
|
||||
public static final byte HT = (byte) '\t';
|
||||
|
||||
|
||||
/**
|
||||
* COLON.
|
||||
*/
|
||||
public static final byte COLON = (byte) ':';
|
||||
|
||||
|
||||
/**
|
||||
* SEMI_COLON.
|
||||
*/
|
||||
public static final byte SEMI_COLON = (byte) ';';
|
||||
|
||||
|
||||
/**
|
||||
* 'A'.
|
||||
*/
|
||||
public static final byte A = (byte) 'A';
|
||||
|
||||
|
||||
/**
|
||||
* 'a'.
|
||||
*/
|
||||
public static final byte a = (byte) 'a';
|
||||
|
||||
|
||||
/**
|
||||
* 'Z'.
|
||||
*/
|
||||
public static final byte Z = (byte) 'Z';
|
||||
|
||||
|
||||
/**
|
||||
* '?'.
|
||||
*/
|
||||
public static final byte QUESTION = (byte) '?';
|
||||
|
||||
|
||||
/**
|
||||
* Lower case offset.
|
||||
*/
|
||||
public static final byte LC_OFFSET = A - a;
|
||||
|
||||
|
||||
/* Various constant "strings" */
|
||||
public static final String CONNECTION = "Connection";
|
||||
public static final String CLOSE = "close";
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 10.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final byte[] CLOSE_BYTES = ByteChunk.convertToBytes(CLOSE);
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 10.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String KEEPALIVE = "keep-alive";
|
||||
public static final String KEEP_ALIVE_HEADER_VALUE_TOKEN = "keep-alive";
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 10.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final byte[] KEEPALIVE_BYTES = ByteChunk.convertToBytes(KEEPALIVE);
|
||||
public static final String CHUNKED = "chunked";
|
||||
/**
|
||||
* @deprecated This option will be removed in Tomcat 9. Reason phrase will
|
||||
* not be sent.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final byte[] ACK_BYTES_REASON =
|
||||
ByteChunk.convertToBytes("HTTP/1.1 100 Continue" + CRLF + CRLF);
|
||||
public static final byte[] ACK_BYTES = ByteChunk.convertToBytes("HTTP/1.1 100 " + CRLF + CRLF);
|
||||
public static final String TRANSFERENCODING = "Transfer-Encoding";
|
||||
public static final String KEEP_ALIVE_HEADER_NAME = "Keep-Alive";
|
||||
public static final byte[] _200_BYTES = ByteChunk.convertToBytes("200");
|
||||
public static final byte[] _400_BYTES = ByteChunk.convertToBytes("400");
|
||||
public static final byte[] _404_BYTES = ByteChunk.convertToBytes("404");
|
||||
|
||||
|
||||
/**
|
||||
* Identity filters (input and output).
|
||||
*/
|
||||
public static final int IDENTITY_FILTER = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Chunked filters (input and output).
|
||||
*/
|
||||
public static final int CHUNKED_FILTER = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Void filters (input and output).
|
||||
*/
|
||||
public static final int VOID_FILTER = 2;
|
||||
|
||||
|
||||
/**
|
||||
* GZIP filter (output).
|
||||
*/
|
||||
public static final int GZIP_FILTER = 3;
|
||||
|
||||
|
||||
/**
|
||||
* Buffered filter (input)
|
||||
*/
|
||||
public static final int BUFFERED_FILTER = 3;
|
||||
|
||||
|
||||
/**
|
||||
* HTTP/1.0.
|
||||
*/
|
||||
public static final String HTTP_10 = "HTTP/1.0";
|
||||
|
||||
|
||||
/**
|
||||
* HTTP/1.1.
|
||||
*/
|
||||
public static final String HTTP_11 = "HTTP/1.1";
|
||||
public static final byte[] HTTP_11_BYTES = ByteChunk.convertToBytes(HTTP_11);
|
||||
}
|
||||
42
java/org/apache/coyote/http11/HeadersTooLargeException.java
Normal file
42
java/org/apache/coyote/http11/HeadersTooLargeException.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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;
|
||||
|
||||
/**
|
||||
* Exception used to mark the specific error condition of the HTTP headers
|
||||
* exceeding the maximum permitted size.
|
||||
*/
|
||||
public class HeadersTooLargeException extends IllegalStateException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public HeadersTooLargeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public HeadersTooLargeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public HeadersTooLargeException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public HeadersTooLargeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
71
java/org/apache/coyote/http11/Http11AprProtocol.java
Normal file
71
java/org/apache/coyote/http11/Http11AprProtocol.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.AprEndpoint;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract the protocol implementation, including threading, etc.
|
||||
* Processor is single threaded and specific to stream-based protocols,
|
||||
* will not fit Jk protocols like JNI.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
* @author Costin Manolache
|
||||
*/
|
||||
public class Http11AprProtocol extends AbstractHttp11Protocol<Long> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(Http11AprProtocol.class);
|
||||
|
||||
public Http11AprProtocol() {
|
||||
super(new AprEndpoint());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Log getLog() { return log; }
|
||||
|
||||
@Override
|
||||
public boolean isAprRequired() {
|
||||
// Override since this protocol implementation requires the APR/native
|
||||
// library
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getPollTime() { return ((AprEndpoint)getEndpoint()).getPollTime(); }
|
||||
public void setPollTime(int pollTime) { ((AprEndpoint)getEndpoint()).setPollTime(pollTime); }
|
||||
|
||||
public int getSendfileSize() { return ((AprEndpoint)getEndpoint()).getSendfileSize(); }
|
||||
public void setSendfileSize(int sendfileSize) { ((AprEndpoint)getEndpoint()).setSendfileSize(sendfileSize); }
|
||||
|
||||
public boolean getDeferAccept() { return ((AprEndpoint)getEndpoint()).getDeferAccept(); }
|
||||
public void setDeferAccept(boolean deferAccept) { ((AprEndpoint)getEndpoint()).setDeferAccept(deferAccept); }
|
||||
|
||||
|
||||
// ----------------------------------------------------- JMX related methods
|
||||
|
||||
@Override
|
||||
protected String getNamePrefix() {
|
||||
if (isSSLEnabled()) {
|
||||
return ("https-openssl-apr");
|
||||
} else {
|
||||
return ("http-apr");
|
||||
}
|
||||
}
|
||||
}
|
||||
1156
java/org/apache/coyote/http11/Http11InputBuffer.java
Normal file
1156
java/org/apache/coyote/http11/Http11InputBuffer.java
Normal file
File diff suppressed because it is too large
Load Diff
52
java/org/apache/coyote/http11/Http11Nio2Protocol.java
Normal file
52
java/org/apache/coyote/http11/Http11Nio2Protocol.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.Nio2Channel;
|
||||
import org.apache.tomcat.util.net.Nio2Endpoint;
|
||||
|
||||
|
||||
/**
|
||||
* HTTP/1.1 protocol implementation using NIO2.
|
||||
*/
|
||||
public class Http11Nio2Protocol extends AbstractHttp11JsseProtocol<Nio2Channel> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(Http11Nio2Protocol.class);
|
||||
|
||||
|
||||
public Http11Nio2Protocol() {
|
||||
super(new Nio2Endpoint());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Log getLog() { return log; }
|
||||
|
||||
|
||||
// ----------------------------------------------------- JMX related methods
|
||||
|
||||
@Override
|
||||
protected String getNamePrefix() {
|
||||
if (isSSLEnabled()) {
|
||||
return ("https-" + getSslImplementationShortName()+ "-nio2");
|
||||
} else {
|
||||
return ("http-nio2");
|
||||
}
|
||||
}
|
||||
}
|
||||
84
java/org/apache/coyote/http11/Http11NioProtocol.java
Normal file
84
java/org/apache/coyote/http11/Http11NioProtocol.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.NioChannel;
|
||||
import org.apache.tomcat.util.net.NioEndpoint;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract the protocol implementation, including threading, etc.
|
||||
* Processor is single threaded and specific to stream-based protocols,
|
||||
* will not fit Jk protocols like JNI.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
* @author Costin Manolache
|
||||
*/
|
||||
public class Http11NioProtocol extends AbstractHttp11JsseProtocol<NioChannel> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(Http11NioProtocol.class);
|
||||
|
||||
|
||||
public Http11NioProtocol() {
|
||||
super(new NioEndpoint());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Log getLog() { return log; }
|
||||
|
||||
|
||||
// -------------------- Pool setup --------------------
|
||||
|
||||
public void setPollerThreadCount(int count) {
|
||||
((NioEndpoint)getEndpoint()).setPollerThreadCount(count);
|
||||
}
|
||||
|
||||
public int getPollerThreadCount() {
|
||||
return ((NioEndpoint)getEndpoint()).getPollerThreadCount();
|
||||
}
|
||||
|
||||
public void setSelectorTimeout(long timeout) {
|
||||
((NioEndpoint)getEndpoint()).setSelectorTimeout(timeout);
|
||||
}
|
||||
|
||||
public long getSelectorTimeout() {
|
||||
return ((NioEndpoint)getEndpoint()).getSelectorTimeout();
|
||||
}
|
||||
|
||||
public void setPollerThreadPriority(int threadPriority) {
|
||||
((NioEndpoint)getEndpoint()).setPollerThreadPriority(threadPriority);
|
||||
}
|
||||
|
||||
public int getPollerThreadPriority() {
|
||||
return ((NioEndpoint)getEndpoint()).getPollerThreadPriority();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- JMX related methods
|
||||
|
||||
@Override
|
||||
protected String getNamePrefix() {
|
||||
if (isSSLEnabled()) {
|
||||
return ("https-" + getSslImplementationShortName()+ "-nio");
|
||||
} else {
|
||||
return ("http-nio");
|
||||
}
|
||||
}
|
||||
}
|
||||
649
java/org/apache/coyote/http11/Http11OutputBuffer.java
Normal file
649
java/org/apache/coyote/http11/Http11OutputBuffer.java
Normal file
@@ -0,0 +1,649 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.coyote.ActionCode;
|
||||
import org.apache.coyote.Response;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.buf.MessageBytes;
|
||||
import org.apache.tomcat.util.http.HttpMessages;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* Provides buffering for the HTTP headers (allowing responses to be reset
|
||||
* before they have been committed) and the link to the Socket for writing the
|
||||
* headers (once committed) and the response body. Note that buffering of the
|
||||
* response body happens at a higher level.
|
||||
*/
|
||||
public class Http11OutputBuffer implements HttpOutputBuffer {
|
||||
|
||||
// -------------------------------------------------------------- Variables
|
||||
|
||||
/**
|
||||
* The string manager for this package.
|
||||
*/
|
||||
protected static final StringManager sm = StringManager.getManager(Http11OutputBuffer.class);
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
/**
|
||||
* Associated Coyote response.
|
||||
*/
|
||||
protected Response response;
|
||||
|
||||
|
||||
/**
|
||||
* Finished flag.
|
||||
*/
|
||||
protected boolean responseFinished;
|
||||
|
||||
|
||||
/**
|
||||
* The buffer used for header composition.
|
||||
*/
|
||||
protected final ByteBuffer headerBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* Filter library for processing the response body.
|
||||
*/
|
||||
protected OutputFilter[] filterLibrary;
|
||||
|
||||
|
||||
/**
|
||||
* Active filters for the current request.
|
||||
*/
|
||||
protected OutputFilter[] activeFilters;
|
||||
|
||||
|
||||
/**
|
||||
* Index of the last active filter.
|
||||
*/
|
||||
protected int lastActiveFilter;
|
||||
|
||||
|
||||
/**
|
||||
* Underlying output buffer.
|
||||
*/
|
||||
protected HttpOutputBuffer outputStreamOutputBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper for socket where data will be written to.
|
||||
*/
|
||||
protected SocketWrapperBase<?> socketWrapper;
|
||||
|
||||
|
||||
/**
|
||||
* Bytes written to client for the current request
|
||||
*/
|
||||
protected long byteCount = 0;
|
||||
|
||||
|
||||
@Deprecated
|
||||
private boolean sendReasonPhrase = false;
|
||||
|
||||
|
||||
protected Http11OutputBuffer(Response response, int headerBufferSize, boolean sendReasonPhrase) {
|
||||
|
||||
this.response = response;
|
||||
this.sendReasonPhrase = sendReasonPhrase;
|
||||
|
||||
headerBuffer = ByteBuffer.allocate(headerBufferSize);
|
||||
|
||||
filterLibrary = new OutputFilter[0];
|
||||
activeFilters = new OutputFilter[0];
|
||||
lastActiveFilter = -1;
|
||||
|
||||
responseFinished = false;
|
||||
|
||||
outputStreamOutputBuffer = new SocketOutputBuffer();
|
||||
|
||||
if (sendReasonPhrase) {
|
||||
// Cause loading of HttpMessages
|
||||
HttpMessages.getInstance(response.getLocale()).getMessage(200);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------- Properties
|
||||
|
||||
/**
|
||||
* Add an output filter to the filter library. Note that calling this method
|
||||
* resets the currently active filters to none.
|
||||
*
|
||||
* @param filter The filter to add
|
||||
*/
|
||||
public void addFilter(OutputFilter filter) {
|
||||
|
||||
OutputFilter[] newFilterLibrary = new OutputFilter[filterLibrary.length + 1];
|
||||
for (int i = 0; i < filterLibrary.length; i++) {
|
||||
newFilterLibrary[i] = filterLibrary[i];
|
||||
}
|
||||
newFilterLibrary[filterLibrary.length] = filter;
|
||||
filterLibrary = newFilterLibrary;
|
||||
|
||||
activeFilters = new OutputFilter[filterLibrary.length];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get filters.
|
||||
*
|
||||
* @return The current filter library containing all possible filters
|
||||
*/
|
||||
public OutputFilter[] getFilters() {
|
||||
return filterLibrary;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an output filter to the active filters for the current response.
|
||||
* <p>
|
||||
* The filter does not have to be present in {@link #getFilters()}.
|
||||
* <p>
|
||||
* A filter can only be added to a response once. If the filter has already
|
||||
* been added to this response then this method will be a NO-OP.
|
||||
*
|
||||
* @param filter The filter to add
|
||||
*/
|
||||
public void addActiveFilter(OutputFilter filter) {
|
||||
|
||||
if (lastActiveFilter == -1) {
|
||||
filter.setBuffer(outputStreamOutputBuffer);
|
||||
} else {
|
||||
for (int i = 0; i <= lastActiveFilter; i++) {
|
||||
if (activeFilters[i] == filter)
|
||||
return;
|
||||
}
|
||||
filter.setBuffer(activeFilters[lastActiveFilter]);
|
||||
}
|
||||
|
||||
activeFilters[++lastActiveFilter] = filter;
|
||||
|
||||
filter.setResponse(response);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doWrite(ByteBuffer)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doWrite(ByteChunk chunk) throws IOException {
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
// Send the connector a request for commit. The connector should
|
||||
// then validate the headers, send them (using sendHeaders) and
|
||||
// set the filters accordingly.
|
||||
response.action(ActionCode.COMMIT, null);
|
||||
}
|
||||
|
||||
if (lastActiveFilter == -1) {
|
||||
return outputStreamOutputBuffer.doWrite(chunk);
|
||||
} else {
|
||||
return activeFilters[lastActiveFilter].doWrite(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int doWrite(ByteBuffer chunk) throws IOException {
|
||||
|
||||
if (!response.isCommitted()) {
|
||||
// Send the connector a request for commit. The connector should
|
||||
// then validate the headers, send them (using sendHeaders) and
|
||||
// set the filters accordingly.
|
||||
response.action(ActionCode.COMMIT, null);
|
||||
}
|
||||
|
||||
if (lastActiveFilter == -1) {
|
||||
return outputStreamOutputBuffer.doWrite(chunk);
|
||||
} else {
|
||||
return activeFilters[lastActiveFilter].doWrite(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getBytesWritten() {
|
||||
if (lastActiveFilter == -1) {
|
||||
return outputStreamOutputBuffer.getBytesWritten();
|
||||
} else {
|
||||
return activeFilters[lastActiveFilter].getBytesWritten();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------- HttpOutputBuffer Methods
|
||||
|
||||
/**
|
||||
* Flush the response.
|
||||
*
|
||||
* @throws IOException an underlying I/O error occurred
|
||||
*/
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if (lastActiveFilter == -1) {
|
||||
outputStreamOutputBuffer.flush();
|
||||
} else {
|
||||
activeFilters[lastActiveFilter].flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void end() throws IOException {
|
||||
if (responseFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastActiveFilter == -1) {
|
||||
outputStreamOutputBuffer.end();
|
||||
} else {
|
||||
activeFilters[lastActiveFilter].end();
|
||||
}
|
||||
|
||||
responseFinished = true;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
/**
|
||||
* Reset the header buffer if an error occurs during the writing of the
|
||||
* headers so the error response can be written.
|
||||
*/
|
||||
void resetHeaderBuffer() {
|
||||
headerBuffer.position(0).limit(headerBuffer.capacity());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recycle the output buffer. This should be called when closing the
|
||||
* connection.
|
||||
*/
|
||||
public void recycle() {
|
||||
nextRequest();
|
||||
socketWrapper = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* End processing of current HTTP request.
|
||||
* Note: All bytes of the current request should have been already
|
||||
* consumed. This method only resets all the pointers so that we are ready
|
||||
* to parse the next HTTP request.
|
||||
*/
|
||||
public void nextRequest() {
|
||||
// Recycle filters
|
||||
for (int i = 0; i <= lastActiveFilter; i++) {
|
||||
activeFilters[i].recycle();
|
||||
}
|
||||
// Recycle response object
|
||||
response.recycle();
|
||||
// Reset pointers
|
||||
headerBuffer.position(0).limit(headerBuffer.capacity());
|
||||
lastActiveFilter = -1;
|
||||
responseFinished = false;
|
||||
byteCount = 0;
|
||||
}
|
||||
|
||||
|
||||
public void init(SocketWrapperBase<?> socketWrapper) {
|
||||
this.socketWrapper = socketWrapper;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public void sendAck() throws IOException {
|
||||
if (!response.isCommitted()) {
|
||||
if (sendReasonPhrase) {
|
||||
socketWrapper.write(isBlocking(), Constants.ACK_BYTES_REASON, 0, Constants.ACK_BYTES_REASON.length);
|
||||
} else {
|
||||
socketWrapper.write(isBlocking(), Constants.ACK_BYTES, 0, Constants.ACK_BYTES.length);
|
||||
}
|
||||
if (flushBuffer(true)) {
|
||||
throw new IOException(sm.getString("iob.failedwrite.ack"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Commit the response.
|
||||
*
|
||||
* @throws IOException an underlying I/O error occurred
|
||||
*/
|
||||
protected void commit() throws IOException {
|
||||
response.setCommitted(true);
|
||||
|
||||
if (headerBuffer.position() > 0) {
|
||||
// Sending the response header buffer
|
||||
headerBuffer.flip();
|
||||
try {
|
||||
socketWrapper.write(isBlocking(), headerBuffer);
|
||||
} finally {
|
||||
headerBuffer.position(0).limit(headerBuffer.capacity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send the response status line.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void sendStatus() {
|
||||
// Write protocol name
|
||||
write(Constants.HTTP_11_BYTES);
|
||||
headerBuffer.put(Constants.SP);
|
||||
|
||||
// Write status code
|
||||
int status = response.getStatus();
|
||||
switch (status) {
|
||||
case 200:
|
||||
write(Constants._200_BYTES);
|
||||
break;
|
||||
case 400:
|
||||
write(Constants._400_BYTES);
|
||||
break;
|
||||
case 404:
|
||||
write(Constants._404_BYTES);
|
||||
break;
|
||||
default:
|
||||
write(status);
|
||||
}
|
||||
|
||||
headerBuffer.put(Constants.SP);
|
||||
|
||||
if (sendReasonPhrase) {
|
||||
// Write message
|
||||
String message = null;
|
||||
if (org.apache.coyote.Constants.USE_CUSTOM_STATUS_MSG_IN_HEADER &&
|
||||
HttpMessages.isSafeInHttpHeader(response.getMessage())) {
|
||||
message = response.getMessage();
|
||||
}
|
||||
if (message == null) {
|
||||
write(HttpMessages.getInstance(
|
||||
response.getLocale()).getMessage(status));
|
||||
} else {
|
||||
write(message);
|
||||
}
|
||||
} else {
|
||||
// The reason phrase is optional but the space before it is not. Skip
|
||||
// sending the reason phrase. Clients should ignore it (RFC 7230) and it
|
||||
// just wastes bytes.
|
||||
}
|
||||
|
||||
headerBuffer.put(Constants.CR).put(Constants.LF);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a header.
|
||||
*
|
||||
* @param name Header name
|
||||
* @param value Header value
|
||||
*/
|
||||
public void sendHeader(MessageBytes name, MessageBytes value) {
|
||||
write(name);
|
||||
headerBuffer.put(Constants.COLON).put(Constants.SP);
|
||||
write(value);
|
||||
headerBuffer.put(Constants.CR).put(Constants.LF);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* End the header block.
|
||||
*/
|
||||
public void endHeaders() {
|
||||
headerBuffer.put(Constants.CR).put(Constants.LF);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will write the contents of the specified message bytes
|
||||
* buffer to the output stream, without filtering. This method is meant to
|
||||
* be used to write the response header.
|
||||
*
|
||||
* @param mb data to be written
|
||||
*/
|
||||
private void write(MessageBytes mb) {
|
||||
if (mb.getType() != MessageBytes.T_BYTES) {
|
||||
mb.toBytes();
|
||||
ByteChunk bc = mb.getByteChunk();
|
||||
// Need to filter out CTLs excluding TAB. ISO-8859-1 and UTF-8
|
||||
// values will be OK. Strings using other encodings may be
|
||||
// corrupted.
|
||||
byte[] buffer = bc.getBuffer();
|
||||
for (int i = bc.getOffset(); i < bc.getLength(); i++) {
|
||||
// byte values are signed i.e. -128 to 127
|
||||
// The values are used unsigned. 0 to 31 are CTLs so they are
|
||||
// filtered (apart from TAB which is 9). 127 is a control (DEL).
|
||||
// The values 128 to 255 are all OK. Converting those to signed
|
||||
// gives -128 to -1.
|
||||
if ((buffer[i] > -1 && buffer[i] <= 31 && buffer[i] != 9) ||
|
||||
buffer[i] == 127) {
|
||||
buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
write(mb.getByteChunk());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will write the contents of the specified byte chunk to the
|
||||
* output stream, without filtering. This method is meant to be used to
|
||||
* write the response header.
|
||||
*
|
||||
* @param bc data to be written
|
||||
*/
|
||||
private void write(ByteChunk bc) {
|
||||
// Writing the byte chunk to the output buffer
|
||||
int length = bc.getLength();
|
||||
checkLengthBeforeWrite(length);
|
||||
headerBuffer.put(bc.getBytes(), bc.getStart(), length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will write the contents of the specified byte
|
||||
* buffer to the output stream, without filtering. This method is meant to
|
||||
* be used to write the response header.
|
||||
*
|
||||
* @param b data to be written
|
||||
*/
|
||||
public void write(byte[] b) {
|
||||
checkLengthBeforeWrite(b.length);
|
||||
|
||||
// Writing the byte chunk to the output buffer
|
||||
headerBuffer.put(b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will write the contents of the specified String to the
|
||||
* output stream, without filtering. This method is meant to be used to
|
||||
* write the response header.
|
||||
*
|
||||
* @param s data to be written
|
||||
*/
|
||||
private void write(String s) {
|
||||
if (s == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// From the Tomcat 3.3 HTTP/1.0 connector
|
||||
int len = s.length();
|
||||
checkLengthBeforeWrite(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = s.charAt (i);
|
||||
// Note: This is clearly incorrect for many strings,
|
||||
// but is the only consistent approach within the current
|
||||
// servlet framework. It must suffice until servlet output
|
||||
// streams properly encode their output.
|
||||
if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
|
||||
c = ' ';
|
||||
}
|
||||
headerBuffer.put((byte) c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will write the specified integer to the output stream. This
|
||||
* method is meant to be used to write the response header.
|
||||
*
|
||||
* @param value data to be written
|
||||
*/
|
||||
private void write(int value) {
|
||||
// From the Tomcat 3.3 HTTP/1.0 connector
|
||||
String s = Integer.toString(value);
|
||||
int len = s.length();
|
||||
checkLengthBeforeWrite(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char c = s.charAt (i);
|
||||
headerBuffer.put((byte) c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks to see if there is enough space in the buffer to write the
|
||||
* requested number of bytes.
|
||||
*/
|
||||
private void checkLengthBeforeWrite(int length) {
|
||||
// "+ 4": BZ 57509. Reserve space for CR/LF/COLON/SP characters that
|
||||
// are put directly into the buffer following this write operation.
|
||||
if (headerBuffer.position() + length + 4 > headerBuffer.capacity()) {
|
||||
throw new HeadersTooLargeException(
|
||||
sm.getString("iob.responseheadertoolarge.error"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------ Non-blocking writes
|
||||
|
||||
/**
|
||||
* Writes any remaining buffered data.
|
||||
*
|
||||
* @param block Should this method block until the buffer is empty
|
||||
* @return <code>true</code> if data remains in the buffer (which can only
|
||||
* happen in non-blocking mode) else <code>false</code>.
|
||||
* @throws IOException Error writing data
|
||||
*/
|
||||
protected boolean flushBuffer(boolean block) throws IOException {
|
||||
return socketWrapper.flush(block);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is standard Servlet blocking IO being used for output?
|
||||
* @return <code>true</code> if this is blocking IO
|
||||
*/
|
||||
protected final boolean isBlocking() {
|
||||
return response.getWriteListener() == null;
|
||||
}
|
||||
|
||||
|
||||
protected final boolean isReady() {
|
||||
boolean result = !hasDataToWrite();
|
||||
if (!result) {
|
||||
socketWrapper.registerWriteInterest();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasDataToWrite() {
|
||||
return socketWrapper.hasDataToWrite();
|
||||
}
|
||||
|
||||
|
||||
public void registerWriteInterest() {
|
||||
socketWrapper.registerWriteInterest();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------ SocketOutputBuffer Inner Class
|
||||
|
||||
/**
|
||||
* This class is an output buffer which will write data to a socket.
|
||||
*/
|
||||
protected class SocketOutputBuffer implements HttpOutputBuffer {
|
||||
|
||||
/**
|
||||
* Write chunk.
|
||||
*
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doWrite(ByteBuffer)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doWrite(ByteChunk chunk) throws IOException {
|
||||
int len = chunk.getLength();
|
||||
int start = chunk.getStart();
|
||||
byte[] b = chunk.getBuffer();
|
||||
socketWrapper.write(isBlocking(), b, start, len);
|
||||
byteCount += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write chunk.
|
||||
*/
|
||||
@Override
|
||||
public int doWrite(ByteBuffer chunk) throws IOException {
|
||||
try {
|
||||
int len = chunk.remaining();
|
||||
socketWrapper.write(isBlocking(), chunk);
|
||||
len -= chunk.remaining();
|
||||
byteCount += len;
|
||||
return len;
|
||||
} catch (IOException ioe) {
|
||||
response.action(ActionCode.CLOSE_NOW, ioe);
|
||||
// Re-throw
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBytesWritten() {
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() throws IOException {
|
||||
socketWrapper.flush(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
socketWrapper.flush(isBlocking());
|
||||
}
|
||||
}
|
||||
}
|
||||
1538
java/org/apache/coyote/http11/Http11Processor.java
Normal file
1538
java/org/apache/coyote/http11/Http11Processor.java
Normal file
File diff suppressed because it is too large
Load Diff
37
java/org/apache/coyote/http11/Http11Protocol.java
Normal file
37
java/org/apache/coyote/http11/Http11Protocol.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* @deprecated This class will be removed in Tomcat 9.
|
||||
*/
|
||||
@Deprecated
|
||||
public class Http11Protocol extends Http11NioProtocol {
|
||||
|
||||
private static final Log log = LogFactory.getLog(Http11Protocol.class);
|
||||
private static final StringManager sm = StringManager.getManager(Http11Protocol.class);
|
||||
|
||||
|
||||
public Http11Protocol() {
|
||||
super();
|
||||
log.warn(sm.getString("http11protocol.noBio"));
|
||||
}
|
||||
}
|
||||
40
java/org/apache/coyote/http11/HttpOutputBuffer.java
Normal file
40
java/org/apache/coyote/http11/HttpOutputBuffer.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.io.IOException;
|
||||
|
||||
import org.apache.coyote.OutputBuffer;
|
||||
|
||||
public interface HttpOutputBuffer extends OutputBuffer {
|
||||
|
||||
/**
|
||||
* Finish writing the current response. It is acceptable to write extra
|
||||
* bytes using {@link #doWrite(java.nio.ByteBuffer)} during the execution of
|
||||
* this method.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs while writing to the client
|
||||
*/
|
||||
public void end() throws IOException;
|
||||
|
||||
/**
|
||||
* Flushes any unwritten data to the client.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs while flushing
|
||||
*/
|
||||
public void flush() throws IOException;
|
||||
}
|
||||
93
java/org/apache/coyote/http11/InputFilter.java
Normal file
93
java/org/apache/coyote/http11/InputFilter.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.io.IOException;
|
||||
|
||||
import org.apache.coyote.InputBuffer;
|
||||
import org.apache.coyote.Request;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
|
||||
/**
|
||||
* Input filter interface.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public interface InputFilter extends InputBuffer {
|
||||
|
||||
/**
|
||||
* Some filters need additional parameters from the request.
|
||||
*
|
||||
* @param request The request to be associated with this filter
|
||||
*/
|
||||
public void setRequest(Request request);
|
||||
|
||||
|
||||
/**
|
||||
* Make the filter ready to process the next request.
|
||||
*/
|
||||
public void recycle();
|
||||
|
||||
|
||||
/**
|
||||
* Get the name of the encoding handled by this filter.
|
||||
*
|
||||
* @return The encoding name as a byte chunk to facilitate comparison with
|
||||
* the value read from the HTTP headers which will also be a
|
||||
* ByteChunk
|
||||
*/
|
||||
public ByteChunk getEncodingName();
|
||||
|
||||
|
||||
/**
|
||||
* Set the next buffer in the filter pipeline.
|
||||
*
|
||||
* @param buffer The next buffer
|
||||
*/
|
||||
public void setBuffer(InputBuffer buffer);
|
||||
|
||||
|
||||
/**
|
||||
* End the current request.
|
||||
*
|
||||
* @return 0 is the expected return value. A positive value indicates that
|
||||
* too many bytes were read. This method is allowed to use buffer.doRead
|
||||
* to consume extra bytes. The result of this method can't be negative (if
|
||||
* an error happens, an IOException should be thrown instead).
|
||||
*
|
||||
* @throws IOException If an error happens
|
||||
*/
|
||||
public long end() throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Amount of bytes still available in a buffer.
|
||||
*
|
||||
* @return The number of bytes in the buffer
|
||||
*/
|
||||
public int available();
|
||||
|
||||
|
||||
/**
|
||||
* Has the request body been read fully?
|
||||
*
|
||||
* @return {@code true} if the request body has been fully read, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public boolean isFinished();
|
||||
}
|
||||
55
java/org/apache/coyote/http11/LocalStrings.properties
Normal file
55
java/org/apache/coyote/http11/LocalStrings.properties
Normal file
@@ -0,0 +1,55 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
abstractHttp11Protocol.alpnConfigured=The [{0}] connector has been configured to support negotiation to [{1}] via ALPN
|
||||
abstractHttp11Protocol.alpnWithNoAlpn=The upgrade handler [{0}] for [{1}] only supports upgrade via ALPN but has been configured for the [{2}] connector that does not support ALPN.
|
||||
abstractHttp11Protocol.httpUpgradeConfigured=The [{0}] connector has been configured to support HTTP upgrade to [{1}]
|
||||
|
||||
http11processor.fallToDebug=\n\
|
||||
\ Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
|
||||
http11processor.header.parse=Error parsing HTTP request header
|
||||
http11processor.request.finish=Error finishing request
|
||||
http11processor.request.inconsistentHosts=The host specified in the request line is not consistent with the host header
|
||||
http11processor.request.invalidScheme=The HTTP request contained an absolute URI with an invalid scheme
|
||||
http11processor.request.invalidTransferEncoding=The HTTP request contained an invalid Transfer-Encoding header
|
||||
http11processor.request.invalidUri=The HTTP request contained an invalid URI
|
||||
http11processor.request.invalidUserInfo=The HTTP request contained an absolute URI with an invalid userinfo
|
||||
http11processor.request.multipleContentLength=The request contained multiple content-length headers
|
||||
http11processor.request.multipleHosts=The request contained multiple host headers
|
||||
http11processor.request.noHostHeader=The HTTP/1.1 request did not provide a host header
|
||||
http11processor.request.nonNumericContentLength=The request contained a content-length header with a non-numeric value
|
||||
http11processor.request.prepare=Error preparing request
|
||||
http11processor.request.process=Error processing request
|
||||
http11processor.response.finish=Error finishing response
|
||||
http11processor.sendfile.error=Error sending data using sendfile. May be caused by invalid request attributes for start/end points
|
||||
http11processor.socket.info=Exception getting socket information
|
||||
|
||||
http11protocol.noBio=The HTTP BIO connector has been removed in Tomcat 8.5.x onwards. The HTTP BIO connector configuration has been automatically switched to use the HTTP NIO connector instead.
|
||||
|
||||
iib.available.readFail=A non-blocking read failed while attempting to determine if data was available
|
||||
iib.eof.error=Unexpected EOF read on the socket
|
||||
iib.failedread.apr=Read failed with APR/native error code [{0}]
|
||||
iib.filter.npe=You may not add a null filter
|
||||
iib.invalidHttpProtocol=Invalid character found in the HTTP protocol
|
||||
iib.invalidRequestTarget=Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
|
||||
iib.invalidheader=The HTTP header line [{0}] does not conform to RFC 7230 and has been ignored.
|
||||
iib.invalidmethod=Invalid character found in method name. HTTP method names must be tokens
|
||||
iib.parseheaders.ise.error=Unexpected state: headers already parsed. Buffer not recycled?
|
||||
iib.readtimeout=Timeout attempting to read data from the socket
|
||||
iib.requestheadertoolarge.error=Request header is too large
|
||||
|
||||
iob.failedwrite=Failed write
|
||||
iob.failedwrite.ack=Failed to send HTTP 100 continue response
|
||||
iob.responseheadertoolarge.error=An attempt was made to write more data to the response headers than there was room available in the buffer. Increase maxHttpHeaderSize on the connector or write less data into the response headers.
|
||||
22
java/org/apache/coyote/http11/LocalStrings_de.properties
Normal file
22
java/org/apache/coyote/http11/LocalStrings_de.properties
Normal file
@@ -0,0 +1,22 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
http11processor.request.prepare=Fehler beim vorbereiten der Anfrage
|
||||
http11processor.request.process=Fehler bei der Verarbeitung der Anfrage
|
||||
http11processor.socket.info=Ausnahme beim Lesen der Informationen zum Socket
|
||||
|
||||
iib.invalidmethod=Ungültiges Zeichen in Methoden Namen gefunden. HTTP Methoden Namen müssen Token nach RFC-7230 sein
|
||||
|
||||
iob.failedwrite=Fehlgeschlagener Schreibvorgang
|
||||
29
java/org/apache/coyote/http11/LocalStrings_es.properties
Normal file
29
java/org/apache/coyote/http11/LocalStrings_es.properties
Normal file
@@ -0,0 +1,29 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
http11processor.header.parse=Error analizando cabecera de requerimiento HTTP
|
||||
http11processor.request.finish=Error acabando requerimiento
|
||||
http11processor.request.prepare=Error preparando solicitud
|
||||
http11processor.request.process=Error procesando requerimiento
|
||||
http11processor.response.finish=Error acabando respuesta
|
||||
http11processor.socket.info=Excepción obteniendo información de conector
|
||||
|
||||
iib.eof.error=Inesperado Fin De Archivo (EOF) leído en el enchufe (socket)
|
||||
iib.invalidmethod=Se encontró un carácter inválido en el nombre del método. Los nombres de métodos HTTP deben ser tokens
|
||||
iib.parseheaders.ise.error=Estado inesperado: las cabeceras ya fueron parseadas. No se ha reciclado el buffer??
|
||||
iib.requestheadertoolarge.error=La cabecera del requerimiento es demasido grande
|
||||
|
||||
iob.failedwrite=Fallo de escritura
|
||||
iob.responseheadertoolarge.error=Un intento para escribir más datos en las cabeceras de respuesta escribir fue hecho, sin embargo no hay más espacio disponible en el bufer. Aumente el parámetro maxHttpHeaderSize en el conector o escribe menos datos en las respuestas de las cabeceras.\n
|
||||
51
java/org/apache/coyote/http11/LocalStrings_fr.properties
Normal file
51
java/org/apache/coyote/http11/LocalStrings_fr.properties
Normal file
@@ -0,0 +1,51 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
abstractHttp11Protocol.alpnConfigured=Le connecteur [{0}] a été configuré pour supporter la négociation de [{1}] avec ALPN
|
||||
abstractHttp11Protocol.alpnWithNoAlpn=Le gestionnaire de mise à niveau [{0}] pour [{1}] ne supporte qu''une mise à niveau via ALPN mais il a été configuré pour le connecteur [{2}] qui ne supporte pas ALPN
|
||||
abstractHttp11Protocol.httpUpgradeConfigured=Le connecteur [{0}] a été configuré pour supporter la mise à niveau de HTTP vers [{1}]
|
||||
|
||||
http11processor.fallToDebug=\ Note: toutes les occurrences suivantes d'erreurs d'analyse des requêtes HTTP seront enregistrées au niveau DEBUG
|
||||
http11processor.header.parse=Erreur lors de l'analyse d'un en-tête de requête HTTP
|
||||
http11processor.request.finish=Erreur en terminant la requête
|
||||
http11processor.request.inconsistentHosts=L'hôte spécifié dans la ligne de requête ne correspond pas à celui de l'en-tête hôte
|
||||
http11processor.request.invalidScheme=La requête HTTP contenait une URi absolue avec un schéma invalide
|
||||
http11processor.request.invalidUri==La requête HTTP contenait une URI invalide
|
||||
http11processor.request.invalidUserInfo=La requête HTTP contenait un URI absolu avec un composant "userinfo" invalide
|
||||
http11processor.request.multipleContentLength=La requête contenait plusieurs en-têtes content-length
|
||||
http11processor.request.multipleHosts=La requête contenait plusieurs en-têtes hôtes
|
||||
http11processor.request.noHostHeader=La requ6ete HTTP/1.1 ne contient pas d'en-tête host
|
||||
http11processor.request.nonNumericContentLength=La requête contenait un en-tête content-length avec une valeur non numérique
|
||||
http11processor.request.prepare=Echec de préparation de la requête
|
||||
http11processor.request.process=Erreur de traitement de la requête
|
||||
http11processor.response.finish=Erreur en finissant la réponse
|
||||
http11processor.sendfile.error=Erreur d'envoi des données avec sendfile, cela peut être causé par des attributs de démarrage ou de fin incorrects dans la requête
|
||||
http11processor.socket.info=Exception pendant la requête d'information sur le socket.
|
||||
|
||||
iib.available.readFail=Une lecture non-bloquante a échoué lors de la détermination préalable de données disponibles
|
||||
iib.eof.error=Fin de flux (EOF) inattendue à la lecture sur la socket
|
||||
iib.failedread.apr=Echec de lecteur avec le code d''erreur APR [{0}]
|
||||
iib.filter.npe=Impossible d'ajouter un filtre null
|
||||
iib.invalidHttpProtocol=Un caractère invalide a été trouvé dans le protocole HTTP
|
||||
iib.invalidRequestTarget=Un caractère invalide a été trouvé dans la cible de la requête, les caractères valides sont définis dans RFC 7230 et RFC 3986
|
||||
iib.invalidheader=La ligne d''en-être HTTP [{0}] n''est pas conforme à la RFC 7230 et a été ignorée
|
||||
iib.invalidmethod=Caractère invalide trouvé dans le nom de méthode. Les noms HTTP doivent être des "token".
|
||||
iib.parseheaders.ise.error=Etat inattendu, les en-êtres ont déjà été traités, il est possible que le buffer n'ait pas été recyclé
|
||||
iib.readtimeout=Délai d'attente dépassé en lisant des données du socket
|
||||
iib.requestheadertoolarge.error=L'entête de requête est trop important
|
||||
|
||||
iob.failedwrite=Echec d'écriture
|
||||
iob.failedwrite.ack=Echec d'envoi de la réponse HTTP 100 Continue
|
||||
iob.responseheadertoolarge.error=Essai d'écriture de plus de données dans les en-t^tes de réponse, qu'il n'y a de place disponible dans le tampon. Augmentez maxHttpHeaderSize pour le connecteur, ou écrivez moins de données dans les en-têtes de réponse.
|
||||
49
java/org/apache/coyote/http11/LocalStrings_ja.properties
Normal file
49
java/org/apache/coyote/http11/LocalStrings_ja.properties
Normal file
@@ -0,0 +1,49 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
abstractHttp11Protocol.alpnConfigured=[{0}]コネクタは、ALPN経由で[{1}]へのネゴシエーションをサポートするように構成されています
|
||||
abstractHttp11Protocol.alpnWithNoAlpn=[{1}]のアップグレードハンドラ[{0}]は、ALPNによるアップグレードのみをサポートしていますが、ALPNをサポートしていない[{2}]コネクタ用に構成されています。
|
||||
abstractHttp11Protocol.httpUpgradeConfigured=コネクタ[{0}]は、[{1}]へのHTTPアップグレードをサポートするように構成されています。
|
||||
|
||||
http11processor.fallToDebug=注:HTTPリクエスト構文解析エラーがさらに発生すると、DEBUGレベルでログに記録されます。
|
||||
http11processor.header.parse=HTTP リクエストヘッダーを解釈できませんでした。
|
||||
http11processor.request.finish=リクエスト終了処理エラー
|
||||
http11processor.request.inconsistentHosts=リクエストラインに指定されたホストが Host ヘッダーの値と矛盾しています。
|
||||
http11processor.request.invalidScheme=HTTP リクエストに不正なスキーマを指定した完全 URI が含まれています。
|
||||
http11processor.request.invalidUri== HTTPリクエストに無効なURIが含まれています
|
||||
http11processor.request.invalidUserInfo=HTTP リクエストに不正な userinfo を含む絶対 URI が指定されました。
|
||||
http11processor.request.multipleHosts=リクエストには複数のホストヘッダーが含まれていました。
|
||||
http11processor.request.noHostHeader=HTTP / 1.1リクエストでhostヘッダーが提供されませんでした。
|
||||
http11processor.request.prepare=リクエストの準備に失敗しました。
|
||||
http11processor.request.process=リクエスト処理中にエラーが発生しました
|
||||
http11processor.response.finish=レスポンス終了処理のエラー
|
||||
http11processor.sendfile.error=sendfileを使ってデータを送信中にエラーが発生しました 開始点または終了点の無効なリクエスト属性によって引き起こされる可能性があります。
|
||||
http11processor.socket.info=ソケット情報を取得する際の例外
|
||||
|
||||
iib.available.readFail=利用できるデータがあるか確かめている途中でノンブロッキング読み込みが失敗しました。
|
||||
iib.eof.error=ソケットから予期しないEOFを読み込みました
|
||||
iib.failedread.apr=APR/nativeエラーコード[{0}]で読み取りが失敗しました。
|
||||
iib.filter.npe=Nullフィルタを追加することはできません。
|
||||
iib.invalidHttpProtocol=HTTPプロトコルで無効な文字が見つかりました。
|
||||
iib.invalidRequestTarget=リクエストの宛先に不正な文字が含まれています。利用可能な文字は RFC 7230 および RFC 3986 に定義されています。
|
||||
iib.invalidheader=HTTP ヘッダー行 [{0}]は RFC 7230 に適合しないため無視します。
|
||||
iib.invalidmethod=HTTP メソッド名に不正な文字が含まれています。HTTP メソッド名は決められたトークンでなければなりません。
|
||||
iib.parseheaders.ise.error=予期しない状態:ヘッダがすでに解析されています。 バッファはリサイクルされていませんか?
|
||||
iib.readtimeout=ソケットからデータを読み取ろうとしている際のタイムアウト
|
||||
iib.requestheadertoolarge.error=リクエストヘッダが長すぎます
|
||||
|
||||
iob.failedwrite=書き込みが失敗しました。
|
||||
iob.failedwrite.ack=HTTP 100 continue レスポンスの送信に失敗しました
|
||||
iob.responseheadertoolarge.error=レスポンスヘッダーにバッファー領域より大きなデータの書き込みが発生しました。データを小さくするか Connector の maxHttpHeaderSize を大きくしてください。
|
||||
52
java/org/apache/coyote/http11/LocalStrings_ko.properties
Normal file
52
java/org/apache/coyote/http11/LocalStrings_ko.properties
Normal file
@@ -0,0 +1,52 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
abstractHttp11Protocol.alpnConfigured=[{0}] connector는 ALPN을 통해 [{1}](으)로 negotiation을 지원하도록 설정되었습니다.
|
||||
abstractHttp11Protocol.alpnWithNoAlpn=[{1}]을(를) 위한 업그레이드 핸들러 [{0}]은(는) 오직 ALPN을 통한 업그레이드만 지원합니다만, 해당 업그레이드 핸들러가 ALPN을 지원하지 않는 [{2}] Connector를 위해 설정되어 있습니다.
|
||||
abstractHttp11Protocol.httpUpgradeConfigured=[{0}] connector가, [{1}](으)로 HTTP 업그레이드를 지원하도록 설정되어 있습니다.
|
||||
|
||||
http11processor.fallToDebug=\n\
|
||||
비고: HTTP 요청 파싱 오류들이 더 발생하는 경우 DEBUG 레벨 로그로 기록될 것입니다.
|
||||
http11processor.header.parse=HTTP 요청 헤더를 파싱하는 중 오류 발생
|
||||
http11processor.request.finish=요청을 완료하는 중 오류 발생
|
||||
http11processor.request.inconsistentHosts=요청 행(request line)에 지정된 호스트가, 호스트 헤더와 일관되지 않습니다.
|
||||
http11processor.request.invalidScheme=HTTP 요청이 유효하지 않은 스킴을 가진 절대 URI를 포함했습니다.
|
||||
http11processor.request.invalidUri==HTTP 요청이 유효하지 않은 URI를 포함했습니다.
|
||||
http11processor.request.invalidUserInfo=HTTP 요청이, 유효하지 않은 userinfo를 가진 절대 URI를 포함했습니다.
|
||||
http11processor.request.multipleContentLength=해당 요청이 복수 개의 Content-Length 헤더들을 포함했습니다.
|
||||
http11processor.request.multipleHosts=요청이 여러 개의 호스트 헤더들을 포함했습니다.
|
||||
http11processor.request.noHostHeader=HTTP/1.1 요청이 호스트 헤더를 제공하지 않았습니다.
|
||||
http11processor.request.nonNumericContentLength=해당 요청이 숫자가 아닌 Content-Length 헤더 값을 포함했습니다.
|
||||
http11processor.request.prepare=요청을 준비하는 중 오류 발생
|
||||
http11processor.request.process=요청 처리 중 오류 발생
|
||||
http11processor.response.finish=응답을 완료하는 중 오류 발생
|
||||
http11processor.sendfile.error=sendfile을 사용하여 데이터를 보내는 중 오류 발생. 시작 지점과 종료 지점을 위한 요청 속성들이 유효하지 않아 발생했을 수 있습니다.
|
||||
http11processor.socket.info=소켓에 대한 정보를 얻는 중 예외 발생
|
||||
|
||||
iib.available.readFail=데이터가 가용한지 결정하려 시도하는 동안, non-blocking 읽기가 실패했습니다.
|
||||
iib.eof.error=소켓에서 예기치 않은 EOF를 읽었습니다.
|
||||
iib.failedread.apr=APR/native 오류 코드 [{0}]와(과) 함께, 읽기가 실패했습니다.
|
||||
iib.filter.npe=널인 필터를 추가할 수 없습니다.
|
||||
iib.invalidHttpProtocol=HTTP 프로토콜에서 유효하지 않은 문자가 발견되었습니다.
|
||||
iib.invalidRequestTarget=요청 타겟에서 유효하지 않은 문자가 발견되었습니다. 유효한 문자들은 RFC 7230과 RFC 3986에 정의되어 있습니다.
|
||||
iib.invalidheader=HTTP 헤더 행 [{0}]이(가) RFC 7230을 준수하지 않아, 무시되었습니다.
|
||||
iib.invalidmethod=메소드 이름에 유효하지 않은 문자가 발견되었습니다. HTTP 메소드 이름은 유효한 토큰이어야 합니다.
|
||||
iib.parseheaders.ise.error=예기치 않은 상태: 헤더들이 이미 파싱되었습니다. 버퍼가 참조 해제되지 않았었나요?
|
||||
iib.readtimeout=소켓으로부터 데이터를 읽으려 시도하는 중 제한 시간 초과
|
||||
iib.requestheadertoolarge.error=요청 헤더가 너무 큽니다.
|
||||
|
||||
iob.failedwrite=쓰기 실패
|
||||
iob.failedwrite.ack=HTTP 100 continue 응답을 보내지 못했습니다.
|
||||
iob.responseheadertoolarge.error=응답 헤더들에 가용한 버퍼 공간을 초과하는 데이터를 쓰려는 시도가 발생했습니다. 해당 Connector의 maxHttpHeaderSize를 증가시키거나, 응답 헤더들에 보다 적은 데이터를 쓰도록 하십시오.
|
||||
16
java/org/apache/coyote/http11/LocalStrings_ru.properties
Normal file
16
java/org/apache/coyote/http11/LocalStrings_ru.properties
Normal file
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
http11processor.request.process=Ошибка при обработке запроса
|
||||
39
java/org/apache/coyote/http11/LocalStrings_zh_CN.properties
Normal file
39
java/org/apache/coyote/http11/LocalStrings_zh_CN.properties
Normal file
@@ -0,0 +1,39 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
abstractHttp11Protocol.alpnConfigured=[{0}]连接器已配置为支持通过ALPN与[{1}]协商。
|
||||
|
||||
http11processor.header.parse=解析 HTTP 请求 header 错误
|
||||
http11processor.request.inconsistentHosts=请求行中指定的主机与主机头不一致。
|
||||
http11processor.request.invalidScheme=HTTP请求包含具有无效方案的绝对URL
|
||||
http11processor.request.invalidUserInfo=HTTP 请求包含带有无效 userinfo 的绝对 URI
|
||||
http11processor.request.multipleContentLength=请求包含了多个content-length请求头参数
|
||||
http11processor.request.noHostHeader=http/1.1请求没有提供主机头
|
||||
http11processor.request.prepare=准备请求时出错
|
||||
http11processor.request.process=错误的处理请求
|
||||
http11processor.response.finish=错误完成相应
|
||||
http11processor.socket.info=获取socket信息异常
|
||||
|
||||
iib.available.readFail=尝试确定数据是否可用时,非阻塞读取失败
|
||||
iib.eof.error=套接字读取到意外的EOF
|
||||
iib.filter.npe=你不能添加空过滤器(null)
|
||||
iib.invalidheader=HTTP header行 [{0}] 不符合RFC 7230并且已被忽略。
|
||||
iib.invalidmethod=在方法名称中发现无效的字符串, HTTP 方法名必须是有效的符号.
|
||||
iib.parseheaders.ise.error=意外状态:已解析标头。 缓冲池不回收?
|
||||
iib.readtimeout=从套接字读取数据超时
|
||||
|
||||
iob.failedwrite=写入.失败
|
||||
iob.failedwrite.ack=无法发送HTTP 100继续响应
|
||||
iob.responseheadertoolarge.error=尝试将更多数据写入响应标头,而不是缓冲区中有可用空间。 增加连接器上的maxHttpHeaderSize或将更少的数据写入响应头。
|
||||
50
java/org/apache/coyote/http11/OutputFilter.java
Normal file
50
java/org/apache/coyote/http11/OutputFilter.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.coyote.Response;
|
||||
|
||||
/**
|
||||
* Output filter.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public interface OutputFilter extends HttpOutputBuffer {
|
||||
|
||||
/**
|
||||
* Some filters need additional parameters from the response. All the
|
||||
* necessary reading can occur in that method, as this method is called
|
||||
* after the response header processing is complete.
|
||||
*
|
||||
* @param response The response to associate with this OutputFilter
|
||||
*/
|
||||
public void setResponse(Response response);
|
||||
|
||||
|
||||
/**
|
||||
* Make the filter ready to process the next request.
|
||||
*/
|
||||
public void recycle();
|
||||
|
||||
|
||||
/**
|
||||
* Set the next buffer in the filter pipeline.
|
||||
*
|
||||
* @param buffer The next buffer instance
|
||||
*/
|
||||
public void setBuffer(HttpOutputBuffer buffer);
|
||||
}
|
||||
188
java/org/apache/coyote/http11/filters/BufferedInputFilter.java
Normal file
188
java/org/apache/coyote/http11/filters/BufferedInputFilter.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.coyote.InputBuffer;
|
||||
import org.apache.coyote.Request;
|
||||
import org.apache.coyote.http11.InputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.net.ApplicationBufferHandler;
|
||||
|
||||
/**
|
||||
* Input filter responsible for reading and buffering the request body, so that
|
||||
* it does not interfere with client SSL handshake messages.
|
||||
*/
|
||||
public class BufferedInputFilter implements InputFilter, ApplicationBufferHandler {
|
||||
|
||||
// -------------------------------------------------------------- Constants
|
||||
|
||||
private static final String ENCODING_NAME = "buffered";
|
||||
private static final ByteChunk ENCODING = new ByteChunk();
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
private ByteBuffer buffered;
|
||||
private ByteBuffer tempRead;
|
||||
private InputBuffer buffer;
|
||||
private boolean hasRead = false;
|
||||
|
||||
|
||||
// ----------------------------------------------------- Static Initializer
|
||||
|
||||
static {
|
||||
ENCODING.setBytes(ENCODING_NAME.getBytes(StandardCharsets.ISO_8859_1),
|
||||
0, ENCODING_NAME.length());
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------- Public Methods
|
||||
|
||||
|
||||
/**
|
||||
* Set the buffering limit. This should be reset every time the buffer is
|
||||
* used.
|
||||
*
|
||||
* @param limit The maximum number of bytes that will be buffered
|
||||
*/
|
||||
public void setLimit(int limit) {
|
||||
if (buffered == null) {
|
||||
buffered = ByteBuffer.allocate(limit);
|
||||
buffered.flip();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- InputBuffer Methods
|
||||
|
||||
|
||||
/**
|
||||
* Reads the request body and buffers it.
|
||||
*/
|
||||
@Override
|
||||
public void setRequest(Request request) {
|
||||
// save off the Request body
|
||||
try {
|
||||
while (buffer.doRead(this) >= 0) {
|
||||
buffered.mark().position(buffered.limit()).limit(buffered.capacity());
|
||||
buffered.put(tempRead);
|
||||
buffered.limit(buffered.position()).reset();
|
||||
tempRead = null;
|
||||
}
|
||||
} catch(IOException | BufferOverflowException ioe) {
|
||||
// No need for i18n - this isn't going to get logged anywhere
|
||||
throw new IllegalStateException(
|
||||
"Request body too large for buffer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the given ByteChunk with the buffered request body.
|
||||
*
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doRead(ApplicationBufferHandler)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doRead(ByteChunk chunk) throws IOException {
|
||||
if (isFinished()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
chunk.setBytes(buffered.array(), buffered.arrayOffset() + buffered.position(),
|
||||
buffered.remaining());
|
||||
hasRead = true;
|
||||
return chunk.getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the given ByteBuffer with the buffered request body.
|
||||
*/
|
||||
@Override
|
||||
public int doRead(ApplicationBufferHandler handler) throws IOException {
|
||||
if (isFinished()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
handler.setByteBuffer(buffered);
|
||||
hasRead = true;
|
||||
return buffered.remaining();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBuffer(InputBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
if (buffered != null) {
|
||||
if (buffered.capacity() > 65536) {
|
||||
buffered = null;
|
||||
} else {
|
||||
buffered.position(0).limit(0);
|
||||
}
|
||||
}
|
||||
hasRead = false;
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteChunk getEncodingName() {
|
||||
return ENCODING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long end() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() {
|
||||
return buffered.remaining();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return hasRead || buffered.remaining() <= 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setByteBuffer(ByteBuffer buffer) {
|
||||
tempRead = buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ByteBuffer getByteBuffer() {
|
||||
return tempRead;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void expand(int size) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
688
java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
Normal file
688
java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
Normal file
@@ -0,0 +1,688 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.coyote.InputBuffer;
|
||||
import org.apache.coyote.Request;
|
||||
import org.apache.coyote.http11.Constants;
|
||||
import org.apache.coyote.http11.InputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.buf.HexUtils;
|
||||
import org.apache.tomcat.util.buf.MessageBytes;
|
||||
import org.apache.tomcat.util.http.MimeHeaders;
|
||||
import org.apache.tomcat.util.net.ApplicationBufferHandler;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* Chunked input filter. Parses chunked data according to
|
||||
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1">http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1</a><br>
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class ChunkedInputFilter implements InputFilter, ApplicationBufferHandler {
|
||||
|
||||
private static final StringManager sm = StringManager.getManager(
|
||||
ChunkedInputFilter.class.getPackage().getName());
|
||||
|
||||
|
||||
// -------------------------------------------------------------- Constants
|
||||
|
||||
protected static final String ENCODING_NAME = "chunked";
|
||||
protected static final ByteChunk ENCODING = new ByteChunk();
|
||||
|
||||
|
||||
// ----------------------------------------------------- Static Initializer
|
||||
|
||||
static {
|
||||
ENCODING.setBytes(ENCODING_NAME.getBytes(StandardCharsets.ISO_8859_1),
|
||||
0, ENCODING_NAME.length());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
/**
|
||||
* Next buffer in the pipeline.
|
||||
*/
|
||||
protected InputBuffer buffer;
|
||||
|
||||
|
||||
/**
|
||||
* Number of bytes remaining in the current chunk.
|
||||
*/
|
||||
protected int remaining = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Byte chunk used to read bytes.
|
||||
*/
|
||||
protected ByteBuffer readChunk;
|
||||
|
||||
|
||||
/**
|
||||
* Flag set to true when the end chunk has been read.
|
||||
*/
|
||||
protected boolean endChunk = false;
|
||||
|
||||
|
||||
/**
|
||||
* Byte chunk used to store trailing headers.
|
||||
*/
|
||||
protected final ByteChunk trailingHeaders = new ByteChunk();
|
||||
|
||||
|
||||
/**
|
||||
* Flag set to true if the next call to doRead() must parse a CRLF pair
|
||||
* before doing anything else.
|
||||
*/
|
||||
protected boolean needCRLFParse = false;
|
||||
|
||||
|
||||
/**
|
||||
* Request being parsed.
|
||||
*/
|
||||
private Request request;
|
||||
|
||||
|
||||
/**
|
||||
* Limit for extension size.
|
||||
*/
|
||||
private final long maxExtensionSize;
|
||||
|
||||
|
||||
/**
|
||||
* Limit for trailer size.
|
||||
*/
|
||||
private final int maxTrailerSize;
|
||||
|
||||
|
||||
/**
|
||||
* Size of extensions processed for this request.
|
||||
*/
|
||||
private long extensionSize;
|
||||
|
||||
|
||||
private final int maxSwallowSize;
|
||||
|
||||
|
||||
/**
|
||||
* Flag that indicates if an error has occurred.
|
||||
*/
|
||||
private boolean error;
|
||||
|
||||
|
||||
private final Set<String> allowedTrailerHeaders;
|
||||
|
||||
// ----------------------------------------------------------- Constructors
|
||||
|
||||
public ChunkedInputFilter(int maxTrailerSize, Set<String> allowedTrailerHeaders,
|
||||
int maxExtensionSize, int maxSwallowSize) {
|
||||
this.trailingHeaders.setLimit(maxTrailerSize);
|
||||
this.allowedTrailerHeaders = allowedTrailerHeaders;
|
||||
this.maxExtensionSize = maxExtensionSize;
|
||||
this.maxTrailerSize = maxTrailerSize;
|
||||
this.maxSwallowSize = maxSwallowSize;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- InputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doRead(ApplicationBufferHandler)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doRead(ByteChunk chunk) throws IOException {
|
||||
if (endChunk) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
checkError();
|
||||
|
||||
if(needCRLFParse) {
|
||||
needCRLFParse = false;
|
||||
parseCRLF(false);
|
||||
}
|
||||
|
||||
if (remaining <= 0) {
|
||||
if (!parseChunkHeader()) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.invalidHeader"));
|
||||
}
|
||||
if (endChunk) {
|
||||
parseEndChunk();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() < 0) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.eos"));
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining > readChunk.remaining()) {
|
||||
result = readChunk.remaining();
|
||||
remaining = remaining - result;
|
||||
chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + readChunk.position(), result);
|
||||
readChunk.position(readChunk.limit());
|
||||
} else {
|
||||
result = remaining;
|
||||
chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + readChunk.position(), remaining);
|
||||
readChunk.position(readChunk.position() + remaining);
|
||||
remaining = 0;
|
||||
//we need a CRLF
|
||||
if ((readChunk.position() + 1) >= readChunk.limit()) {
|
||||
//if we call parseCRLF we overrun the buffer here
|
||||
//so we defer it to the next call BZ 11117
|
||||
needCRLFParse = true;
|
||||
} else {
|
||||
parseCRLF(false); //parse the CRLF immediately
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doRead(ApplicationBufferHandler handler) throws IOException {
|
||||
if (endChunk) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
checkError();
|
||||
|
||||
if(needCRLFParse) {
|
||||
needCRLFParse = false;
|
||||
parseCRLF(false);
|
||||
}
|
||||
|
||||
if (remaining <= 0) {
|
||||
if (!parseChunkHeader()) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.invalidHeader"));
|
||||
}
|
||||
if (endChunk) {
|
||||
parseEndChunk();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() < 0) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.eos"));
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining > readChunk.remaining()) {
|
||||
result = readChunk.remaining();
|
||||
remaining = remaining - result;
|
||||
if (readChunk != handler.getByteBuffer()) {
|
||||
handler.setByteBuffer(readChunk.duplicate());
|
||||
}
|
||||
readChunk.position(readChunk.limit());
|
||||
} else {
|
||||
result = remaining;
|
||||
if (readChunk != handler.getByteBuffer()) {
|
||||
handler.setByteBuffer(readChunk.duplicate());
|
||||
handler.getByteBuffer().limit(readChunk.position() + remaining);
|
||||
}
|
||||
readChunk.position(readChunk.position() + remaining);
|
||||
remaining = 0;
|
||||
//we need a CRLF
|
||||
if ((readChunk.position() + 1) >= readChunk.limit()) {
|
||||
//if we call parseCRLF we overrun the buffer here
|
||||
//so we defer it to the next call BZ 11117
|
||||
needCRLFParse = true;
|
||||
} else {
|
||||
parseCRLF(false); //parse the CRLF immediately
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- InputFilter Methods
|
||||
|
||||
/**
|
||||
* Read the content length from the request.
|
||||
*/
|
||||
@Override
|
||||
public void setRequest(Request request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* End the current request.
|
||||
*/
|
||||
@Override
|
||||
public long end() throws IOException {
|
||||
long swallowed = 0;
|
||||
int read = 0;
|
||||
// Consume extra bytes : parse the stream until the end chunk is found
|
||||
while ((read = doRead(this)) >= 0) {
|
||||
swallowed += read;
|
||||
if (maxSwallowSize > -1 && swallowed > maxSwallowSize) {
|
||||
throwIOException(sm.getString("inputFilter.maxSwallow"));
|
||||
}
|
||||
}
|
||||
|
||||
// Return the number of extra bytes which were consumed
|
||||
return readChunk.remaining();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Amount of bytes still available in a buffer.
|
||||
*/
|
||||
@Override
|
||||
public int available() {
|
||||
return readChunk != null ? readChunk.remaining() : 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the next buffer in the filter pipeline.
|
||||
*/
|
||||
@Override
|
||||
public void setBuffer(InputBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make the filter ready to process the next request.
|
||||
*/
|
||||
@Override
|
||||
public void recycle() {
|
||||
remaining = 0;
|
||||
if (readChunk != null) {
|
||||
readChunk.position(0).limit(0);
|
||||
}
|
||||
endChunk = false;
|
||||
needCRLFParse = false;
|
||||
trailingHeaders.recycle();
|
||||
trailingHeaders.setLimit(maxTrailerSize);
|
||||
extensionSize = 0;
|
||||
error = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the associated encoding; Here, the value is
|
||||
* "identity".
|
||||
*/
|
||||
@Override
|
||||
public ByteChunk getEncodingName() {
|
||||
return ENCODING;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return endChunk;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------ Protected Methods
|
||||
|
||||
/**
|
||||
* Read bytes from the previous buffer.
|
||||
* @return The byte count which has been read
|
||||
* @throws IOException Read error
|
||||
*/
|
||||
protected int readBytes() throws IOException {
|
||||
return buffer.doRead(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the header of a chunk.
|
||||
* A chunk header can look like one of the following:<br>
|
||||
* A10CRLF<br>
|
||||
* F23;chunk-extension to be ignoredCRLF
|
||||
*
|
||||
* <p>
|
||||
* The letters before CRLF or ';' (whatever comes first) must be valid hex
|
||||
* digits. We should not parse F23IAMGONNAMESSTHISUP34CRLF as a valid
|
||||
* header according to the spec.
|
||||
* @return <code>true</code> if the chunk header has been
|
||||
* successfully parsed
|
||||
* @throws IOException Read error
|
||||
*/
|
||||
protected boolean parseChunkHeader() throws IOException {
|
||||
|
||||
int result = 0;
|
||||
boolean eol = false;
|
||||
int readDigit = 0;
|
||||
boolean extension = false;
|
||||
|
||||
while (!eol) {
|
||||
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() <= 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
byte chr = readChunk.get(readChunk.position());
|
||||
if (chr == Constants.CR || chr == Constants.LF) {
|
||||
parseCRLF(false);
|
||||
eol = true;
|
||||
} else if (chr == Constants.SEMI_COLON && !extension) {
|
||||
// First semi-colon marks the start of the extension. Further
|
||||
// semi-colons may appear to separate multiple chunk-extensions.
|
||||
// These need to be processed as part of parsing the extensions.
|
||||
extension = true;
|
||||
extensionSize++;
|
||||
} else if (!extension) {
|
||||
//don't read data after the trailer
|
||||
int charValue = HexUtils.getDec(chr);
|
||||
if (charValue != -1 && readDigit < 8) {
|
||||
readDigit++;
|
||||
result = (result << 4) | charValue;
|
||||
} else {
|
||||
//we shouldn't allow invalid, non hex characters
|
||||
//in the chunked header
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Extension 'parsing'
|
||||
// Note that the chunk-extension is neither parsed nor
|
||||
// validated. Currently it is simply ignored.
|
||||
extensionSize++;
|
||||
if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.maxExtension"));
|
||||
}
|
||||
}
|
||||
|
||||
// Parsing the CRLF increments pos
|
||||
if (!eol) {
|
||||
readChunk.position(readChunk.position() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (readDigit == 0 || result < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
endChunk = true;
|
||||
}
|
||||
|
||||
remaining = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse CRLF at end of chunk.
|
||||
*
|
||||
* @param tolerant Should tolerant parsing (LF and CRLF) be used? This
|
||||
* is recommended (RFC2616, section 19.3) for message
|
||||
* headers.
|
||||
* @throws IOException An error occurred parsing CRLF
|
||||
*/
|
||||
protected void parseCRLF(boolean tolerant) throws IOException {
|
||||
|
||||
boolean eol = false;
|
||||
boolean crfound = false;
|
||||
|
||||
while (!eol) {
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() <= 0) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.invalidCrlfNoData"));
|
||||
}
|
||||
}
|
||||
|
||||
byte chr = readChunk.get(readChunk.position());
|
||||
if (chr == Constants.CR) {
|
||||
if (crfound) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.invalidCrlfCRCR"));
|
||||
}
|
||||
crfound = true;
|
||||
} else if (chr == Constants.LF) {
|
||||
if (!tolerant && !crfound) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.invalidCrlfNoCR"));
|
||||
}
|
||||
eol = true;
|
||||
} else {
|
||||
throwIOException(sm.getString("chunkedInputFilter.invalidCrlf"));
|
||||
}
|
||||
|
||||
readChunk.position(readChunk.position() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse end chunk data.
|
||||
* @throws IOException Error propagation
|
||||
*/
|
||||
protected void parseEndChunk() throws IOException {
|
||||
// Handle optional trailer headers
|
||||
while (parseHeader()) {
|
||||
// Loop until we run out of headers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean parseHeader() throws IOException {
|
||||
|
||||
MimeHeaders headers = request.getMimeHeaders();
|
||||
|
||||
byte chr = 0;
|
||||
|
||||
// Read new bytes if needed
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() <0) {
|
||||
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
|
||||
}
|
||||
}
|
||||
|
||||
// readBytes() above will set readChunk unless it returns a value < 0
|
||||
chr = readChunk.get(readChunk.position());
|
||||
|
||||
// CRLF terminates the request
|
||||
if (chr == Constants.CR || chr == Constants.LF) {
|
||||
parseCRLF(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark the current buffer position
|
||||
int startPos = trailingHeaders.getEnd();
|
||||
|
||||
//
|
||||
// Reading the header name
|
||||
// Header name is always US-ASCII
|
||||
//
|
||||
|
||||
boolean colon = false;
|
||||
while (!colon) {
|
||||
|
||||
// Read new bytes if needed
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() <0) {
|
||||
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
|
||||
}
|
||||
}
|
||||
|
||||
// readBytes() above will set readChunk unless it returns a value < 0
|
||||
chr = readChunk.get(readChunk.position());
|
||||
if ((chr >= Constants.A) && (chr <= Constants.Z)) {
|
||||
chr = (byte) (chr - Constants.LC_OFFSET);
|
||||
}
|
||||
|
||||
if (chr == Constants.COLON) {
|
||||
colon = true;
|
||||
} else {
|
||||
trailingHeaders.append(chr);
|
||||
}
|
||||
|
||||
readChunk.position(readChunk.position() + 1);
|
||||
|
||||
}
|
||||
int colonPos = trailingHeaders.getEnd();
|
||||
|
||||
//
|
||||
// Reading the header value (which can be spanned over multiple lines)
|
||||
//
|
||||
|
||||
boolean eol = false;
|
||||
boolean validLine = true;
|
||||
int lastSignificantChar = 0;
|
||||
|
||||
while (validLine) {
|
||||
|
||||
boolean space = true;
|
||||
|
||||
// Skipping spaces
|
||||
while (space) {
|
||||
|
||||
// Read new bytes if needed
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() <0) {
|
||||
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
|
||||
}
|
||||
}
|
||||
|
||||
chr = readChunk.get(readChunk.position());
|
||||
if ((chr == Constants.SP) || (chr == Constants.HT)) {
|
||||
readChunk.position(readChunk.position() + 1);
|
||||
// If we swallow whitespace, make sure it counts towards the
|
||||
// limit placed on trailing header size
|
||||
int newlimit = trailingHeaders.getLimit() -1;
|
||||
if (trailingHeaders.getEnd() > newlimit) {
|
||||
throwIOException(sm.getString("chunkedInputFilter.maxTrailer"));
|
||||
}
|
||||
trailingHeaders.setLimit(newlimit);
|
||||
} else {
|
||||
space = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Reading bytes until the end of the line
|
||||
while (!eol) {
|
||||
|
||||
// Read new bytes if needed
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() <0) {
|
||||
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
|
||||
}
|
||||
}
|
||||
|
||||
chr = readChunk.get(readChunk.position());
|
||||
if (chr == Constants.CR || chr == Constants.LF) {
|
||||
parseCRLF(true);
|
||||
eol = true;
|
||||
} else if (chr == Constants.SP) {
|
||||
trailingHeaders.append(chr);
|
||||
} else {
|
||||
trailingHeaders.append(chr);
|
||||
lastSignificantChar = trailingHeaders.getEnd();
|
||||
}
|
||||
|
||||
if (!eol) {
|
||||
readChunk.position(readChunk.position() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Checking the first character of the new line. If the character
|
||||
// is a LWS, then it's a multiline header
|
||||
|
||||
// Read new bytes if needed
|
||||
if (readChunk == null || readChunk.position() >= readChunk.limit()) {
|
||||
if (readBytes() <0) {
|
||||
throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
|
||||
}
|
||||
}
|
||||
|
||||
chr = readChunk.get(readChunk.position());
|
||||
if ((chr != Constants.SP) && (chr != Constants.HT)) {
|
||||
validLine = false;
|
||||
} else {
|
||||
eol = false;
|
||||
// Copying one extra space in the buffer (since there must
|
||||
// be at least one space inserted between the lines)
|
||||
trailingHeaders.append(chr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
String headerName = new String(trailingHeaders.getBytes(), startPos,
|
||||
colonPos - startPos, StandardCharsets.ISO_8859_1);
|
||||
|
||||
if (allowedTrailerHeaders.contains(headerName.toLowerCase(Locale.ENGLISH))) {
|
||||
MessageBytes headerValue = headers.addValue(headerName);
|
||||
|
||||
// Set the header value
|
||||
headerValue.setBytes(trailingHeaders.getBytes(), colonPos,
|
||||
lastSignificantChar - colonPos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void throwIOException(String msg) throws IOException {
|
||||
error = true;
|
||||
throw new IOException(msg);
|
||||
}
|
||||
|
||||
|
||||
private void throwEOFException(String msg) throws IOException {
|
||||
error = true;
|
||||
throw new EOFException(msg);
|
||||
}
|
||||
|
||||
|
||||
private void checkError() throws IOException {
|
||||
if (error) {
|
||||
throw new IOException(sm.getString("chunkedInputFilter.error"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setByteBuffer(ByteBuffer buffer) {
|
||||
readChunk = buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ByteBuffer getByteBuffer() {
|
||||
return readChunk;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void expand(int size) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
184
java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java
Normal file
184
java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.coyote.Response;
|
||||
import org.apache.coyote.http11.HttpOutputBuffer;
|
||||
import org.apache.coyote.http11.OutputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.buf.HexUtils;
|
||||
|
||||
/**
|
||||
* Chunked output filter.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class ChunkedOutputFilter implements OutputFilter {
|
||||
|
||||
|
||||
// -------------------------------------------------------------- Constants
|
||||
private static final byte[] END_CHUNK_BYTES = {(byte) '0', (byte) '\r', (byte) '\n',
|
||||
(byte) '\r', (byte) '\n'};
|
||||
|
||||
|
||||
// ------------------------------------------------------------ Constructor
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public ChunkedOutputFilter() {
|
||||
chunkHeader.put(8, (byte) '\r');
|
||||
chunkHeader.put(9, (byte) '\n');
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
|
||||
/**
|
||||
* Next buffer in the pipeline.
|
||||
*/
|
||||
protected HttpOutputBuffer buffer;
|
||||
|
||||
|
||||
/**
|
||||
* Chunk header.
|
||||
*/
|
||||
protected final ByteBuffer chunkHeader = ByteBuffer.allocate(10);
|
||||
|
||||
|
||||
/**
|
||||
* End chunk.
|
||||
*/
|
||||
protected final ByteBuffer endChunk = ByteBuffer.wrap(END_CHUNK_BYTES);
|
||||
|
||||
|
||||
// ------------------------------------------------------------- Properties
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doWrite(ByteBuffer)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doWrite(ByteChunk chunk) throws IOException {
|
||||
|
||||
int result = chunk.getLength();
|
||||
|
||||
if (result <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pos = calculateChunkHeader(result);
|
||||
|
||||
chunkHeader.position(pos).limit(10);
|
||||
buffer.doWrite(chunkHeader);
|
||||
|
||||
buffer.doWrite(chunk);
|
||||
|
||||
chunkHeader.position(8).limit(10);
|
||||
buffer.doWrite(chunkHeader);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int doWrite(ByteBuffer chunk) throws IOException {
|
||||
|
||||
int result = chunk.remaining();
|
||||
|
||||
if (result <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pos = calculateChunkHeader(result);
|
||||
|
||||
chunkHeader.position(pos).limit(10);
|
||||
buffer.doWrite(chunkHeader);
|
||||
|
||||
buffer.doWrite(chunk);
|
||||
|
||||
chunkHeader.position(8).limit(10);
|
||||
buffer.doWrite(chunkHeader);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private int calculateChunkHeader(int len) {
|
||||
// Calculate chunk header
|
||||
int pos = 8;
|
||||
int current = len;
|
||||
while (current > 0) {
|
||||
int digit = current % 16;
|
||||
current = current / 16;
|
||||
chunkHeader.put(--pos, HexUtils.getHex(digit));
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getBytesWritten() {
|
||||
return buffer.getBytesWritten();
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputFilter Methods
|
||||
|
||||
@Override
|
||||
public void setResponse(Response response) {
|
||||
// NOOP: No need for parameters from response in this filter
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBuffer(HttpOutputBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
// No data buffered in this filter. Flush next buffer.
|
||||
buffer.flush();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void end() throws IOException {
|
||||
// Write end chunk
|
||||
buffer.doWrite(endChunk);
|
||||
endChunk.position(0).limit(endChunk.capacity());
|
||||
|
||||
buffer.end();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
// NOOP: Nothing to recycle
|
||||
}
|
||||
}
|
||||
184
java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Normal file
184
java/org/apache/coyote/http11/filters/GzipOutputFilter.java
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.coyote.Response;
|
||||
import org.apache.coyote.http11.HttpOutputBuffer;
|
||||
import org.apache.coyote.http11.OutputFilter;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
|
||||
/**
|
||||
* Gzip output filter.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class GzipOutputFilter implements OutputFilter {
|
||||
|
||||
protected static final Log log = LogFactory.getLog(GzipOutputFilter.class);
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
/**
|
||||
* Next buffer in the pipeline.
|
||||
*/
|
||||
protected HttpOutputBuffer buffer;
|
||||
|
||||
|
||||
/**
|
||||
* Compression output stream.
|
||||
*/
|
||||
protected GZIPOutputStream compressionStream = null;
|
||||
|
||||
|
||||
/**
|
||||
* Fake internal output stream.
|
||||
*/
|
||||
protected final OutputStream fakeOutputStream = new FakeOutputStream();
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doWrite(ByteBuffer)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doWrite(ByteChunk chunk) throws IOException {
|
||||
if (compressionStream == null) {
|
||||
compressionStream = new GZIPOutputStream(fakeOutputStream, true);
|
||||
}
|
||||
compressionStream.write(chunk.getBytes(), chunk.getStart(),
|
||||
chunk.getLength());
|
||||
return chunk.getLength();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int doWrite(ByteBuffer chunk) throws IOException {
|
||||
if (compressionStream == null) {
|
||||
compressionStream = new GZIPOutputStream(fakeOutputStream, true);
|
||||
}
|
||||
int len = chunk.remaining();
|
||||
if (chunk.hasArray()) {
|
||||
compressionStream.write(chunk.array(), chunk.arrayOffset() + chunk.position(), len);
|
||||
} else {
|
||||
byte[] bytes = new byte[len];
|
||||
chunk.put(bytes);
|
||||
compressionStream.write(bytes, 0, len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getBytesWritten() {
|
||||
return buffer.getBytesWritten();
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputFilter Methods
|
||||
|
||||
/**
|
||||
* Added to allow flushing to happen for the gzip'ed outputstream
|
||||
*/
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if (compressionStream != null) {
|
||||
try {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Flushing the compression stream!");
|
||||
}
|
||||
compressionStream.flush();
|
||||
} catch (IOException e) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Ignored exception while flushing gzip filter", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.flush();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setResponse(Response response) {
|
||||
// NOOP: No need for parameters from response in this filter
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBuffer(HttpOutputBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void end() throws IOException {
|
||||
if (compressionStream == null) {
|
||||
compressionStream = new GZIPOutputStream(fakeOutputStream, true);
|
||||
}
|
||||
compressionStream.finish();
|
||||
compressionStream.close();
|
||||
buffer.end();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make the filter ready to process the next request.
|
||||
*/
|
||||
@Override
|
||||
public void recycle() {
|
||||
// Set compression stream to null
|
||||
compressionStream = null;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------- FakeOutputStream Inner Class
|
||||
|
||||
|
||||
protected class FakeOutputStream
|
||||
extends OutputStream {
|
||||
protected final ByteBuffer outputChunk = ByteBuffer.allocate(1);
|
||||
@Override
|
||||
public void write(int b)
|
||||
throws IOException {
|
||||
// Shouldn't get used for good performance, but is needed for
|
||||
// compatibility with Sun JDK 1.4.0
|
||||
outputChunk.put(0, (byte) (b & 0xff));
|
||||
buffer.doWrite(outputChunk);
|
||||
}
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len)
|
||||
throws IOException {
|
||||
buffer.doWrite(ByteBuffer.wrap(b, off, len));
|
||||
}
|
||||
@Override
|
||||
public void flush() throws IOException {/*NOOP*/}
|
||||
@Override
|
||||
public void close() throws IOException {/*NOOP*/}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
274
java/org/apache/coyote/http11/filters/IdentityInputFilter.java
Normal file
274
java/org/apache/coyote/http11/filters/IdentityInputFilter.java
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.coyote.InputBuffer;
|
||||
import org.apache.coyote.Request;
|
||||
import org.apache.coyote.http11.InputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.net.ApplicationBufferHandler;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* Identity input filter.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class IdentityInputFilter implements InputFilter, ApplicationBufferHandler {
|
||||
|
||||
private static final StringManager sm = StringManager.getManager(
|
||||
IdentityInputFilter.class.getPackage().getName());
|
||||
|
||||
|
||||
// -------------------------------------------------------------- Constants
|
||||
|
||||
|
||||
protected static final String ENCODING_NAME = "identity";
|
||||
protected static final ByteChunk ENCODING = new ByteChunk();
|
||||
|
||||
|
||||
// ----------------------------------------------------- Static Initializer
|
||||
|
||||
|
||||
static {
|
||||
ENCODING.setBytes(ENCODING_NAME.getBytes(StandardCharsets.ISO_8859_1),
|
||||
0, ENCODING_NAME.length());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
|
||||
/**
|
||||
* Content length.
|
||||
*/
|
||||
protected long contentLength = -1;
|
||||
|
||||
|
||||
/**
|
||||
* Remaining bytes.
|
||||
*/
|
||||
protected long remaining = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Next buffer in the pipeline.
|
||||
*/
|
||||
protected InputBuffer buffer;
|
||||
|
||||
|
||||
/**
|
||||
* ByteBuffer used to read leftover bytes.
|
||||
*/
|
||||
protected ByteBuffer tempRead;
|
||||
|
||||
|
||||
private final int maxSwallowSize;
|
||||
|
||||
|
||||
public IdentityInputFilter(int maxSwallowSize) {
|
||||
this.maxSwallowSize = maxSwallowSize;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- InputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doRead(ApplicationBufferHandler)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doRead(ByteChunk chunk) throws IOException {
|
||||
|
||||
int result = -1;
|
||||
|
||||
if (contentLength >= 0) {
|
||||
if (remaining > 0) {
|
||||
int nRead = buffer.doRead(chunk);
|
||||
if (nRead > remaining) {
|
||||
// The chunk is longer than the number of bytes remaining
|
||||
// in the body; changing the chunk length to the number
|
||||
// of bytes remaining
|
||||
chunk.setBytes(chunk.getBytes(), chunk.getStart(),
|
||||
(int) remaining);
|
||||
result = (int) remaining;
|
||||
} else {
|
||||
result = nRead;
|
||||
}
|
||||
if (nRead > 0) {
|
||||
remaining = remaining - nRead;
|
||||
}
|
||||
} else {
|
||||
// No more bytes left to be read : return -1 and clear the
|
||||
// buffer
|
||||
chunk.recycle();
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doRead(ApplicationBufferHandler handler) throws IOException {
|
||||
|
||||
int result = -1;
|
||||
|
||||
if (contentLength >= 0) {
|
||||
if (remaining > 0) {
|
||||
int nRead = buffer.doRead(handler);
|
||||
if (nRead > remaining) {
|
||||
// The chunk is longer than the number of bytes remaining
|
||||
// in the body; changing the chunk length to the number
|
||||
// of bytes remaining
|
||||
handler.getByteBuffer().limit(handler.getByteBuffer().position() + (int) remaining);
|
||||
result = (int) remaining;
|
||||
} else {
|
||||
result = nRead;
|
||||
}
|
||||
if (nRead > 0) {
|
||||
remaining = remaining - nRead;
|
||||
}
|
||||
} else {
|
||||
// No more bytes left to be read : return -1 and clear the
|
||||
// buffer
|
||||
if (handler.getByteBuffer() != null) {
|
||||
handler.getByteBuffer().position(0).limit(0);
|
||||
}
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- InputFilter Methods
|
||||
|
||||
|
||||
/**
|
||||
* Read the content length from the request.
|
||||
*/
|
||||
@Override
|
||||
public void setRequest(Request request) {
|
||||
contentLength = request.getContentLengthLong();
|
||||
remaining = contentLength;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long end() throws IOException {
|
||||
|
||||
final boolean maxSwallowSizeExceeded = (maxSwallowSize > -1 && remaining > maxSwallowSize);
|
||||
long swallowed = 0;
|
||||
|
||||
// Consume extra bytes.
|
||||
while (remaining > 0) {
|
||||
|
||||
int nread = buffer.doRead(this);
|
||||
tempRead = null;
|
||||
if (nread > 0 ) {
|
||||
swallowed += nread;
|
||||
remaining = remaining - nread;
|
||||
if (maxSwallowSizeExceeded && swallowed > maxSwallowSize) {
|
||||
// Note: We do not fail early so the client has a chance to
|
||||
// read the response before the connection is closed. See:
|
||||
// https://httpd.apache.org/docs/2.0/misc/fin_wait_2.html#appendix
|
||||
throw new IOException(sm.getString("inputFilter.maxSwallow"));
|
||||
}
|
||||
} else { // errors are handled higher up.
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// If too many bytes were read, return the amount.
|
||||
return -remaining;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Amount of bytes still available in a buffer.
|
||||
*/
|
||||
@Override
|
||||
public int available() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the next buffer in the filter pipeline.
|
||||
*/
|
||||
@Override
|
||||
public void setBuffer(InputBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make the filter ready to process the next request.
|
||||
*/
|
||||
@Override
|
||||
public void recycle() {
|
||||
contentLength = -1;
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the associated encoding; Here, the value is
|
||||
* "identity".
|
||||
*/
|
||||
@Override
|
||||
public ByteChunk getEncodingName() {
|
||||
return ENCODING;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
// Only finished if a content length is defined and there is no data
|
||||
// remaining
|
||||
return contentLength > -1 && remaining <= 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setByteBuffer(ByteBuffer buffer) {
|
||||
tempRead = buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ByteBuffer getByteBuffer() {
|
||||
return tempRead;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void expand(int size) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
175
java/org/apache/coyote/http11/filters/IdentityOutputFilter.java
Normal file
175
java/org/apache/coyote/http11/filters/IdentityOutputFilter.java
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.coyote.Response;
|
||||
import org.apache.coyote.http11.HttpOutputBuffer;
|
||||
import org.apache.coyote.http11.OutputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
|
||||
/**
|
||||
* Identity output filter.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class IdentityOutputFilter implements OutputFilter {
|
||||
|
||||
// ----------------------------------------------------- Instance Variables
|
||||
|
||||
/**
|
||||
* Content length.
|
||||
*/
|
||||
protected long contentLength = -1;
|
||||
|
||||
|
||||
/**
|
||||
* Remaining bytes.
|
||||
*/
|
||||
protected long remaining = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Next buffer in the pipeline.
|
||||
*/
|
||||
protected HttpOutputBuffer buffer;
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doWrite(ByteBuffer)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doWrite(ByteChunk chunk) throws IOException {
|
||||
|
||||
int result = -1;
|
||||
|
||||
if (contentLength >= 0) {
|
||||
if (remaining > 0) {
|
||||
result = chunk.getLength();
|
||||
if (result > remaining) {
|
||||
// The chunk is longer than the number of bytes remaining
|
||||
// in the body; changing the chunk length to the number
|
||||
// of bytes remaining
|
||||
chunk.setBytes(chunk.getBytes(), chunk.getStart(),
|
||||
(int) remaining);
|
||||
result = (int) remaining;
|
||||
remaining = 0;
|
||||
} else {
|
||||
remaining = remaining - result;
|
||||
}
|
||||
buffer.doWrite(chunk);
|
||||
} else {
|
||||
// No more bytes left to be written : return -1 and clear the
|
||||
// buffer
|
||||
chunk.recycle();
|
||||
result = -1;
|
||||
}
|
||||
} else {
|
||||
// If no content length was set, just write the bytes
|
||||
buffer.doWrite(chunk);
|
||||
result = chunk.getLength();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int doWrite(ByteBuffer chunk) throws IOException {
|
||||
|
||||
int result = -1;
|
||||
|
||||
if (contentLength >= 0) {
|
||||
if (remaining > 0) {
|
||||
result = chunk.remaining();
|
||||
if (result > remaining) {
|
||||
// The chunk is longer than the number of bytes remaining
|
||||
// in the body; changing the chunk length to the number
|
||||
// of bytes remaining
|
||||
chunk.limit(chunk.position() + (int) remaining);
|
||||
result = (int) remaining;
|
||||
remaining = 0;
|
||||
} else {
|
||||
remaining = remaining - result;
|
||||
}
|
||||
buffer.doWrite(chunk);
|
||||
} else {
|
||||
// No more bytes left to be written : return -1 and clear the
|
||||
// buffer
|
||||
chunk.position(0);
|
||||
chunk.limit(0);
|
||||
result = -1;
|
||||
}
|
||||
} else {
|
||||
// If no content length was set, just write the bytes
|
||||
result = chunk.remaining();
|
||||
buffer.doWrite(chunk);
|
||||
result -= chunk.remaining();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getBytesWritten() {
|
||||
return buffer.getBytesWritten();
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputFilter Methods
|
||||
|
||||
@Override
|
||||
public void setResponse(Response response) {
|
||||
contentLength = response.getContentLengthLong();
|
||||
remaining = contentLength;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBuffer(HttpOutputBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
// No data buffered in this filter. Flush next buffer.
|
||||
buffer.flush();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void end() throws IOException {
|
||||
buffer.end();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
contentLength = -1;
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
chunkedInputFilter.eos=Unexpected end of stream while reading request body
|
||||
chunkedInputFilter.eosTrailer=Unexpected end of stream while reading trailer headers
|
||||
chunkedInputFilter.error=No data available due to previous error
|
||||
chunkedInputFilter.invalidCrlf=Invalid end of line sequence (character other than CR or LF found)
|
||||
chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR)
|
||||
chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF)
|
||||
chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read)
|
||||
chunkedInputFilter.invalidHeader=Invalid chunk header
|
||||
chunkedInputFilter.maxExtension=maxExtensionSize exceeded
|
||||
chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
|
||||
|
||||
inputFilter.maxSwallow=maxSwallowSize exceeded
|
||||
@@ -0,0 +1,18 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
chunkedInputFilter.eos=Unerwartetes Ende des Streams beim lesen des Request Bodys.
|
||||
chunkedInputFilter.eosTrailer=Unerwartetes Ende des Eingabestroms während die Trailer-Header gelesen wurden
|
||||
chunkedInputFilter.invalidCrlfNoCR=Falsche Buchstabensequenz für Zeilenende (richtig wäre <CR><LF>)
|
||||
@@ -0,0 +1,18 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
chunkedInputFilter.eos=Fin del flujo inesperado mientras se leía la petición del cuerpo
|
||||
chunkedInputFilter.eosTrailer=Fin inesperado de stream mintras se leían las cabeceras finales
|
||||
chunkedInputFilter.invalidCrlfNoCR=Fin de linea incorrecto (CR no debe estar antes de LF)
|
||||
@@ -0,0 +1,27 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
chunkedInputFilter.eos=Fin du flux inattendue durant la lecture du corps de la requête
|
||||
chunkedInputFilter.eosTrailer=Fin inattendue de flux lors de la lecture des en-têtes de fin (trailer headers)
|
||||
chunkedInputFilter.error=Aucune donnée disponible suite à l'erreur précédente
|
||||
chunkedInputFilter.invalidCrlf=Séquence de fin de ligne invalide, un caractère autre que CR ou LF a été trouvé
|
||||
chunkedInputFilter.invalidCrlfCRCR=Séquence de fin de ligne invalide, CR CR
|
||||
chunkedInputFilter.invalidCrlfNoCR=Terminateur de ligne incorrect (manque CR devant LF)
|
||||
chunkedInputFilter.invalidCrlfNoData=Séquence de fin de ligne invalide (aucune donnée disponible en lecture)
|
||||
chunkedInputFilter.invalidHeader=En-tête de morceau (chunk) invalide
|
||||
chunkedInputFilter.maxExtension=maxExtensionSize a été dépassé
|
||||
chunkedInputFilter.maxTrailer=maxTrailerSize a été dépassé
|
||||
|
||||
inputFilter.maxSwallow=maxSwallowSize a été dépassé
|
||||
@@ -0,0 +1,27 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
chunkedInputFilter.eos=リクエストボディの読み取り中に予期せぬストリームの終端が見つかりました。
|
||||
chunkedInputFilter.eosTrailer=トレーラーヘッダーの読み込み中に突然ストリームが終了しました。
|
||||
chunkedInputFilter.error=以前のエラーのため利用できるデータがありません。
|
||||
chunkedInputFilter.invalidCrlf=無効なEOLシーケンス(CRまたはLF以外の文字が見つかりました)
|
||||
chunkedInputFilter.invalidCrlfCRCR=無効なEOLシーケンス(CRCR)
|
||||
chunkedInputFilter.invalidCrlfNoCR=不正な改行コードです (LFの前にCRがありません)。
|
||||
chunkedInputFilter.invalidCrlfNoData=無効なEOL順序(読み込み可能なデータがありません)
|
||||
chunkedInputFilter.invalidHeader=不正なチャンクヘッダーです。
|
||||
chunkedInputFilter.maxExtension=maxExtensionSizeを超過しました
|
||||
chunkedInputFilter.maxTrailer=maxTrailerSize を超過しています。
|
||||
|
||||
inputFilter.maxSwallow=maxShallowSize を超えました。
|
||||
@@ -0,0 +1,27 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
chunkedInputFilter.eos=요청의 body를 읽는 동안 예기치 않은 스트림의 끝
|
||||
chunkedInputFilter.eosTrailer=Trailer 헤더들을 읽는 중 예기치 않은 스트림의 끝
|
||||
chunkedInputFilter.error=이전 오류로 인하여 데이터가 가용하지 않습니다.
|
||||
chunkedInputFilter.invalidCrlf=유효하지 않은 행의 끝 시퀀스입니다. (CR 또는 LF가 아닌 다른 문자가 발견됨)
|
||||
chunkedInputFilter.invalidCrlfCRCR=유효하지 않은 행의 끝 시퀀스 (CRCR)
|
||||
chunkedInputFilter.invalidCrlfNoCR=유효하지 않은 라인 끝 시퀀스 (CR 바이트가 LF 바이트 전에 존재하지 않음)
|
||||
chunkedInputFilter.invalidCrlfNoData=유효하지 않은 행의 끝 시퀀스 (더 이상 읽을 데이터가 없음)
|
||||
chunkedInputFilter.invalidHeader=유효하지 않은 chunk 헤더
|
||||
chunkedInputFilter.maxExtension=maxExtensionSize 값을 초과했습니다.
|
||||
chunkedInputFilter.maxTrailer=maxTrailerSize 값을 초과했습니다.
|
||||
|
||||
inputFilter.maxSwallow=maxSwallowSize 값을 초과했습니다.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
chunkedInputFilter.eos=读取请求主体时流的意外结束
|
||||
chunkedInputFilter.eosTrailer=读取 trailer 头时出现意外的流结束
|
||||
chunkedInputFilter.error=没有数据可用由于先前的错误
|
||||
chunkedInputFilter.invalidCrlfCRCR=无效的结束的行序列(CRCR)
|
||||
chunkedInputFilter.invalidCrlfNoCR=无效的行尾结束符序列(LF前缺少CR)
|
||||
chunkedInputFilter.invalidCrlfNoData=无效的行尾序列(没有可读取的数据)
|
||||
chunkedInputFilter.maxExtension=超过最大扩展数
|
||||
chunkedInputFilter.maxTrailer=超过最大数
|
||||
|
||||
inputFilter.maxSwallow=最大吞咽数据大小超出异常
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.coyote.InputBuffer;
|
||||
import org.apache.coyote.http11.InputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.net.ApplicationBufferHandler;
|
||||
|
||||
/**
|
||||
* Input filter responsible for replaying the request body when restoring the
|
||||
* saved request after FORM authentication.
|
||||
*/
|
||||
public class SavedRequestInputFilter implements InputFilter {
|
||||
|
||||
/**
|
||||
* The original request body.
|
||||
*/
|
||||
protected ByteChunk input = null;
|
||||
|
||||
/**
|
||||
* Create a new SavedRequestInputFilter.
|
||||
*
|
||||
* @param input The saved request body to be replayed.
|
||||
*/
|
||||
public SavedRequestInputFilter(ByteChunk input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doRead(ApplicationBufferHandler)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doRead(ByteChunk chunk) throws IOException {
|
||||
if(input.getOffset()>= input.getEnd())
|
||||
return -1;
|
||||
|
||||
int writeLength = 0;
|
||||
|
||||
if (chunk.getLimit() > 0 && chunk.getLimit() < input.getLength()) {
|
||||
writeLength = chunk.getLimit();
|
||||
} else {
|
||||
writeLength = input.getLength();
|
||||
}
|
||||
|
||||
input.substract(chunk.getBuffer(), 0, writeLength);
|
||||
chunk.setOffset(0);
|
||||
chunk.setEnd(writeLength);
|
||||
|
||||
return writeLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doRead(ApplicationBufferHandler handler) throws IOException {
|
||||
if(input.getOffset()>= input.getEnd())
|
||||
return -1;
|
||||
|
||||
ByteBuffer byteBuffer = handler.getByteBuffer();
|
||||
byteBuffer.position(byteBuffer.limit()).limit(byteBuffer.capacity());
|
||||
input.substract(byteBuffer);
|
||||
|
||||
return byteBuffer.remaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content length on the request.
|
||||
*/
|
||||
@Override
|
||||
public void setRequest(org.apache.coyote.Request request) {
|
||||
request.setContentLength(input.getLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the filter ready to process the next request.
|
||||
*/
|
||||
@Override
|
||||
public void recycle() {
|
||||
input = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the associated encoding; here, the value is null.
|
||||
*/
|
||||
@Override
|
||||
public ByteChunk getEncodingName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the next buffer in the filter pipeline (has no effect).
|
||||
*/
|
||||
@Override
|
||||
public void setBuffer(InputBuffer buffer) {
|
||||
// NOOP since this filter will be providing the request body
|
||||
}
|
||||
|
||||
/**
|
||||
* Amount of bytes still available in a buffer.
|
||||
*/
|
||||
@Override
|
||||
public int available() {
|
||||
return input.getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* End the current request (has no effect).
|
||||
*/
|
||||
@Override
|
||||
public long end() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return input.getOffset() >= input.getEnd();
|
||||
}
|
||||
}
|
||||
133
java/org/apache/coyote/http11/filters/VoidInputFilter.java
Normal file
133
java/org/apache/coyote/http11/filters/VoidInputFilter.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.coyote.InputBuffer;
|
||||
import org.apache.coyote.Request;
|
||||
import org.apache.coyote.http11.InputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.apache.tomcat.util.net.ApplicationBufferHandler;
|
||||
|
||||
/**
|
||||
* Void input filter, which returns -1 when attempting a read. Used with a GET,
|
||||
* HEAD, or a similar request.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class VoidInputFilter implements InputFilter {
|
||||
|
||||
|
||||
// -------------------------------------------------------------- Constants
|
||||
|
||||
protected static final String ENCODING_NAME = "void";
|
||||
protected static final ByteChunk ENCODING = new ByteChunk();
|
||||
|
||||
|
||||
// ----------------------------------------------------- Static Initializer
|
||||
|
||||
static {
|
||||
ENCODING.setBytes(ENCODING_NAME.getBytes(StandardCharsets.ISO_8859_1),
|
||||
0, ENCODING_NAME.length());
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- InputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doRead(ApplicationBufferHandler)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doRead(ByteChunk chunk) throws IOException {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int doRead(ApplicationBufferHandler handler) throws IOException {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------- InputFilter Methods
|
||||
|
||||
/**
|
||||
* Set the associated request.
|
||||
*/
|
||||
@Override
|
||||
public void setRequest(Request request) {
|
||||
// NOOP: Request isn't used so ignore it
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the next buffer in the filter pipeline.
|
||||
*/
|
||||
@Override
|
||||
public void setBuffer(InputBuffer buffer) {
|
||||
// NOOP: No body to read
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make the filter ready to process the next request.
|
||||
*/
|
||||
@Override
|
||||
public void recycle() {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the associated encoding; Here, the value is
|
||||
* "void".
|
||||
*/
|
||||
@Override
|
||||
public ByteChunk getEncodingName() {
|
||||
return ENCODING;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* End the current request. It is acceptable to write extra bytes using
|
||||
* buffer.doWrite during the execution of this method.
|
||||
*
|
||||
* @return Should return 0 unless the filter does some content length
|
||||
* delimitation, in which case the number is the amount of extra bytes or
|
||||
* missing bytes, which would indicate an error.
|
||||
* Note: It is recommended that extra bytes be swallowed by the filter.
|
||||
*/
|
||||
@Override
|
||||
public long end() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int available() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
93
java/org/apache/coyote/http11/filters/VoidOutputFilter.java
Normal file
93
java/org/apache/coyote/http11/filters/VoidOutputFilter.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.filters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.coyote.Response;
|
||||
import org.apache.coyote.http11.HttpOutputBuffer;
|
||||
import org.apache.coyote.http11.OutputFilter;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
|
||||
/**
|
||||
* Void output filter, which silently swallows bytes written. Used with a 204
|
||||
* status (no content) or a HEAD request.
|
||||
*
|
||||
* @author Remy Maucherat
|
||||
*/
|
||||
public class VoidOutputFilter implements OutputFilter {
|
||||
|
||||
private HttpOutputBuffer buffer = null;
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputBuffer Methods
|
||||
|
||||
/**
|
||||
* @deprecated Unused. Will be removed in Tomcat 9. Use
|
||||
* {@link #doWrite(ByteBuffer)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public int doWrite(ByteChunk chunk) throws IOException {
|
||||
return chunk.getLength();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int doWrite(ByteBuffer chunk) throws IOException {
|
||||
return chunk.remaining();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getBytesWritten() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- OutputFilter Methods
|
||||
|
||||
@Override
|
||||
public void setResponse(Response response) {
|
||||
// NOOP: No need for parameters from response in this filter
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setBuffer(HttpOutputBuffer buffer) {
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
this.buffer.flush();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void end() throws IOException {
|
||||
buffer.end();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.upgrade;
|
||||
|
||||
import javax.servlet.http.HttpUpgradeHandler;
|
||||
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
||||
import org.apache.tomcat.util.net.SSLSupport;
|
||||
import org.apache.tomcat.util.net.SocketEvent;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
|
||||
|
||||
/**
|
||||
* This Tomcat specific interface is implemented by handlers that require direct
|
||||
* access to Tomcat's I/O layer rather than going through the Servlet API.
|
||||
*/
|
||||
public interface InternalHttpUpgradeHandler extends HttpUpgradeHandler {
|
||||
|
||||
SocketState upgradeDispatch(SocketEvent status);
|
||||
|
||||
void timeoutAsync(long now);
|
||||
|
||||
void setSocketWrapper(SocketWrapperBase<?> wrapper);
|
||||
|
||||
void setSslSupport(SSLSupport sslSupport);
|
||||
|
||||
void pause();
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.errorCloseFail=Failed to close InputStream cleanly after a previous error
|
||||
upgrade.sis.isFinished.ise=It is illegal to call isFinished() when the ServletInputStream is not in non-blocking mode (i.e. setReadListener() must be called first)
|
||||
upgrade.sis.isReady.ise=It is illegal to call isReady() when the ServletInputStream is not in non-blocking mode (i.e. setReadListener() must be called first)
|
||||
upgrade.sis.onErrorFail=onError processing for the registered ReadListener triggered this further error which was swallowed
|
||||
upgrade.sis.read.closed=The InputStream has been closed
|
||||
upgrade.sis.read.ise=It is illegal to call any of the read() methods in non-blocking mode without first checking that there is data available by calling isReady()
|
||||
upgrade.sis.readListener.null=It is illegal to pass null to setReadListener()
|
||||
upgrade.sis.readListener.set=It is illegal to call setReadListener() more than once for the same upgraded connection
|
||||
upgrade.sos.canWrite.ise=It is illegal to call canWrite() when the ServletOutputStream is not in non-blocking mode (i.e. setWriteListener() must be called first)
|
||||
upgrade.sos.errorCloseFail=Failed to close OutputStream cleanly after a previous error
|
||||
upgrade.sos.onErrorFail=onError processing for the registered WriteListener triggered this further error which was swallowed
|
||||
upgrade.sos.write.closed=The OutputStream has been closed
|
||||
upgrade.sos.write.ise=It is illegal to call any of the write() methods in non-blocking mode without first checking that there is space available by calling isReady()
|
||||
upgrade.sos.writeListener.null=It is illegal to pass null to setWriteListener()
|
||||
upgrade.sos.writeListener.set=It is illegal to call setWriteListener() more than once for the same upgraded connection
|
||||
|
||||
upgradeProcessor.isCloseFail=Failed to close input stream associated with upgraded connection
|
||||
upgradeProcessor.osCloseFail=Failed to close output stream associated with upgraded connection
|
||||
upgradeProcessor.requiredClose=Closing upgraded connection due to closeRequired state of streams: Input [{0}], Output [{1}]
|
||||
upgradeProcessor.stop=Closing upgraded connection as incoming socket status was STOP
|
||||
upgradeProcessor.unexpectedState=Closing upgraded connection unexpectedly as incoming socket status was [{0}]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.read.closed=Der InputStream wurde geschlossen.
|
||||
upgrade.sis.readListener.set=setReadListener() darf nicht mehr als einmal für eine Upgraded-Verbindung aufgerufen werden
|
||||
upgrade.sos.writeListener.null=setWriteListener() darf nicht mit null aufgerufen werden
|
||||
@@ -0,0 +1,20 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.read.closed=El InputStream ha sido cerrado.
|
||||
upgrade.sis.readListener.set=Es ilegal llamar a setReadListener() más de una vez para la misma conexión actualizada\n
|
||||
upgrade.sos.writeListener.null=Es ilegal pasar valor nulo a setWriteListener()\n
|
||||
|
||||
upgradeProcessor.unexpectedState=Cerrando la conexión actualizada inesperadamente debido al que el estatus del socket fue [{0}]\n
|
||||
@@ -0,0 +1,36 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.errorCloseFail=Impossible de fermer l'InputStream proprement après une précédente erreur
|
||||
upgrade.sis.isFinished.ise=Il est illégal d'appeler isFinished() quand le ServletInputStream n'est pas en mode non bloquant, c'est à dire que setReadListener() doit d'abord être appelé
|
||||
upgrade.sis.isReady.ise=il est illégal d'appeler isReady() quand le ServletInputStream n'est pas en mode non bloquant, c'est à dire que setReadListener() doit d'abord être appelé
|
||||
upgrade.sis.onErrorFail=Le traitement de onError pour le ReadListener configuré a causé cette erreur qui a été avalée
|
||||
upgrade.sis.read.closed=Le flux d'entrée (InputStream) a été fermé
|
||||
upgrade.sis.read.ise=Il est interdit d'appeler une des méthodes read() en mode non bloquant avant de d'abord vérifier qu'il y a des données disponibles en utilisant isReady()
|
||||
upgrade.sis.readListener.null=Il est illégal de passer un argument null à setReadListener()
|
||||
upgrade.sis.readListener.set=Il est interdit d'appeler setReadListener() plus d'une fois pour une même connection upgradée
|
||||
upgrade.sos.canWrite.ise=il est illégal d'appeler canWrite() quand le ServletOutputStream n'est pas en mode non bloquant, c'est à dire que setWriteListener() doit d'abord être appelé
|
||||
upgrade.sos.errorCloseFail=Impossible de fermer l'OutputStream proprement après une précédente erreur
|
||||
upgrade.sos.onErrorFail=Le traitement de onError pour le WriteListener configuré a causé cette erreur qui a été avalée
|
||||
upgrade.sos.write.closed=L'OutputSteam a été fermée
|
||||
upgrade.sos.write.ise=Il est interdit d'appeler une des méthodes write() en mode non bloquant avant de d'abord vérifier qu'il y a de la place disponible en utilisant isReady()
|
||||
upgrade.sos.writeListener.null=Il est illégal de passer un argument null à setWriteListener()
|
||||
upgrade.sos.writeListener.set=Il est interdit d'appeler setWriteListener() plus d'une fois pour une même connection upgradée
|
||||
|
||||
upgradeProcessor.isCloseFail=Impossible de fermer l'InputStream associée avec la connection upgradée
|
||||
upgradeProcessor.osCloseFail=Impossible de fermer l'OutputStream associée avec la connection upgradée
|
||||
upgradeProcessor.requiredClose=Fermeture de la connection upgradée à cause de l''état du closeRequired des flux: Entrée [{0}] Sortie [{1}]
|
||||
upgradeProcessor.stop=Fermeture de la connection upgradée car l'état du socket est STOP
|
||||
upgradeProcessor.unexpectedState=Fermeture inattendue de la connection upgradée alors que le statut du socket en lecture est [{0}]
|
||||
@@ -0,0 +1,36 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.errorCloseFail=直前のエラーの後に完全にInputStreamを閉じることができませんでした。
|
||||
upgrade.sis.isFinished.ise=ノンブロッキングモードではない ServletInputStream の isFinished() を呼び出すことはできません。(すなわち最初に setReadListener() を呼び出さなければなりません。)
|
||||
upgrade.sis.isReady.ise=ServletInputStreamが非ブロッキングモードでない場合(つまり、最初にsetReadListener()を呼び出さなければならない場合)isReady()を呼び出すことはできません。
|
||||
upgrade.sis.onErrorFail=登録されたReadListenerのonError処理により、さらなるエラーがトリガされました。エラーは飲み込まれました。
|
||||
upgrade.sis.read.closed=InputStream はすでに切断されています。
|
||||
upgrade.sis.read.ise=isReady()を呼び出すことによって利用可能なデータがあることを最初にチェックすることなく、非ブロックモードでread()メソッドを呼び出すことは不正です。
|
||||
upgrade.sis.readListener.null=setReadListener() には null を指定できません。
|
||||
upgrade.sis.readListener.set=アップグレードしたコネクションに何度も setReadListener() を呼び出すのは不正な操作です。
|
||||
upgrade.sos.canWrite.ise=ServletOutputStreamが非ブロッキングモードでない場合(つまり、setWriteListener()を最初に呼び出さなければならない場合)、canWrite()を呼び出すことはできません。
|
||||
upgrade.sos.errorCloseFail=以前のエラーの後にOutputStreamをきれいに閉じることができませんでした。
|
||||
upgrade.sos.onErrorFail=登録されたWriteListenerのonError処理により、これがトリガされました。さらなるエラーは飲み込まれました。
|
||||
upgrade.sos.write.closed=OutputStreamはクローズされました
|
||||
upgrade.sos.write.ise=ノンブロッキングモードでは初めに isReady() を呼び出して利用可能な領域があることを確かめなければ、あらゆる write() メソッドの呼び出しは不正になります。
|
||||
upgrade.sos.writeListener.null=setWriteListener() に null を渡すのは不正な操作です。
|
||||
upgrade.sos.writeListener.set=同じアップグレードされたコネクションに対してsetWriteListener()を複数回呼び出すことはできません。
|
||||
|
||||
upgradeProcessor.isCloseFail=アップグレードされたコネクションに関連する入力ストリームを閉じることができませんでした。
|
||||
upgradeProcessor.osCloseFail=アップグレードされた接続に関連する出力ストリームを閉じることができませんでした
|
||||
upgradeProcessor.requiredClose=ストリームのcloseRequired状態によるアップグレードされた接続のクローズ:入力[{0}]、出力[{1}]
|
||||
upgradeProcessor.stop=到着したソケットステータスがSTOPであるためにアップグレードされたコネクションを閉じます。
|
||||
upgradeProcessor.unexpectedState=ソケットの状態は [{0}] でしたがアップグレードしたコネクションは予期せぬ理由で切断しました。
|
||||
@@ -0,0 +1,36 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.errorCloseFail=이전 오류 발생 이후, InputStream을 깨끗하게 닫지 못했습니다.
|
||||
upgrade.sis.isFinished.ise=ServletInputStream이 non-blocking 모드 안에 있지 않을 때, isFinished()를 호출하는 것은 불허됩니다. (즉, setReadListener()가 먼저 호출되어야만 합니다.)
|
||||
upgrade.sis.isReady.ise=ServletInputStream이 non-blocking 모드 안에 있지 않을 때, isReady()를 호출하는 것은 불허됩니다. (즉 setReadListener()가 반드시 먼저 호출되어야 합니다.)
|
||||
upgrade.sis.onErrorFail=등록된 ReadListener를 위한 onError 처리가 더많은 오류를 유발시켰습니다. 이 추가 오류는 별도로 표출되지 않습니다.
|
||||
upgrade.sis.read.closed=InputStream은 이미 닫혀 있습니다.
|
||||
upgrade.sis.read.ise=Non-blocking 모드에서는, 먼저 isReady()를 호출하여 가용한 데이터가 있는지 여부를 점검하지 않은 상태에서, 어떤 종류의 read() 메소드라도 호출하는 것은 불허됩니다.
|
||||
upgrade.sis.readListener.null=setReadListener()에 널을 넘기는 것은 불허됩니다.
|
||||
upgrade.sis.readListener.set=업그레이드된 동일한 연결을 위해, setReadListener()를 두 번 이상 호출하는 것은 불허됩니다.
|
||||
upgrade.sos.canWrite.ise=ServletOutputStream이 non-blocking 모드 안에 있지 않을 때, canWrite()를 호출하는 것은 불허됩니다. (즉 setWriteListener()가 반드시 먼저 호출되어야 합니다.)
|
||||
upgrade.sos.errorCloseFail=이전 오류 발생 이후, OutputStream을 깨끗하게 닫지 못했습니다.
|
||||
upgrade.sos.onErrorFail=등록된 WriteListener를 위한 onError 처리가 이 오류를 더 유발시켰습니다. 이 추가 오류는 별도로 표출되지 않습니다.
|
||||
upgrade.sos.write.closed=OutputStream이 이미 닫혀 있습니다.
|
||||
upgrade.sos.write.ise=Non-blocking 모드에서는, 먼저 isReady()를 호출하여 공간이 남아있는지 점검하지 않고, 어떤 종류의 write() 메소드들을 호출하는 것은 불허됩니다.
|
||||
upgrade.sos.writeListener.null=setWriteListener() 호출 시, 널을 넘기는 것은 불허됩니다.
|
||||
upgrade.sos.writeListener.set=동일한 업그레이드된 연결에 대하여, setWriteListener()를 두번 이상 호출하는 것은 불허됩니다.
|
||||
|
||||
upgradeProcessor.isCloseFail=업그레이드된 연결과 연관된 입력 스트림을 닫지 못했습니다.
|
||||
upgradeProcessor.osCloseFail=업그레이드된 연결과 연관된 출력 스트림을 닫지 못했습니다.
|
||||
upgradeProcessor.requiredClose=스트림들의 closeRequired 상태로 인하여, 업그레이드된 연결을 닫습니다: 입력 [{0}], 출력 [{1}]
|
||||
upgradeProcessor.stop=Incoming 소켓의 상태가 STOP임에 따라, 업그레이드된 연결을 닫습니다.
|
||||
upgradeProcessor.unexpectedState=Incoming 소켓의 상태가 [{0}](이)라서, 업그레이드된 연결을 예기치 않게 종료합니다.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.read.closed=InputStream был закрыт
|
||||
@@ -0,0 +1,26 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You 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.
|
||||
|
||||
upgrade.sis.isFinished.ise=当 ServletInputStream 不处于非阻塞模式时调用 isFinished() 是非法的(即必须首先调用 setReadListener())
|
||||
upgrade.sis.onErrorFail=对注册的readlistener的错误处理触发了这个进一步的错误,该错误被吞入
|
||||
upgrade.sis.read.closed=InputStream 已被关闭
|
||||
upgrade.sis.read.ise=在非阻塞模式下调用任何read()方法而不首先通过调用isready()检查是否有可用的数据是非法的
|
||||
upgrade.sis.readListener.set=在同一个upgraded连接上调用多次setReadListener()函数是非法的
|
||||
upgrade.sos.onErrorFail=对注册的WriteListener 的错误处理触发了这个进一步的错误,该错误被吞入
|
||||
upgrade.sos.write.closed=输出流已被关闭
|
||||
upgrade.sos.write.ise=在非阻塞模式下调用任何写()方法都是非法的,而无需首先检查是否有可用的空间,只需调用isreadi()
|
||||
upgrade.sos.writeListener.null=对setWriteListener()传递null是非法的
|
||||
|
||||
upgradeProcessor.unexpectedState=因传入套接字状态为[{0}]而意外关闭升级连接
|
||||
105
java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java
Normal file
105
java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.upgrade;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.servlet.http.WebConnection;
|
||||
|
||||
import org.apache.coyote.AbstractProcessorLight;
|
||||
import org.apache.coyote.Request;
|
||||
import org.apache.coyote.UpgradeToken;
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
|
||||
public abstract class UpgradeProcessorBase extends AbstractProcessorLight implements WebConnection {
|
||||
|
||||
protected static final int INFINITE_TIMEOUT = -1;
|
||||
|
||||
private final UpgradeToken upgradeToken;
|
||||
|
||||
public UpgradeProcessorBase(UpgradeToken upgradeToken) {
|
||||
this.upgradeToken = upgradeToken;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------- Implemented Processor methods
|
||||
|
||||
@Override
|
||||
public final boolean isUpgrade() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UpgradeToken getUpgradeToken() {
|
||||
return upgradeToken;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void recycle() {
|
||||
// Currently a NO-OP as upgrade processors are not recycled.
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------- Processor methods that are NO-OP for upgrade
|
||||
|
||||
@Override
|
||||
public final SocketState service(SocketWrapperBase<?> socketWrapper) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final SocketState asyncPostProcess() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isAsync() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Request getRequest() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ByteBuffer getLeftoverInput() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean checkAsyncTimeoutGeneration() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ----------------- Processor methods that are NO-OP by default for upgrade
|
||||
|
||||
@Override
|
||||
public void timeoutAsync(long now) {
|
||||
// NO-OP
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.upgrade;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
|
||||
import org.apache.coyote.UpgradeToken;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
||||
import org.apache.tomcat.util.net.SSLSupport;
|
||||
import org.apache.tomcat.util.net.SocketEvent;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class UpgradeProcessorExternal extends UpgradeProcessorBase {
|
||||
|
||||
private static final Log log = LogFactory.getLog(UpgradeProcessorExternal.class);
|
||||
private static final StringManager sm = StringManager.getManager(UpgradeProcessorExternal.class);
|
||||
|
||||
private final UpgradeServletInputStream upgradeServletInputStream;
|
||||
private final UpgradeServletOutputStream upgradeServletOutputStream;
|
||||
|
||||
|
||||
public UpgradeProcessorExternal(SocketWrapperBase<?> wrapper,
|
||||
UpgradeToken upgradeToken) {
|
||||
super(upgradeToken);
|
||||
this.upgradeServletInputStream = new UpgradeServletInputStream(this, wrapper);
|
||||
this.upgradeServletOutputStream = new UpgradeServletOutputStream(this, wrapper);
|
||||
|
||||
/*
|
||||
* Leave timeouts in the hands of the upgraded protocol.
|
||||
*/
|
||||
wrapper.setReadTimeout(INFINITE_TIMEOUT);
|
||||
wrapper.setWriteTimeout(INFINITE_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Log getLog() {
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- AutoCloseable methods
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
upgradeServletInputStream.close();
|
||||
upgradeServletOutputStream.close();
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- WebConnection methods
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
return upgradeServletInputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
return upgradeServletOutputStream;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------- Implemented Processor methods
|
||||
|
||||
@Override
|
||||
public final SocketState dispatch(SocketEvent status) {
|
||||
if (status == SocketEvent.OPEN_READ) {
|
||||
upgradeServletInputStream.onDataAvailable();
|
||||
} else if (status == SocketEvent.OPEN_WRITE) {
|
||||
upgradeServletOutputStream.onWritePossible();
|
||||
} else if (status == SocketEvent.STOP) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("upgradeProcessor.stop"));
|
||||
}
|
||||
try {
|
||||
upgradeServletInputStream.close();
|
||||
} catch (IOException ioe) {
|
||||
log.debug(sm.getString("upgradeProcessor.isCloseFail", ioe));
|
||||
}
|
||||
try {
|
||||
upgradeServletOutputStream.close();
|
||||
} catch (IOException ioe) {
|
||||
log.debug(sm.getString("upgradeProcessor.osCloseFail", ioe));
|
||||
}
|
||||
return SocketState.CLOSED;
|
||||
} else {
|
||||
// Unexpected state
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("upgradeProcessor.unexpectedState"));
|
||||
}
|
||||
return SocketState.CLOSED;
|
||||
}
|
||||
if (upgradeServletInputStream.isClosed() &&
|
||||
upgradeServletOutputStream.isClosed()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("upgradeProcessor.requiredClose",
|
||||
Boolean.valueOf(upgradeServletInputStream.isClosed()),
|
||||
Boolean.valueOf(upgradeServletOutputStream.isClosed())));
|
||||
}
|
||||
return SocketState.CLOSED;
|
||||
}
|
||||
return SocketState.UPGRADED;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------- Unimplemented Processor methods
|
||||
|
||||
@Override
|
||||
public final void setSslSupport(SSLSupport sslSupport) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
// NOOP
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.upgrade;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
|
||||
import org.apache.coyote.UpgradeToken;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
|
||||
import org.apache.tomcat.util.net.SSLSupport;
|
||||
import org.apache.tomcat.util.net.SocketEvent;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
|
||||
public class UpgradeProcessorInternal extends UpgradeProcessorBase {
|
||||
|
||||
private static final Log log = LogFactory.getLog(UpgradeProcessorInternal.class);
|
||||
|
||||
private final InternalHttpUpgradeHandler internalHttpUpgradeHandler;
|
||||
|
||||
public UpgradeProcessorInternal(SocketWrapperBase<?> wrapper,
|
||||
UpgradeToken upgradeToken) {
|
||||
super(upgradeToken);
|
||||
this.internalHttpUpgradeHandler = (InternalHttpUpgradeHandler) upgradeToken.getHttpUpgradeHandler();
|
||||
/*
|
||||
* Leave timeouts in the hands of the upgraded protocol.
|
||||
*/
|
||||
wrapper.setReadTimeout(INFINITE_TIMEOUT);
|
||||
wrapper.setWriteTimeout(INFINITE_TIMEOUT);
|
||||
|
||||
internalHttpUpgradeHandler.setSocketWrapper(wrapper);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SocketState dispatch(SocketEvent status) {
|
||||
return internalHttpUpgradeHandler.upgradeDispatch(status);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void setSslSupport(SSLSupport sslSupport) {
|
||||
internalHttpUpgradeHandler.setSslSupport(sslSupport);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void pause() {
|
||||
internalHttpUpgradeHandler.pause();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Log getLog() {
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void timeoutAsync(long now) {
|
||||
internalHttpUpgradeHandler.timeoutAsync(now);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- AutoCloseable methods
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
internalHttpUpgradeHandler.destroy();
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------- WebConnection methods
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.upgrade;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
|
||||
import org.apache.coyote.ContainerThreadMarker;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.ExceptionUtils;
|
||||
import org.apache.tomcat.util.net.DispatchType;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class UpgradeServletInputStream extends ServletInputStream {
|
||||
|
||||
private static final Log log = LogFactory.getLog(UpgradeServletInputStream.class);
|
||||
private static final StringManager sm =
|
||||
StringManager.getManager(UpgradeServletInputStream.class);
|
||||
|
||||
private final UpgradeProcessorBase processor;
|
||||
private final SocketWrapperBase<?> socketWrapper;
|
||||
|
||||
private volatile boolean closed = false;
|
||||
private volatile boolean eof = false;
|
||||
// Start in blocking-mode
|
||||
private volatile Boolean ready = Boolean.TRUE;
|
||||
private volatile ReadListener listener = null;
|
||||
|
||||
|
||||
public UpgradeServletInputStream(UpgradeProcessorBase processor,
|
||||
SocketWrapperBase<?> socketWrapper) {
|
||||
this.processor = processor;
|
||||
this.socketWrapper = socketWrapper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isFinished() {
|
||||
if (listener == null) {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("upgrade.sis.isFinished.ise"));
|
||||
}
|
||||
return eof;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isReady() {
|
||||
if (listener == null) {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("upgrade.sis.isReady.ise"));
|
||||
}
|
||||
|
||||
if (eof || closed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we already know the current state, return it.
|
||||
if (ready != null) {
|
||||
return ready.booleanValue();
|
||||
}
|
||||
|
||||
try {
|
||||
ready = Boolean.valueOf(socketWrapper.isReadyForRead());
|
||||
} catch (IOException e) {
|
||||
onError(e);
|
||||
}
|
||||
return ready.booleanValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void setReadListener(ReadListener listener) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException(
|
||||
sm.getString("upgrade.sis.readListener.null"));
|
||||
}
|
||||
if (this.listener != null) {
|
||||
throw new IllegalArgumentException(
|
||||
sm.getString("upgrade.sis.readListener.set"));
|
||||
}
|
||||
if (closed) {
|
||||
throw new IllegalStateException(sm.getString("upgrade.sis.read.closed"));
|
||||
}
|
||||
|
||||
this.listener = listener;
|
||||
|
||||
// Container is responsible for first call to onDataAvailable().
|
||||
if (ContainerThreadMarker.isContainerThread()) {
|
||||
processor.addDispatch(DispatchType.NON_BLOCKING_READ);
|
||||
} else {
|
||||
socketWrapper.registerReadInterest();
|
||||
}
|
||||
|
||||
// Switching to non-blocking. Don't know if data is available.
|
||||
ready = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int read() throws IOException {
|
||||
preReadChecks();
|
||||
|
||||
return readInternal();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int readLine(byte[] b, int off, int len) throws IOException {
|
||||
preReadChecks();
|
||||
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0, c;
|
||||
|
||||
while ((c = readInternal()) != -1) {
|
||||
b[off++] = (byte) c;
|
||||
count++;
|
||||
if (c == '\n' || count == len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count > 0 ? count : -1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int read(byte[] b, int off, int len) throws IOException {
|
||||
preReadChecks();
|
||||
|
||||
try {
|
||||
int result = socketWrapper.read(listener == null, b, off, len);
|
||||
if (result == -1) {
|
||||
eof = true;
|
||||
}
|
||||
return result;
|
||||
} catch (IOException ioe) {
|
||||
close();
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
eof = true;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
|
||||
private void preReadChecks() {
|
||||
if (listener != null && (ready == null || !ready.booleanValue())) {
|
||||
throw new IllegalStateException(sm.getString("upgrade.sis.read.ise"));
|
||||
}
|
||||
if (closed) {
|
||||
throw new IllegalStateException(sm.getString("upgrade.sis.read.closed"));
|
||||
}
|
||||
// No longer know if data is available
|
||||
ready = null;
|
||||
}
|
||||
|
||||
|
||||
private int readInternal() throws IOException {
|
||||
// Single byte reads for non-blocking need special handling so all
|
||||
// single byte reads run through this method.
|
||||
byte[] b = new byte[1];
|
||||
int result;
|
||||
try {
|
||||
result = socketWrapper.read(listener == null, b, 0, 1);
|
||||
} catch (IOException ioe) {
|
||||
close();
|
||||
throw ioe;
|
||||
}
|
||||
if (result == 0) {
|
||||
return -1;
|
||||
} else if (result == -1) {
|
||||
eof = true;
|
||||
return -1;
|
||||
} else {
|
||||
return b[0] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final void onDataAvailable() {
|
||||
try {
|
||||
if (listener == null || !socketWrapper.isReadyForRead()) {
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
onError(e);
|
||||
}
|
||||
ready = Boolean.TRUE;
|
||||
ClassLoader oldCL = processor.getUpgradeToken().getContextBind().bind(false, null);
|
||||
try {
|
||||
if (!eof) {
|
||||
listener.onDataAvailable();
|
||||
}
|
||||
if (eof) {
|
||||
listener.onAllDataRead();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
ExceptionUtils.handleThrowable(t);
|
||||
onError(t);
|
||||
} finally {
|
||||
processor.getUpgradeToken().getContextBind().unbind(false, oldCL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final void onError(Throwable t) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
ClassLoader oldCL = processor.getUpgradeToken().getContextBind().bind(false, null);
|
||||
try {
|
||||
listener.onError(t);
|
||||
} catch (Throwable t2) {
|
||||
ExceptionUtils.handleThrowable(t2);
|
||||
log.warn(sm.getString("upgrade.sis.onErrorFail"), t2);
|
||||
} finally {
|
||||
processor.getUpgradeToken().getContextBind().unbind(false, oldCL);
|
||||
}
|
||||
try {
|
||||
close();
|
||||
} catch (IOException ioe) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("upgrade.sis.errorCloseFail"), ioe);
|
||||
}
|
||||
}
|
||||
ready = Boolean.FALSE;
|
||||
}
|
||||
|
||||
|
||||
final boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.upgrade;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
|
||||
import org.apache.coyote.ContainerThreadMarker;
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.ExceptionUtils;
|
||||
import org.apache.tomcat.util.net.DispatchType;
|
||||
import org.apache.tomcat.util.net.SocketWrapperBase;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class UpgradeServletOutputStream extends ServletOutputStream {
|
||||
|
||||
private static final Log log = LogFactory.getLog(UpgradeServletOutputStream.class);
|
||||
private static final StringManager sm =
|
||||
StringManager.getManager(UpgradeServletOutputStream.class);
|
||||
|
||||
private final UpgradeProcessorBase processor;
|
||||
private final SocketWrapperBase<?> socketWrapper;
|
||||
|
||||
// Used to ensure that isReady() and onWritePossible() have a consistent
|
||||
// view of buffer and registered.
|
||||
private final Object registeredLock = new Object();
|
||||
|
||||
// Used to ensure that only one thread writes to the socket at a time and
|
||||
// that buffer is consistently updated with any unwritten data after the
|
||||
// write. Note it is not necessary to hold this lock when checking if buffer
|
||||
// contains data but, depending on how the result is used, some form of
|
||||
// synchronization may be required (see fireListenerLock for an example).
|
||||
private final Object writeLock = new Object();
|
||||
|
||||
private volatile boolean flushing = false;
|
||||
|
||||
private volatile boolean closed = false;
|
||||
|
||||
// Start in blocking-mode
|
||||
private volatile WriteListener listener = null;
|
||||
|
||||
// Guarded by registeredLock
|
||||
private boolean registered = false;
|
||||
|
||||
|
||||
|
||||
public UpgradeServletOutputStream(UpgradeProcessorBase processor,
|
||||
SocketWrapperBase<?> socketWrapper) {
|
||||
this.processor = processor;
|
||||
this.socketWrapper = socketWrapper;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean isReady() {
|
||||
if (listener == null) {
|
||||
throw new IllegalStateException(
|
||||
sm.getString("upgrade.sos.canWrite.ise"));
|
||||
}
|
||||
if (closed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure isReady() and onWritePossible() have a consistent view of
|
||||
// fireListener when determining if the listener should fire
|
||||
synchronized (registeredLock) {
|
||||
if (flushing) {
|
||||
// Since flushing is true the socket must already be registered
|
||||
// for write and multiple registrations will cause problems.
|
||||
registered = true;
|
||||
return false;
|
||||
} else if (registered){
|
||||
// The socket is already registered for write and multiple
|
||||
// registrations will cause problems.
|
||||
return false;
|
||||
} else {
|
||||
boolean result = socketWrapper.isReadyForWrite();
|
||||
registered = !result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void setWriteListener(WriteListener listener) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException(
|
||||
sm.getString("upgrade.sos.writeListener.null"));
|
||||
}
|
||||
if (this.listener != null) {
|
||||
throw new IllegalArgumentException(
|
||||
sm.getString("upgrade.sos.writeListener.set"));
|
||||
}
|
||||
if (closed) {
|
||||
throw new IllegalStateException(sm.getString("upgrade.sos.write.closed"));
|
||||
}
|
||||
this.listener = listener;
|
||||
// Container is responsible for first call to onWritePossible().
|
||||
synchronized (registeredLock) {
|
||||
registered = true;
|
||||
// Container is responsible for first call to onDataAvailable().
|
||||
if (ContainerThreadMarker.isContainerThread()) {
|
||||
processor.addDispatch(DispatchType.NON_BLOCKING_WRITE);
|
||||
} else {
|
||||
socketWrapper.registerWriteInterest();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
final boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
synchronized (writeLock) {
|
||||
preWriteChecks();
|
||||
writeInternal(new byte[] { (byte) b }, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
synchronized (writeLock) {
|
||||
preWriteChecks();
|
||||
writeInternal(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
preWriteChecks();
|
||||
flushInternal(listener == null, true);
|
||||
}
|
||||
|
||||
|
||||
private void flushInternal(boolean block, boolean updateFlushing) throws IOException {
|
||||
try {
|
||||
synchronized (writeLock) {
|
||||
if (updateFlushing) {
|
||||
flushing = socketWrapper.flush(block);
|
||||
if (flushing) {
|
||||
socketWrapper.registerWriteInterest();
|
||||
}
|
||||
} else {
|
||||
socketWrapper.flush(block);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
ExceptionUtils.handleThrowable(t);
|
||||
onError(t);
|
||||
if (t instanceof IOException) {
|
||||
throw (IOException) t;
|
||||
} else {
|
||||
throw new IOException(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (closed) {
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
flushInternal((listener == null), false);
|
||||
}
|
||||
|
||||
|
||||
private void preWriteChecks() {
|
||||
if (listener != null && !socketWrapper.canWrite()) {
|
||||
throw new IllegalStateException(sm.getString("upgrade.sos.write.ise"));
|
||||
}
|
||||
if (closed) {
|
||||
throw new IllegalStateException(sm.getString("upgrade.sos.write.closed"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Must hold writeLock to call this method.
|
||||
*/
|
||||
private void writeInternal(byte[] b, int off, int len) throws IOException {
|
||||
if (listener == null) {
|
||||
// Simple case - blocking IO
|
||||
socketWrapper.write(true, b, off, len);
|
||||
} else {
|
||||
socketWrapper.write(false, b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final void onWritePossible() {
|
||||
try {
|
||||
if (flushing) {
|
||||
flushInternal(false, true);
|
||||
if (flushing) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// This may fill the write buffer in which case the
|
||||
// isReadyForWrite() call below will re-register the socket for
|
||||
// write
|
||||
flushInternal(false, false);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
onError(ioe);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure isReady() and onWritePossible() have a consistent view
|
||||
// of buffer and fireListener when determining if the listener
|
||||
// should fire
|
||||
boolean fire = false;
|
||||
synchronized (registeredLock) {
|
||||
if (socketWrapper.isReadyForWrite()) {
|
||||
registered = false;
|
||||
fire = true;
|
||||
} else {
|
||||
registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fire) {
|
||||
ClassLoader oldCL = processor.getUpgradeToken().getContextBind().bind(false, null);
|
||||
try {
|
||||
listener.onWritePossible();
|
||||
} catch (Throwable t) {
|
||||
ExceptionUtils.handleThrowable(t);
|
||||
onError(t);
|
||||
} finally {
|
||||
processor.getUpgradeToken().getContextBind().unbind(false, oldCL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final void onError(Throwable t) {
|
||||
if (listener == null) {
|
||||
return;
|
||||
}
|
||||
ClassLoader oldCL = processor.getUpgradeToken().getContextBind().bind(false, null);
|
||||
try {
|
||||
listener.onError(t);
|
||||
} catch (Throwable t2) {
|
||||
ExceptionUtils.handleThrowable(t2);
|
||||
log.warn(sm.getString("upgrade.sos.onErrorFail"), t2);
|
||||
} finally {
|
||||
processor.getUpgradeToken().getContextBind().unbind(false, oldCL);
|
||||
}
|
||||
try {
|
||||
close();
|
||||
} catch (IOException ioe) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(sm.getString("upgrade.sos.errorCloseFail"), ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user