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:
parent
87c21752a0
commit
4912c23732
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue