297783 Handle HEAD reponses in HttpClient

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1157 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2009-12-17 03:31:26 +00:00
parent 87c21752a0
commit 4912c23732
4 changed files with 322 additions and 2 deletions

View File

@ -3,6 +3,7 @@ jetty-7.0.2-SNAPSHOT
+ 290765 Reset input for HttpExchange retry. + 290765 Reset input for HttpExchange retry.
+ 296765 JMX Connector Server and ShutdownThread + 296765 JMX Connector Server and ShutdownThread
+ 297421 Hide server/system classes from WebAppClassLoader.getResources + 297421 Hide server/system classes from WebAppClassLoader.getResources
+ 297783 Handle HEAD reponses in HttpClient
+ JETTY-1156 SSL blocking close with JVM Bug busy key fix + JETTY-1156 SSL blocking close with JVM Bug busy key fix
+ JETTY-1157 Don't hold array passed in write(byte[]) + JETTY-1157 Don't hold array passed in write(byte[])
+ COMETD-46 reset ContentExchange response content on resend + COMETD-46 reset ContentExchange response content on resend

View File

@ -23,6 +23,7 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeaderValues; import org.eclipse.jetty.http.HttpHeaderValues;
import org.eclipse.jetty.http.HttpHeaders; import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.HttpVersions; import org.eclipse.jetty.http.HttpVersions;
@ -404,7 +405,9 @@ public class HttpConnection implements Connection
auth.setCredentials(_exchange); auth.setCredentials(_exchange);
} }
_generator.setRequest(_exchange.getMethod(), uri); String method=_exchange.getMethod();
_generator.setRequest(method, uri);
_parser.setHeadResponse(HttpMethods.HEAD.equalsIgnoreCase(method));
HttpFields requestHeaders = _exchange.getRequestFields(); HttpFields requestHeaders = _exchange.getRequestFields();
if (_exchange.getVersion() >= HttpVersions.HTTP_1_1_ORDINAL) if (_exchange.getVersion() >= HttpVersions.HTTP_1_1_ORDINAL)

View File

