jetty-9 - HTTP client: added HttpClient.POST() utility method.

This commit is contained in:
Simone Bordet 2012-09-20 17:05:09 +02:00
parent bfe08d1a99
commit 92c93e2868
6 changed files with 191 additions and 35 deletions

View File

@ -44,6 +44,7 @@ import org.eclipse.jetty.client.api.CookieStore;
import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.MappedByteBufferPool;
@ -223,6 +224,16 @@ public class HttpClient extends AggregateLifeCycle
return newRequest(uri).send();
}
public Request POST(String uri)
{
return POST(URI.create(uri));
}
public Request POST(URI uri)
{
return newRequest(uri).method(HttpMethod.POST);
}
public Request newRequest(String host, int port)
{
return newRequest(URI.create(address("http", host, port)));
@ -280,7 +291,7 @@ public class HttpClient extends AggregateLifeCycle
return new ArrayList<Destination>(destinations.values());
}
public void send(Request request, Response.Listener listener)
protected void send(Request request, Response.Listener listener)
{
String scheme = request.scheme().toLowerCase();
if (!Arrays.asList("http", "https").contains(scheme))

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.client;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
@ -29,13 +32,16 @@ import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -120,6 +126,7 @@ public class HttpConnection extends AbstractConnection implements Connection
if (request.idleTimeout() <= 0)
request.idleTimeout(client.getIdleTimeout());
HttpMethod method = request.method();
HttpVersion version = request.version();
HttpFields headers = request.headers();
ContentProvider content = request.content();
@ -127,7 +134,64 @@ public class HttpConnection extends AbstractConnection implements Connection
// Make sure the path is there
String path = request.path();
if (path.matches("\\s*"))
request.path("/");
{
path = "/";
request.path(path);
}
Fields fields = request.params();
if (!fields.isEmpty())
{
StringBuilder params = new StringBuilder();
for (Iterator<Fields.Field> fieldIterator = fields.iterator(); fieldIterator.hasNext();)
{
Fields.Field field = fieldIterator.next();
String[] values = field.values();
for (int i = 0; i < values.length; ++i)
{
if (i > 0)
params.append("&");
params.append(field.name()).append("=");
params.append(urlEncode(values[i]));
}
if (fieldIterator.hasNext())
params.append("&");
}
// Behave as a GET, adding the params to the path, if it's a POST with some content
if (method == HttpMethod.POST && request.content() != null)
method = HttpMethod.GET;
switch (method)
{
case GET:
{
path += "?";
path += params.toString();
request.path(path);
break;
}
case POST:
{
request.header(HttpHeader.CONTENT_TYPE.asString(), MimeTypes.Type.FORM_ENCODED.asString());
request.content(new StringContentProvider(params.toString()));
break;
}
}
}
// If we are HTTP 1.1, add the Host header
if (version.getVersion() > 10)
{
if (!headers.containsKey(HttpHeader.HOST.asString()))
{
String value = request.host();
int port = request.port();
if (port > 0)
value += ":" + port;
headers.put(HttpHeader.HOST, value);
}
}
// Add content headers
if (content != null)
@ -181,18 +245,18 @@ public class HttpConnection extends AbstractConnection implements Connection
headers.put(HttpHeader.ACCEPT_ENCODING, value.toString());
}
}
}
// If we are HTTP 1.1, add the Host header
if (version.getVersion() > 10)
private String urlEncode(String value)
{
String encoding = "UTF-8";
try
{
if (!headers.containsKey(HttpHeader.HOST.asString()))
{
String value = request.host();
int port = request.port();
if (port > 0)
value += ":" + port;
headers.put(HttpHeader.HOST, value);
}
return URLEncoder.encode(value, encoding);
}
catch (UnsupportedEncodingException e)
{
throw new UnsupportedCharsetException(encoding);
}
}

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.client;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Iterator;
@ -33,7 +32,6 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -95,27 +93,7 @@ public class HttpSender
{
case NEED_INFO:
{
String path = request.path();
Fields fields = request.params();
if (!fields.isEmpty())
{
path += "?";
for (Iterator<Fields.Field> fieldIterator = fields.iterator(); fieldIterator.hasNext();)
{
Fields.Field field = fieldIterator.next();
String[] values = field.values();
for (int i = 0; i < values.length; ++i)
{
if (i > 0)
path += "&";
path += field.name() + "=";
path += URLEncoder.encode(values[i], "UTF-8");
}
if (fieldIterator.hasNext())
path += "&";
}
}
info = new HttpGenerator.RequestInfo(request.version(), request.headers(), contentLength, request.method().asString(), path);
info = new HttpGenerator.RequestInfo(request.version(), request.headers(), contentLength, request.method().asString(), request.path());
break;
}
case NEED_HEADER:

View File

@ -0,0 +1,34 @@
//
// ========================================================================
// Copyright (c) 1995-2012 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.util;
import java.nio.charset.Charset;
public class StringContentProvider extends BytesContentProvider
{
public StringContentProvider(String content)
{
this(content, "UTF-8");
}
public StringContentProvider(String content, String encoding)
{
super(content.getBytes(Charset.forName(encoding)));
}
}

View File

@ -43,6 +43,7 @@ import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.BytesContentProvider;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@ -214,6 +215,67 @@ public class HttpClientTest extends AbstractHttpClientServerTest
Assert.assertEquals(value11 + value12 + value2, content);
}
@Test
public void test_POST_WithParameters() throws Exception
{
final String paramName = "a";
final String paramValue = "\u20AC";
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
String value = request.getParameter(paramName);
if (paramValue.equals(value))
{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/plain");
response.getOutputStream().print(value);
}
}
});
ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort())
.param(paramName, paramValue).send().get(5, TimeUnit.SECONDS);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.status());
Assert.assertEquals(paramValue, new String(response.content(), "UTF-8"));
}
@Test
public void test_POST_WithParameters_WithContent() throws Exception
{
final byte[] content = {0, 1, 2, 3};
final String paramName = "a";
final String paramValue = "\u20AC";
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
String value = request.getParameter(paramName);
if (paramValue.equals(value))
{
response.setCharacterEncoding("UTF-8");
response.setContentType("text/plain");
response.getOutputStream().write(content);
}
}
});
ContentResponse response = client.POST(scheme + "://localhost:" + connector.getLocalPort() + "/?b=1")
.param(paramName, paramValue)
.content(new BytesContentProvider(content))
.send().get(5, TimeUnit.SECONDS);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.status());
Assert.assertArrayEquals(content, response.content());
}
@Test
public void test_QueuedRequest_IsSent_WhenPreviousRequestSucceeded() throws Exception
{

View File

@ -96,6 +96,13 @@ public class Usage
Assert.assertEquals(200, response.status());
}
@Test
public void testPOSTWithParams() throws Exception
{
HttpClient client = new HttpClient();
client.POST("http://localhost:8080").param("a", "\u20AC").send();
}
@Test
public void testRequestListener() throws Exception
{