jetty-9 removed HttpException

This commit is contained in:
Greg Wilkins 2012-05-17 15:12:45 +02:00
parent 6502370426
commit b9a2661a4e
11 changed files with 307 additions and 201 deletions

View File

@ -1,88 +0,0 @@
// ========================================================================
// Copyright (c) 2006-2009 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.http;
import java.io.IOException;
public class HttpException extends IOException
{
int _status;
String _reason;
/* ------------------------------------------------------------ */
public HttpException(int status)
{
this(status,null,null);
}
/* ------------------------------------------------------------ */
public HttpException(int status,String reason)
{
this(status,reason,null);
}
/* ------------------------------------------------------------ */
public HttpException(int status,String reason, Throwable rootCause)
{
_status=status;
_reason=reason;
if (rootCause!=null)
initCause(rootCause);
}
/* ------------------------------------------------------------ */
/**
* @return Returns the reason.
*/
public String getReason()
{
return _reason;
}
/* ------------------------------------------------------------ */
/**
* @param reason The reason to set.
*/
public void setReason(String reason)
{
_reason = reason;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the status.
*/
public int getStatus()
{
return _status;
}
/* ------------------------------------------------------------ */
/**
* @param status The status to set.
*/
public void setStatus(int status)
{
_status = status;
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return ("HttpException("+_status+","+_reason+","+super.getCause()+")");
}
}

View File

@ -281,7 +281,7 @@ public class HttpParser
/* ------------------------------------------------------------------------------- */
/* Parse a request or response line
*/
private boolean parseLine(ByteBuffer buffer) throws IOException
private boolean parseLine(ByteBuffer buffer)
{
boolean return_from_parse=false;
@ -311,7 +311,8 @@ public class HttpParser
}
else if (ch < HttpTokens.SPACE && ch>=0)
{
throw new HttpException(HttpStatus.BAD_REQUEST_400);
badMessage(buffer, "No URI");
return true;
}
else
_string.append((char)ch);
@ -323,13 +324,17 @@ public class HttpParser
String version=takeString();
_version=HttpVersion.CACHE.get(version);
if (_version==null)
throw new HttpException(HttpStatus.BAD_REQUEST_400);
{
badMessage(buffer, "Unknown Version");
return true;
}
_persistent=HttpVersion.HTTP_1_1==_version;
_state=State.SPACE1;
}
else if (ch < HttpTokens.SPACE && ch>=0)
{
throw new HttpException(HttpStatus.BAD_REQUEST_400);
badMessage(buffer, "No Status");
return true;
}
else
_string.append((char)ch);
@ -352,7 +357,8 @@ public class HttpParser
}
else if (ch < HttpTokens.SPACE)
{
throw new HttpException(HttpStatus.BAD_REQUEST_400);
badMessage(buffer, _requestHandler!=null?"No URI":"No Status");
return true;
}
break;
@ -455,7 +461,10 @@ public class HttpParser
String version = takeString();
_version=HttpVersion.CACHE.get(version);
if (_version==null)
throw new HttpException(HttpStatus.BAD_REQUEST_400);
{
badMessage(buffer, "Unknown Version");
return true;
}
_eol=ch;
_persistent=HttpVersion.HTTP_1_1==_version;
@ -499,7 +508,7 @@ public class HttpParser
/*
* Parse the message headers and return true if the handler has signaled for a return
*/
private boolean parseHeaders(ByteBuffer buffer) throws IOException
private boolean parseHeaders(ByteBuffer buffer)
{
boolean return_from_parse=false;
@ -552,7 +561,8 @@ public class HttpParser
catch(NumberFormatException e)
{
LOG.ignore(e);
throw new HttpException(HttpStatus.BAD_REQUEST_400);
badMessage(buffer, "Bad Content-Length");
return true;
}
if (_contentLength <= 0)
_endOfContent=EndOfContent.NO_CONTENT;
@ -569,7 +579,10 @@ public class HttpParser
if (_valueString.endsWith(HttpHeaderValue.CHUNKED.toString()))
_endOfContent=EndOfContent.CHUNKED_CONTENT;
else if (_valueString.indexOf(HttpHeaderValue.CHUNKED.toString()) >= 0)
throw new HttpException(400,null);
{
badMessage(buffer, "Bad chunking");
return true;
}
}
break;
@ -852,9 +865,6 @@ public class HttpParser
*/
public boolean parseNext(ByteBuffer buffer) throws IOException
{
int start=-1;
State startState=null;
try
{
// process end states
@ -1056,22 +1066,21 @@ public class HttpParser
return false;
}
catch(HttpException e)
catch(Exception e)
{
_persistent=false;
_state=State.SEEKING_EOF;
throw e;
LOG.debug(e);
_handler.badMessage(e.toString());
return true;
}
finally
{
if (start>=0)
{
_string.setLength(0);
buffer.position(start);
_state=startState;
}
}
}
/* ------------------------------------------------------------------------------- */
private void badMessage(ByteBuffer buffer, String reason)
{
BufferUtil.clear(buffer);
_persistent=false;
_state=State.SEEKING_EOF;
_handler.badMessage(reason);
}
/* ------------------------------------------------------------------------------- */
@ -1142,11 +1151,11 @@ public class HttpParser
*/
public interface HttpHandler
{
public boolean content(ByteBuffer ref) throws IOException;
public boolean content(ByteBuffer ref);
public boolean headerComplete(boolean hasBody,boolean persistent) throws IOException;
public boolean headerComplete(boolean hasBody,boolean persistent);
public boolean messageComplete(long contentLength) throws IOException;
public boolean messageComplete(long contentLength);
/**
* This is the method called by parser when a HTTP Header name and value is found
@ -1154,11 +1163,12 @@ public class HttpParser
* @param name The String value of the header name
* @param value The String value of the header
* @return
* @throws IOException
*/
public boolean parsedHeader(HttpHeader header, String name, String value) throws IOException;
public boolean parsedHeader(HttpHeader header, String name, String value);
public boolean earlyEOF();
public void badMessage(String reason);
}
public interface RequestHandler extends HttpHandler
@ -1166,8 +1176,7 @@ public class HttpParser
/**
* This is the method called by parser when the HTTP request line is parsed
*/
public abstract boolean startRequest(HttpMethod method, String methodString, String uri, HttpVersion version)
throws IOException;
public abstract boolean startRequest(HttpMethod method, String methodString, String uri, HttpVersion version);
}
public interface ResponseHandler extends HttpHandler
@ -1175,8 +1184,7 @@ public class HttpParser
/**
* This is the method called by parser when the HTTP request line is parsed
*/
public abstract boolean startResponse(HttpVersion version, int status, String reason)
throws IOException;
public abstract boolean startResponse(HttpVersion version, int status, String reason);
}