@ -0,0 +1,287 @@
// ========================================================================
// Copyright (c) 2009-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.client;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.IO;
public class ContentExchangeTest
extends TestCase
{
private static String _content0 =
"Hello World";
private static String _content =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
"Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+
"at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+
"velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+
"Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+
"eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+
"sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+
"consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private File _docRoot;
private Server _server;
private HttpClient _client;
private Realm _realm;
private String _protocol;
private String _requestUrl;
public void setUp()
throws Exception
{
_docRoot = new File("target/test-output/docroot/");
_docRoot.mkdirs();
_docRoot.deleteOnExit();
File content = new File(_docRoot,"content.txt");
FileOutputStream out = new FileOutputStream(content);
out.write(_content0.getBytes("utf-8"));
out.close();
_server = new Server();
configureServer(_server);
_server.start();
int port = _server.getConnectors()[0].getLocalPort();
_requestUrl = _protocol+"://localhost:"+port+ "/content.txt";
}
public void tearDown()
throws Exception
{
if (_server != null)
{
_server.stop();
_server = null;
}
}
public void testPut() throws Exception
{
startClient(_realm);
ContentExchange putExchange = new ContentExchange();
putExchange.setURL(_requestUrl);
putExchange.setMethod(HttpMethods.PUT);
putExchange.setRequestContent(new ByteArrayBuffer(_content.getBytes()));
_client.send(putExchange);
int state = putExchange.waitForDone();
int responseStatus = putExchange.getResponseStatus();
stopClient();
boolean statusOk = (responseStatus == 200 || responseStatus == 201);
assertTrue(statusOk);
String content = IO.toString(new FileInputStream(new File(_docRoot,"content.txt")));
assertEquals(_content,content);
}
public void testGet() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(_requestUrl);
getExchange.setMethod(HttpMethods.GET);
_client.send(getExchange);
int state = getExchange.waitForDone();
String content = "";
int responseStatus = getExchange.getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
content = getExchange.getResponseContent();
}
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
assertEquals(_content0,content);
}
public void testHead() throws Exception
{
startClient(_realm);
ContentExchange getExchange = new ContentExchange();
getExchange.setURL(_requestUrl);
getExchange.setMethod(HttpMethods.HEAD);
_client.send(getExchange);
int state = getExchange.waitForDone();
int responseStatus = getExchange.getResponseStatus();
stopClient();
assertEquals(HttpStatus.OK_200,responseStatus);
}
protected void configureServer(Server server)
throws Exception
{
setProtocol("http");
SelectChannelConnector connector = new SelectChannelConnector();
server.addConnector(connector);
Handler handler = new PutHandler(getBasePath());
ServletContextHandler root = new ServletContextHandler();
root.setContextPath("/");
root.setResourceBase(_docRoot.getAbsolutePath());
ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );
servletHolder.setInitParameter( "gzip", "true" );
root.addServlet( servletHolder, "/*" );
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]{handler, root});
server.setHandler( handlers );
}
protected void startClient(Realm realm)
throws Exception
{
_client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
if (realm != null)
_client.setRealmResolver(new SimpleRealmResolver(realm));
_client.start();
}
protected void stopClient()
throws Exception
{
if (_client != null)
{
_client.stop();
_client = null;
}
}
protected String getBasePath()
{
return _docRoot.getAbsolutePath();
}
protected void setProtocol(String protocol)
{
_protocol = protocol;
}
protected void setRealm(Realm realm)
{
_realm = realm;
}
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer=new byte[1024];
int len;
while ((len=in.read(buffer))>=0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println(e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
protected static class PutHandler extends AbstractHandler {
private final String resourcePath;
public PutHandler(String repositoryPath) {
this.resourcePath = repositoryPath;
}
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
if (baseRequest.isHandled() || !baseRequest.getMethod().equals("PUT")) {
return;
}
baseRequest.setHandled(true);
File file = new File(resourcePath, URLDecoder.decode(request.getPathInfo()));
file.getParentFile().mkdirs();
file.deleteOnExit();
FileOutputStream out = new FileOutputStream(file);
ServletInputStream in = request.getInputStream();
try
{
copyStream( in, out );
}
finally
{
in.close();
out.close();
}
response.setStatus(HttpServletResponse.SC_CREATED);
}
}
}

View File

@ -30,6 +30,14 @@ import org.eclipse.jetty.util.log.Log;
/** /**
* *
*/ */
/* ------------------------------------------------------------ */
/**
*/
/* ------------------------------------------------------------ */
/**
*/
public class HttpParser implements Parser public class HttpParser implements Parser
{ {
// States // States
@ -76,6 +84,7 @@ public class HttpParser implements Parser
protected long _contentPosition; protected long _contentPosition;
protected int _chunkLength; protected int _chunkLength;
protected int _chunkPosition; protected int _chunkPosition;
private boolean _headResponse;
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/** /**
@ -116,12 +125,22 @@ public class HttpParser implements Parser
{ {
return _contentLength; return _contentLength;
} }
/* ------------------------------------------------------------ */
public long getContentRead() public long getContentRead()
{ {
return _contentPosition; return _contentPosition;
} }
/* ------------------------------------------------------------ */
/** Set if a HEAD response is expected
* @param head
*/
public void setHeadResponse(boolean head)
{
_headResponse=head;
}
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
public int getState() public int getState()
{ {
@ -702,6 +721,15 @@ public class HttpParser implements Parser
// ========================== // ==========================
// Handle HEAD response
if (_responseStatus>0 && _headResponse)
{
_state=STATE_END;
_handler.messageComplete(_contentLength);
}
// ==========================
// Handle _content // Handle _content
length=_buffer.length(); length=_buffer.length();
Buffer chunk; Buffer chunk;
@ -924,6 +952,7 @@ public class HttpParser implements Parser
} }
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
public void reset(boolean returnBuffers) public void reset(boolean returnBuffers)
{ {