Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimone Bordet2014-05-14 21:36:18 +0000
committerSimone Bordet2014-05-14 21:54:26 +0000
commitc322ed4b90b185dcdd31209f62d7b85e4637c914 (patch)
treea14cd725949bc91f9a21d73db8f97b657ec6c9da /jetty-client
parentbf7ab5d326860ae5b2049e7500abd2b950883ec0 (diff)
downloadorg.eclipse.jetty.project-c322ed4b90b185dcdd31209f62d7b85e4637c914.tar.gz
org.eclipse.jetty.project-c322ed4b90b185dcdd31209f62d7b85e4637c914.tar.xz
org.eclipse.jetty.project-c322ed4b90b185dcdd31209f62d7b85e4637c914.zip
419972 - Support sending forms (application/x-www-form-urlencoded).
Implemented introducing HttpClient.FORM() method and FormContentProvider, based on Fields.
Diffstat (limited to 'jetty-client')
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java26
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java78
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/util/TypedContentProviderTest.java141
3 files changed, 245 insertions, 0 deletions
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
index 54b82f9ba0..3486c81103 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
@@ -49,12 +49,14 @@ 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.http.HttpClientTransportOverHTTP;
+import org.eclipse.jetty.client.util.FormContentProvider;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
+import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.SocketAddressResolver;
@@ -326,6 +328,30 @@ public class HttpClient extends ContainerLifeCycle
}
/**
+ * Performs a POST request to the specified URI with the given form parameters.
+ *
+ * @param uri the URI to POST
+ * @param fields the fields composing the form name/value pairs
+ * @return the {@link ContentResponse} for the request
+ */
+ public ContentResponse FORM(String uri, Fields fields) throws InterruptedException, ExecutionException, TimeoutException
+ {
+ return FORM(URI.create(uri), fields);
+ }
+
+ /**
+ * Performs a POST request to the specified URI with the given form parameters.
+ *
+ * @param uri the URI to POST
+ * @param fields the fields composing the form name/value pairs
+ * @return the {@link ContentResponse} for the request
+ */
+ public ContentResponse FORM(URI uri, Fields fields) throws InterruptedException, ExecutionException, TimeoutException
+ {
+ return POST(uri).content(new FormContentProvider(fields)).send();
+ }
+
+ /**
* Creates a POST request to the specified URI.
*
* @param uri the URI to POST to
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java
new file mode 100644
index 0000000000..7e4784bb8c
--- /dev/null
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java
@@ -0,0 +1,78 @@
+//
+// ========================================================================
+// 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.client.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
+
+import org.eclipse.jetty.client.api.ContentProvider;
+import org.eclipse.jetty.util.Fields;
+
+/**
+ * A {@link ContentProvider} for form uploads with the
+ * "application/x-www-form-urlencoded" content type.
+ */
+public class FormContentProvider extends StringContentProvider
+{
+ public FormContentProvider(Fields fields)
+ {
+ this(fields, StandardCharsets.UTF_8);
+ }
+
+ public FormContentProvider(Fields fields, Charset charset)
+ {
+ super("application/x-www-form-urlencoded", convert(fields, charset), charset);
+ }
+
+ public static String convert(Fields fields)
+ {
+ return convert(fields, StandardCharsets.UTF_8);
+ }
+
+ public static String convert(Fields fields, Charset charset)
+ {
+ // Assume 32 chars between name and value.
+ StringBuilder builder = new StringBuilder(fields.getSize() * 32);
+ for (Fields.Field field : fields)
+ {
+ for (String value : field.getValues())
+ {
+ if (builder.length() > 0)
+ builder.append("&");
+ builder.append(field.getName()).append("=").append(encode(value, charset));
+ }
+ }
+ return builder.toString();
+ }
+
+ private static String encode(String value, Charset charset)
+ {
+ try
+ {
+ return URLEncoder.encode(value, charset.name());
+ }
+ catch (UnsupportedEncodingException x)
+ {
+ throw new UnsupportedCharsetException(charset.name());
+ }
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/util/TypedContentProviderTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/util/TypedContentProviderTest.java
new file mode 100644
index 0000000000..b8433e8f03
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/util/TypedContentProviderTest.java
@@ -0,0 +1,141 @@
+//
+// ========================================================================
+// 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.client.util;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.AbstractHttpClientServerTest;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.Fields;
+import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TypedContentProviderTest extends AbstractHttpClientServerTest
+{
+ public TypedContentProviderTest(SslContextFactory sslContextFactory)
+ {
+ super(sslContextFactory);
+ }
+
+ @Test
+ public void testFormContentProvider() throws Exception
+ {
+ final String name1 = "a";
+ final String value1 = "1";
+ final String name2 = "b";
+ final String value2 = "2";
+ final String value3 = "\u20AC";
+
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ Assert.assertEquals("POST", request.getMethod());
+ Assert.assertEquals(MimeTypes.Type.FORM_ENCODED.asString(), request.getContentType());
+ Assert.assertEquals(value1, request.getParameter(name1));
+ String[] values = request.getParameterValues(name2);
+ Assert.assertNotNull(values);
+ Assert.assertEquals(2, values.length);
+ Assert.assertThat(values, Matchers.arrayContainingInAnyOrder(value2, value3));
+ }
+ });
+
+ Fields fields = new Fields();
+ fields.put(name1, value1);
+ fields.add(name2, value2);
+ fields.add(name2, value3);
+ ContentResponse response = client.FORM(scheme + "://localhost:" + connector.getLocalPort(), fields);
+
+ Assert.assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testFormContentProviderWithDifferentContentType() throws Exception
+ {
+ final String name1 = "a";
+ final String value1 = "1";
+ final String name2 = "b";
+ final String value2 = "2";
+ Fields fields = new Fields();
+ fields.put(name1, value1);
+ fields.add(name2, value2);
+ final String content = FormContentProvider.convert(fields);
+ final String contentType = "text/plain;charset=UTF-8";
+
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ Assert.assertEquals("POST", request.getMethod());
+ Assert.assertEquals(contentType, request.getContentType());
+ Assert.assertEquals(content, IO.toString(request.getInputStream()));
+ }
+ });
+
+ ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .method(HttpMethod.POST)
+ .content(new FormContentProvider(fields))
+ .header(HttpHeader.CONTENT_TYPE, contentType)
+ .send();
+
+ Assert.assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testTypedContentProviderWithNoContentType() throws Exception
+ {
+ final String content = "data";
+
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ Assert.assertEquals("GET", request.getMethod());
+ Assert.assertNull(request.getContentType());
+ Assert.assertEquals(content, IO.toString(request.getInputStream()));
+ }
+ });
+
+ ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .content(new StringContentProvider(null, content, StandardCharsets.UTF_8))
+ .send();
+
+ Assert.assertEquals(200, response.getStatus());
+ }
+}

Back to the top