View File

@ -43,7 +43,7 @@ public class HttpGeneratorServerTest
private class Handler implements HttpParser.ResponseHandler
{
@Override
public boolean content(ByteBuffer ref) throws IOException
public boolean content(ByteBuffer ref)
{
if (_content==null)
_content="";
@ -59,20 +59,20 @@ public class HttpGeneratorServerTest
}
@Override
public boolean headerComplete(boolean hasBody,boolean persistent) throws IOException
public boolean headerComplete(boolean hasBody,boolean persistent)
{
_content= null;
return false;
}
@Override
public boolean messageComplete(long contentLength) throws IOException
public boolean messageComplete(long contentLength)
{
return true;
}
@Override
public boolean parsedHeader(HttpHeader header, String name, String value) throws IOException
public boolean parsedHeader(HttpHeader header, String name, String value)
{
_hdr.add(name);
_val.add(value);
@ -80,13 +80,20 @@ public class HttpGeneratorServerTest
}
@Override
public boolean startResponse(HttpVersion version, int status, String reason) throws IOException
public boolean startResponse(HttpVersion version, int status, String reason)
{
_version=version;
_status=status;
_reason=reason;
return false;
}
@Override
public void badMessage(String reason)
{
throw new IllegalStateException(reason);
}
}

View File

