moved http/1.1 isms out of HttpChannel into HttpConnection
This commit is contained in:
parent
5883123d07
commit
b38bae36f1
|
@ -236,8 +236,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
//restore the original request's method on this request
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Restoring original method {} for {} with method {}", method, juri,httpRequest.getMethod());
|
||||
Request base_request = HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
HttpMethod m = HttpMethod.fromString(method);
|
||||
base_request.setMethod(m,m.asString());
|
||||
base_request.setMethod(method);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -67,7 +67,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
|||
* HttpTransport.completed().
|
||||
*
|
||||
*/
|
||||
public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, HttpParser.ProxyHandler
|
||||
public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(HttpChannel.class);
|
||||
private static final ThreadLocal<HttpChannel<?>> __currentChannel = new ThreadLocal<>();
|
||||
|
@ -102,9 +102,6 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
private final Request _request;
|
||||
private final Response _response;
|
||||
private HttpVersion _version = HttpVersion.HTTP_1_1;
|
||||
private boolean _expect = false;
|
||||
private boolean _expect100Continue = false;
|
||||
private boolean _expect102Processing = false;
|
||||
|
||||
public HttpChannel(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInput<T> input)
|
||||
{
|
||||
|
@ -201,32 +198,12 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
*/
|
||||
public void continue100(int available) throws IOException
|
||||
{
|
||||
// If the client is expecting 100 CONTINUE, then send it now.
|
||||
// TODO: consider using an AtomicBoolean ?
|
||||
if (isExpecting100Continue())
|
||||
{
|
||||
_expect100Continue = false;
|
||||
|
||||
// is content missing?
|
||||
if (available == 0)
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IOException("Committed before 100 Continues");
|
||||
|
||||
// TODO: break this dependency with HttpGenerator
|
||||
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
|
||||
if (!committed)
|
||||
throw new IOException("Concurrent commit while trying to send 100-Continue");
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
_committed.set(false);
|
||||
_expect = false;
|
||||
_expect100Continue = false;
|
||||
_expect102Processing = false;
|
||||
_request.recycle();
|
||||
_response.recycle();
|
||||
}
|
||||
|
@ -458,12 +435,12 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
|
||||
public boolean isExpecting100Continue()
|
||||
{
|
||||
return _expect100Continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isExpecting102Processing()
|
||||
{
|
||||
return _expect102Processing;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -478,22 +455,9 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
|
||||
{
|
||||
_request.setAttribute("PROXY", protocol);
|
||||
_request.setServerName(sAddr);
|
||||
_request.setServerPort(dPort);
|
||||
_request.setRemoteAddr(InetSocketAddress.createUnresolved(sAddr,sPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startRequest(String method, HttpURI uri, HttpVersion version)
|
||||
{
|
||||
_expect = false;
|
||||
_expect100Continue = false;
|
||||
_expect102Processing = false;
|
||||
|
||||
_request.setTimeStamp(System.currentTimeMillis());
|
||||
_request.setMethod(method);
|
||||
|
||||
|
@ -515,7 +479,7 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
|
||||
if (info == null)
|
||||
{
|
||||
if( path==null && uri.getScheme()!=null &&uri.getHost()!=null)
|
||||
if( path==null && uri.getScheme()!=null && uri.getHost()!=null)
|
||||
{
|
||||
info = "/";
|
||||
_request.setRequestURI("");
|
||||
|
@ -526,8 +490,9 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
_request.setPathInfo(info);
|
||||
_version = version == null ? HttpVersion.HTTP_0_9 : version;
|
||||
_version = version;
|
||||
_request.setHttpVersion(_version);
|
||||
|
||||
return false;
|
||||
|
@ -544,46 +509,6 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
{
|
||||
switch (header)
|
||||
{
|
||||
case EXPECT:
|
||||
if (_version.getVersion()>=HttpVersion.HTTP_1_1.getVersion())
|
||||
{
|
||||
HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value);
|
||||
switch (expect == null ? HttpHeaderValue.UNKNOWN : expect)
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
String[] values = value.split(",");
|
||||
for (int i = 0; values != null && i < values.length; i++)
|
||||
{
|
||||
expect = HttpHeaderValue.CACHE.get(values[i].trim());
|
||||
if (expect == null)
|
||||
_expect = true;
|
||||
else
|
||||
{
|
||||
switch (expect)
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
default:
|
||||
_expect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CONTENT_TYPE:
|
||||
MimeTypes.Type mime = MimeTypes.CACHE.get(value);
|
||||
String charset = (mime == null || mime.getCharset() == null) ? MimeTypes.getCharsetFromContentType(value) : mime.getCharset().toString();
|
||||
|
@ -614,31 +539,9 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
|
|||
public boolean headerComplete()
|
||||
{
|
||||
_requests.incrementAndGet();
|
||||
switch (_version)
|
||||
{
|
||||
case HTTP_0_9:
|
||||
break;
|
||||
|
||||
case HTTP_1_0:
|
||||
if (_configuration.getSendDateHeader())
|
||||
_response.getHttpFields().put(_connector.getServer().getDateField());
|
||||
break;
|
||||
|
||||
case HTTP_1_1:
|
||||
if (_configuration.getSendDateHeader())
|
||||
_response.getHttpFields().put(_connector.getServer().getDateField());
|
||||
|
||||
if (_expect)
|
||||
{
|
||||
badMessage(HttpStatus.EXPECTATION_FAILED_417,null);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
// TODO make this a better field for h2 hpack generation
|
||||
if (_configuration.getSendDateHeader())
|
||||
_response.getHttpFields().put(_connector.getServer().getDateField());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,263 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
|
||||
/**
|
||||
* A HttpChannel customized to be transported over the HTTP/1 protocol
|
||||
*/
|
||||
class HttpChannelOverHttp extends HttpChannel<ByteBuffer> implements HttpParser.ProxyHandler
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final HttpConnection _httpConnection;
|
||||
private boolean _expect = false;
|
||||
private boolean _expect100Continue = false;
|
||||
private boolean _expect102Processing = false;
|
||||
|
||||
public HttpChannelOverHttp(HttpConnection httpConnection, Connector connector, HttpConfiguration config, EndPoint endPoint, HttpTransport transport, HttpInput<ByteBuffer> input)
|
||||
{
|
||||
super(connector,config,endPoint,transport,input);
|
||||
_httpConnection = httpConnection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
_expect = false;
|
||||
_expect100Continue = false;
|
||||
_expect102Processing = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpecting100Continue()
|
||||
{
|
||||
return _expect100Continue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpecting102Processing()
|
||||
{
|
||||
return _expect102Processing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startRequest(String method, HttpURI uri, HttpVersion version)
|
||||
{
|
||||
_expect = false;
|
||||
_expect100Continue = false;
|
||||
_expect102Processing = false;
|
||||
return super.startRequest(method,uri,version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
|
||||
{
|
||||
Request request = getRequest();
|
||||
request.setAttribute("PROXY", protocol);
|
||||
request.setServerName(sAddr);
|
||||
request.setServerPort(dPort);
|
||||
request.setRemoteAddr(InetSocketAddress.createUnresolved(sAddr,sPort));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean parsedHeader(HttpField field)
|
||||
{
|
||||
HttpHeader header=field.getHeader();
|
||||
String value=field.getValue();
|
||||
if (getRequest().getHttpVersion().getVersion()==HttpVersion.HTTP_1_1.getVersion() && header == HttpHeader.EXPECT)
|
||||
{
|
||||
HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value);
|
||||
switch (expect == null ? HttpHeaderValue.UNKNOWN : expect)
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
String[] values = value.split(",");
|
||||
for (int i = 0; values != null && i < values.length; i++)
|
||||
{
|
||||
expect = HttpHeaderValue.CACHE.get(values[i].trim());
|
||||
if (expect == null)
|
||||
_expect = true;
|
||||
else
|
||||
{
|
||||
switch (expect)
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
default:
|
||||
_expect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.parsedHeader(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the associated response has the Expect header set to 100 Continue,
|
||||
* then accessing the input stream indicates that the handler/servlet
|
||||
* is ready for the request body and thus a 100 Continue response is sent.
|
||||
*
|
||||
* @throws IOException if the InputStream cannot be created
|
||||
*/
|
||||
@Override
|
||||
public void continue100(int available) throws IOException
|
||||
{
|
||||
// If the client is expecting 100 CONTINUE, then send it now.
|
||||
// TODO: consider using an AtomicBoolean ?
|
||||
if (isExpecting100Continue())
|
||||
{
|
||||
_expect100Continue = false;
|
||||
|
||||
// is content missing?
|
||||
if (available == 0)
|
||||
{
|
||||
if (getResponse().isCommitted())
|
||||
throw new IOException("Committed before 100 Continues");
|
||||
|
||||
// TODO: break this dependency with HttpGenerator
|
||||
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
|
||||
if (!committed)
|
||||
throw new IOException("Concurrent commit while trying to send 100-Continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void earlyEOF()
|
||||
{
|
||||
// If we have no request yet, just close
|
||||
if (getRequest().getMethod()==null)
|
||||
_httpConnection.close();
|
||||
else
|
||||
super.earlyEOF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean content(ByteBuffer item)
|
||||
{
|
||||
super.content(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void badMessage(int status, String reason)
|
||||
{
|
||||
_httpConnection._generator.setPersistent(false);
|
||||
super.badMessage(status,reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean headerComplete()
|
||||
{
|
||||
boolean persistent;
|
||||
HttpVersion version = getHttpVersion();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case HTTP_1_0:
|
||||
{
|
||||
persistent = getRequest().getHttpFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString());
|
||||
if (!persistent)
|
||||
persistent = HttpMethod.CONNECT.is(getRequest().getMethod());
|
||||
if (persistent)
|
||||
getResponse().getHttpFields().add(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE);
|
||||
break;
|
||||
}
|
||||
|
||||
case HTTP_1_1:
|
||||
{
|
||||
if (_expect)
|
||||
{
|
||||
badMessage(HttpStatus.EXPECTATION_FAILED_417,null);
|
||||
return true;
|
||||
}
|
||||
|
||||
persistent = !getRequest().getHttpFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString());
|
||||
if (!persistent)
|
||||
persistent = HttpMethod.CONNECT.is(getRequest().getMethod());
|
||||
if (!persistent)
|
||||
getResponse().getHttpFields().add(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
if (!persistent)
|
||||
_httpConnection._generator.setPersistent(false);
|
||||
|
||||
return super.headerComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleException(Throwable x)
|
||||
{
|
||||
_httpConnection._generator.setPersistent(false);
|
||||
super.handleException(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed()
|
||||
{
|
||||
getEndPoint().shutdownOutput();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean messageComplete()
|
||||
{
|
||||
super.messageComplete();
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -24,12 +24,9 @@ import java.util.concurrent.RejectedExecutionException;
|
|||
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.io.AbstractConnection;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
|
@ -56,7 +53,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
private final HttpConfiguration _config;
|
||||
private final Connector _connector;
|
||||
private final ByteBufferPool _bufferPool;
|
||||
private final HttpGenerator _generator;
|
||||
final HttpGenerator _generator;
|
||||
private final HttpChannelOverHttp _channel;
|
||||
private final HttpParser _parser;
|
||||
private volatile ByteBuffer _requestBuffer = null;
|
||||
|
@ -118,7 +115,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
|
||||
protected HttpChannelOverHttp newHttpChannel(HttpInput<ByteBuffer> httpInput)
|
||||
{
|
||||
return new HttpChannelOverHttp(_connector, _config, getEndPoint(), this, httpInput);
|
||||
return new HttpChannelOverHttp(this, _connector, _config, getEndPoint(), this, httpInput);
|
||||
}
|
||||
|
||||
protected HttpParser newHttpParser()
|
||||
|
@ -447,102 +444,6 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
}
|
||||
|
||||
|
||||
protected class HttpChannelOverHttp extends HttpChannel<ByteBuffer>
|
||||
{
|
||||
public HttpChannelOverHttp(Connector connector, HttpConfiguration config, EndPoint endPoint, HttpTransport transport, HttpInput<ByteBuffer> input)
|
||||
{
|
||||
super(connector,config,endPoint,transport,input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void earlyEOF()
|
||||
{
|
||||
// If we have no request yet, just close
|
||||
if (getRequest().getMethod()==null)
|
||||
close();
|
||||
else
|
||||
super.earlyEOF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean content(ByteBuffer item)
|
||||
{
|
||||
super.content(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void badMessage(int status, String reason)
|
||||
{
|
||||
_generator.setPersistent(false);
|
||||
super.badMessage(status,reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean headerComplete()
|
||||
{
|
||||
boolean persistent;
|
||||
HttpVersion version = getHttpVersion();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case HTTP_0_9:
|
||||
{
|
||||
persistent = false;
|
||||
break;
|
||||
}
|
||||
case HTTP_1_0:
|
||||
{
|
||||
persistent = getRequest().getHttpFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString());
|
||||
if (!persistent)
|
||||
persistent = HttpMethod.CONNECT.is(getRequest().getMethod());
|
||||
if (persistent)
|
||||
getResponse().getHttpFields().add(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE);
|
||||
break;
|
||||
}
|
||||
case HTTP_1_1:
|
||||
{
|
||||
persistent = !getRequest().getHttpFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString());
|
||||
if (!persistent)
|
||||
persistent = HttpMethod.CONNECT.is(getRequest().getMethod());
|
||||
if (!persistent)
|
||||
getResponse().getHttpFields().add(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
if (!persistent)
|
||||
_generator.setPersistent(false);
|
||||
|
||||
return super.headerComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleException(Throwable x)
|
||||
{
|
||||
_generator.setPersistent(false);
|
||||
super.handleException(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed()
|
||||
{
|
||||
getEndPoint().shutdownOutput();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean messageComplete()
|
||||
{
|
||||
super.messageComplete();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class CommitCallback extends IteratingCallback
|
||||
{
|
||||
final ByteBuffer _content;
|
||||
|
|
|
@ -102,7 +102,7 @@ public class ExtendedServerTest extends HttpServerTestBase
|
|||
@Override
|
||||
protected HttpChannelOverHttp newHttpChannel(HttpInput<ByteBuffer> httpInput)
|
||||
{
|
||||
return new HttpChannelOverHttp(getConnector(), getHttpConfiguration(), getEndPoint(), this, httpInput)
|
||||
return new HttpChannelOverHttp(this, getConnector(), getHttpConfiguration(), getEndPoint(), this, httpInput)
|
||||
{
|
||||
@Override
|
||||
public boolean startRequest(String method, HttpURI uri, HttpVersion version)
|
||||
|
|
Loading…
Reference in New Issue