@ -14,12 +14,15 @@
package org.eclipse.jetty.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
@ -456,6 +459,193 @@ public class HttpParserTest
}
@Test
public void testNoURI() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"GET\015\012"
+ "Content-Length: 0\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
parser.parseNext(buffer);
assertEquals(null,f0);
assertEquals("No URI",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testNoURI2() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"GET \015\012"
+ "Content-Length: 0\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
parser.parseNext(buffer);
assertEquals(null,f0);
assertEquals("No URI",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testUnknownReponseVersion() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"HPPT/7.7 200 OK\015\012"
+ "Content-Length: 0\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
parser.parseNext(buffer);
assertEquals(null,f0);
assertEquals("Unknown Version",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testNoStatus() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"HTTP/1.1\015\012"
+ "Content-Length: 0\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
parser.parseNext(buffer);
assertEquals(null,f0);
assertEquals("No Status",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testNoStatus2() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"HTTP/1.1 \015\012"
+ "Content-Length: 0\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
parser.parseNext(buffer);
assertEquals(null,f0);
assertEquals("No Status",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testBadRequestVersion() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"GET / HPPT/7.7\015\012"
+ "Content-Length: 0\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
parser.parseNext(buffer);
assertEquals(null,f0);
assertEquals("Unknown Version",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testBadContentLength0() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"GET / HTTP/1.0\015\012"
+ "Content-Length: abc\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
parser.parseNext(buffer);
assertEquals("GET",f0);
assertEquals("Bad Content-Length",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testBadContentLength1() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"GET / HTTP/1.0\015\012"
+ "Content-Length: 9999999999999999999999999999999999999999999999\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
parser.parseNext(buffer);
assertEquals("GET",f0);
assertEquals("Bad Content-Length",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Test
public void testBadContentLength2() throws Exception
{
ByteBuffer buffer= BufferUtil.toBuffer(
"GET / HTTP/1.0\015\012"
+ "Content-Length: 1.5\015\012"
+ "Connection: close\015\012"
+ "\015\012");
Handler handler = new Handler();
HttpParser parser= new HttpParser((HttpParser.RequestHandler)handler);
parser.parseNext(buffer);
assertEquals("GET",f0);
assertEquals("Bad Content-Length",_bad);
assertFalse(buffer.hasRemaining());
assertEquals(HttpParser.State.SEEKING_EOF,parser.getState());
}
@Before
public void init()
{
_bad=null;
_content=null;
f0=null;
f1=null;
f2=null;
hdr=null;
val=null;
h=0;
}
private String _bad;
private String _content;
private String f0;
private String f1;
@ -536,6 +726,12 @@ public class HttpParserTest
return true;
}
@Override
public void badMessage(String reason)
{
_bad=reason;
}
@Override
public boolean startResponse(HttpVersion version, int status, String reason)
{

View File

@ -19,7 +19,6 @@ import java.net.Socket;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.io.AsyncConnection;

View File

@ -26,7 +26,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.ContinuationThrowable;
import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
@ -42,7 +41,6 @@ import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.UncheckedPrintWriter;
import org.eclipse.jetty.util.ArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
@ -342,8 +340,10 @@ public abstract class HttpChannel
_uri.getPort();
info=URIUtil.canonicalPath(_uri.getDecodedPath());
if (info==null && !_request.getMethod().equals(HttpMethod.CONNECT))
throw new HttpException(400);
_request.setPathInfo(info);
{
sendError(400,null,null,true);
return;
}
if (_out!=null)
_out.reopen();
@ -371,13 +371,6 @@ public abstract class HttpChannel
error=true;
_request.setHandled(true);
}
catch (HttpException e)
{
LOG.debug(e);
error=true;
_request.setHandled(true);
_response.sendError(e.getStatus(), e.getReason());
}
catch (Throwable e)
{
async_exception=e;
@ -426,24 +419,34 @@ public abstract class HttpChannel
}
/* ------------------------------------------------------------ */
protected void sendError(final int status, final String reason, String content, boolean close) throws IOException
protected boolean sendError(final int status, final String reason, String content, boolean close)
{
if (_response.isCommitted())
throw new IllegalStateException("Committed");
return false;
_response.setStatus(status,reason);
if (close)
_responseFields.add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
ByteBuffer buffer=null;
if (content!=null)
try
{
buffer=BufferUtil.toBuffer(content,StringUtil.__UTF8_CHARSET);
_response.setContentLength(buffer.remaining());
}
_response.setStatus(status,reason);
if (close)
_responseFields.add(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
HttpGenerator.ResponseInfo info = _handler.commit();
commit(info,buffer);
ByteBuffer buffer=null;
if (content!=null)
{
buffer=BufferUtil.toBuffer(content,StringUtil.__UTF8_CHARSET);
_response.setContentLength(buffer.remaining());
}
HttpGenerator.ResponseInfo info = _handler.commit();
commit(info,buffer);
return true;
}
catch(Exception e)
{
LOG.debug("failed to sendError {} {}",status, reason, e);
}
return false;
}
/* ------------------------------------------------------------ */
@ -509,7 +512,7 @@ public abstract class HttpChannel
private class RequestHandler implements EventHandler
{
@Override
public boolean startRequest(HttpMethod httpMethod,String method, String uri, HttpVersion version) throws IOException
public boolean startRequest(HttpMethod httpMethod,String method, String uri, HttpVersion version)
{
_host = false;
_expect = false;
@ -520,30 +523,20 @@ public abstract class HttpChannel
_request.setTimeStamp(System.currentTimeMillis());
_request.setMethod(httpMethod,method);
try
{
if (httpMethod==HttpMethod.CONNECT)
_uri.parseConnect(uri);
else
_uri.parse(uri);
if (httpMethod==HttpMethod.CONNECT)
_uri.parseConnect(uri);
else
_uri.parse(uri);
_request.setUri(_uri);
_version=version==null?HttpVersion.HTTP_0_9:version;
_request.setHttpVersion(_version);
}
catch (Exception e)
{
LOG.debug(e);
if (e instanceof HttpException)
throw (HttpException)e;
throw new HttpException(HttpStatus.BAD_REQUEST_400,null,e);
}
_request.setUri(_uri);
_version=version==null?HttpVersion.HTTP_0_9:version;
_request.setHttpVersion(_version);
return false;
}
@Override
public boolean parsedHeader(HttpHeader header, String name, String value) throws IOException
public boolean parsedHeader(HttpHeader header, String name, String value)
{
if (value==null)
return false;
@ -606,7 +599,7 @@ public abstract class HttpChannel
}
@Override
public boolean headerComplete(boolean hasBody,boolean persistent) throws IOException
public boolean headerComplete(boolean hasBody,boolean persistent)
{
_requests++;
switch (_version)
@ -657,14 +650,14 @@ public abstract class HttpChannel
}
@Override
public boolean content(ByteBuffer ref) throws IOException
public boolean content(ByteBuffer ref)
{
_in.content(ref);
return true;
}
@Override
public boolean messageComplete(long contentLength) throws IOException
public boolean messageComplete(long contentLength)
{
_in.shutdownInput();
return true;
@ -682,6 +675,12 @@ public abstract class HttpChannel
return _response.commit();
}
@Override
public void badMessage(String reason)
{
sendError(HttpStatus.BAD_REQUEST_400,reason,null,true);
}
}

View File

@ -17,19 +17,12 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Timer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.print.attribute.standard.MediaSize.ISO;
import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpGenerator.Action;
import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AbstractAsyncConnection;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EofException;

View File

@ -168,7 +168,7 @@ public abstract class HttpInput extends ServletInputStream
{
}
public boolean content(ByteBuffer ref) throws IOException
public boolean content(ByteBuffer ref)
{
synchronized (_inputQ.lock())
{

View File

@ -1055,15 +1055,8 @@ public class Request implements HttpServletRequest
}
catch (NumberFormatException e)
{
try
{
if (_channel != null)
_channel.sendError(HttpStatus.BAD_REQUEST_400,"Bad Host header",null,true);
}
catch (IOException e1)
{
throw new RuntimeException(e1);
}
if (_channel != null)
_channel.sendError(HttpStatus.BAD_REQUEST_400,"Bad Host header",null,true);
}
return _serverName;
}

View File

@ -54,7 +54,6 @@ import javax.servlet.descriptor.JspConfigDescriptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Handler;
@ -1053,7 +1052,11 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
if (DispatcherType.REQUEST.equals(dispatch) && isProtectedTarget(target))
throw new HttpException(HttpServletResponse.SC_NOT_FOUND);
{
response.sendError(HttpServletResponse.SC_NOT_FOUND);
baseRequest.setHandled(true);
return;
}
// start manual inline of nextHandle(target,baseRequest,request,response);
// noinspection ConstantIfStatement
@ -1065,12 +1068,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
_handler.handle(target,baseRequest,request,response);
// end manual inline
}
catch (HttpException e)
{
LOG.debug(e);
baseRequest.setHandled(true);
response.sendError(e.getStatus(),e.getReason());
}
finally
{
// Handle more REALLY SILLY request events!

View File

@ -164,7 +164,9 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
Headers.Header version = headers.get("version");
if (method == null || uri == null || version == null)
{
throw new HttpException(HttpStatus.BAD_REQUEST_400);
}
String m = method.value();
String u = uri.value();