From 27eba7ffa3c2c90cd74547dee8cd20da1cea499a Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Wed, 7 Oct 2015 15:55:04 +0200 Subject: [PATCH 1/3] =doc,htp #18657 document Headers request values --- .../server/HeaderRequestValsExampleTest.java | 66 +++++++++++++++++++ .../request-vals/header-request-vals.rst | 33 ++++++++++ .../http/routing-dsl/request-vals/index.rst | 18 ++--- .../akka/http/javadsl/model/headers/Host.java | 8 +-- 4 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java create mode 100644 akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java new file mode 100644 index 0000000000..340819c7e6 --- /dev/null +++ b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009-2015 Typesafe Inc. + */ + +package docs.http.javadsl.server; + +import akka.http.javadsl.model.HttpRequest; +//#by-class +import akka.http.javadsl.model.headers.Host; + +//#by-class +import akka.http.javadsl.model.headers.RawHeader; +import akka.http.javadsl.server.*; +import akka.http.javadsl.server.values.Header; +import akka.http.javadsl.server.values.Headers; +import akka.http.javadsl.testkit.JUnitRouteTest; +import org.junit.Test; + +public class HeaderRequestValsExampleTest extends JUnitRouteTest { + + @Test + public void testHeaderVals() { + //#by-class + // extract the entire header instance: + RequestVal host = Headers.byClass(Host.class).instance(); + + final Route route = + route( + handleWith1(host, (ctx, h) -> + ctx.complete(String.format("Host header was: %s", h.host())) + ) + ); + + // tests: + final HttpRequest request = + HttpRequest + .GET("http://akka.io/") + .addHeader(Host.create("akka.io", 80)); + testRoute(route).run(request).assertEntity("Host header was: akka.io"); + + //#by-class + } + + @Test + public void testHeaderByName() { + //#by-name + // extract the `value` of the header: + final RequestVal XFishName = Headers.byName("X-Fish-Name").value(); + + final Route route = + route( + handleWith1(XFishName, (ctx, xFishName) -> + ctx.complete(String.format("The `X-Fish-Name` header's value was: %s", xFishName)) + ) + ); + + // tests: + final HttpRequest request = + HttpRequest + .GET("/") + .addHeader(RawHeader.create("X-Fish-Name", "Blippy")); + testRoute(route).run(request).assertEntity("The `X-Fish-Name` header's value was: Blippy"); + + //#by-name + } +} \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst new file mode 100644 index 0000000000..3f363d82c4 --- /dev/null +++ b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst @@ -0,0 +1,33 @@ +.. _header-request-vals-java: + +Request Values: Headers +======================= + +A collection of pre-defined :ref:`request-vals-java` that can be used to extract header values from incoming requests. + +Description +----------- +Header request values allow extracting ``HttpHeader`` values or concrete instances from HTTP requests. + +The ``RequestVal`` builder is made up of 2 steps, initially you need to pick which Header to extract (``byName`` or +``byClass``) and then you need to pick if the header is optionally available or required (i.e. the route should not +match if the header is not present in the request). This is done using one of the below depicted methods:: + + RequestVal instance() + RequestVal<> optionalInstance() + + RequestVal value() + RequestVal> optionalValue() + +Examples +-------- + +``Headers.byClass(Class[HttpHeader])`` + +.. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java + :include: by-class + +``Headers.byName(String)`` + +.. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java + :include: by-name diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst index e808599e77..ed8927b5d0 100644 --- a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst +++ b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst @@ -25,21 +25,21 @@ Predefined Request values akka-http provides a set of predefined request values for request data commonly accessed in a web service. -These request values are defined: +These request values are defined in the following objects: -RequestVals +akka.http.javadsl.server.values.FormFieldsRequestVals Contains request values for basic data like URI components, request method, peer address, or the entity data. -Cookies +akka.http.javadsl.server.values.FormFieldsCookies Contains request values representing cookies. -FormFields +akka.http.javadsl.server.values.FormFields Contains request values to access form fields unmarshalled to various primitive Java types. -Headers +:ref:`akka.http.javadsl.server.values.Headers ` Contains request values to access request headers or header values. -HttpBasicAuthenticator +akka.http.javadsl.server.values.FormFieldsHttpBasicAuthenticator An abstract class to implement to create a request value representing a HTTP basic authenticated principal. -Parameters +akka.http.javadsl.server.values.FormFieldsParameters Contains request values to access URI paramaters unmarshalled to various primitive Java types. -PathMatchers +akka.http.javadsl.server.values.FormFieldsPathMatchers Contains request values to match and access URI path segments. -CustomRequestVal +akka.http.javadsl.server.values.FormFieldsCustomRequestVal An abstract class to implement arbitrary custom request values. diff --git a/akka-http-core/src/main/java/akka/http/javadsl/model/headers/Host.java b/akka-http-core/src/main/java/akka/http/javadsl/model/headers/Host.java index fff8b2673d..1ce64adad5 100644 --- a/akka-http-core/src/main/java/akka/http/javadsl/model/headers/Host.java +++ b/akka-http-core/src/main/java/akka/http/javadsl/model/headers/Host.java @@ -7,19 +7,19 @@ package akka.http.javadsl.model.headers; import java.net.InetSocketAddress; public abstract class Host extends akka.http.scaladsl.model.HttpHeader { - + public static Host create(InetSocketAddress address) { return akka.http.scaladsl.model.headers.Host.apply(address); } - + public static Host create(String host) { return akka.http.scaladsl.model.headers.Host.apply(host); } - + public static Host create(String host, int port) { return akka.http.scaladsl.model.headers.Host.apply(host, port); } - + public abstract akka.http.javadsl.model.Host host(); public abstract int port(); } From a17604500f2183edd333060b0d44d59c203b992a Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Wed, 7 Oct 2015 15:55:04 +0200 Subject: [PATCH 2/3] =doc,htp #18657 document FormField vals --- .../FormFieldRequestValsExampleTest.java | 75 +++++++++++++++++++ .../server/HeaderRequestValsExampleTest.java | 7 +- .../request-vals/form-field-request-vals.rst | 33 ++++++++ .../http/routing-dsl/request-vals/index.rst | 2 +- .../javadsl/server/values/FormField.scala | 1 + 5 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java create mode 100644 akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java new file mode 100644 index 0000000000..8b44a5dc6d --- /dev/null +++ b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009-2015 Typesafe Inc. + */ + +package docs.http.javadsl.server; + +import akka.http.javadsl.model.ContentTypes; +import akka.http.javadsl.model.HttpRequest; +import akka.http.javadsl.model.headers.RawHeader; +import akka.http.javadsl.server.Marshallers; +import akka.http.javadsl.server.RequestVal; +import akka.http.javadsl.server.Route; +import akka.http.javadsl.server.values.FormField; +import akka.http.javadsl.server.values.FormFields; +import akka.http.javadsl.server.values.Headers; +import akka.http.javadsl.testkit.JUnitRouteTest; +import docs.http.scaladsl.server.directives.Person; +import org.junit.Test; + +public class FormFieldRequestValsExampleTest extends JUnitRouteTest { + + @Test + public void testFormFieldVals() { + //#simple + FormField name = FormFields.stringValue("name"); + FormField age = FormFields.intValue("age"); + + final Route route = + route( + handleWith2(name, age, (ctx, n, a) -> + ctx.complete(String.format("Name: %s, age: %d", n, a)) + ) + ); + + // tests: + final HttpRequest request = + HttpRequest + .POST("/"); + // .withFormData(); // FIXME awaits resolution of https://github.com/akka/akka/issues/18665 + testRoute(route).run(request).assertEntity("Name: ..., age: ..."); + + //#simple + } + + @Test + public void testFormFieldValsUnmarshaling() { + //#custom-unmarshal + FormField sampleId = FormFields.fromString("id", s -> new SampleId(Integer.valueOf(s)), SampleId.class); + + final Route route = + route( + handleWith1(sampleId, (ctx, id) -> + ctx.complete(String.format("SampleId: %s", id)) + ) + ); + + // tests: + final HttpRequest request = + HttpRequest + .POST("/"); + // .withFormData(); // FIXME awaits resolution of https://github.com/akka/akka/issues/18665 + testRoute(route).run(request).assertEntity("Name: ..., age: ..."); + + //#custom-unmarshal + } + + static class SampleId { + public final int id; + + SampleId(int id) { + this.id = id; + } + } + +} \ No newline at end of file diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java index 340819c7e6..c7872959d6 100644 --- a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java +++ b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java @@ -5,13 +5,10 @@ package docs.http.javadsl.server; import akka.http.javadsl.model.HttpRequest; -//#by-class import akka.http.javadsl.model.headers.Host; - -//#by-class import akka.http.javadsl.model.headers.RawHeader; -import akka.http.javadsl.server.*; -import akka.http.javadsl.server.values.Header; +import akka.http.javadsl.server.RequestVal; +import akka.http.javadsl.server.Route; import akka.http.javadsl.server.values.Headers; import akka.http.javadsl.testkit.JUnitRouteTest; import org.junit.Test; diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst new file mode 100644 index 0000000000..dfe95a1bfc --- /dev/null +++ b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst @@ -0,0 +1,33 @@ +.. _form-field-request-vals-java: + +Request Values: FormFields +========================== + +A collection of pre-defined :ref:`request-vals-java` that can be used to extract header values from incoming requests. + +Description +----------- +Header request values allow extracting ``HttpHeader`` values or concrete instances from HTTP requests. + +The ``RequestVal`` builder is made up of 2 steps, initially you need to pick which Header to extract (``byName`` or +``byClass``) and then you need to pick if the header is optionally available or required (i.e. the route should not +match if the header is not present in the request). This is done using one of the below depicted methods:: + + RequestVal instance() + RequestVal<> optionalInstance() + + RequestVal value() + RequestVal> optionalValue() + +Examples +-------- + +``Headers.byClass(Class[HttpHeader])`` + +.. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java + :include: by-class + +``Headers.byName(String)`` + +.. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java + :include: by-name diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst index ed8927b5d0..2a7fb32428 100644 --- a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst +++ b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/index.rst @@ -27,7 +27,7 @@ service. These request values are defined in the following objects: -akka.http.javadsl.server.values.FormFieldsRequestVals +:ref:`akka.http.javadsl.server.values.FormFields ` Contains request values for basic data like URI components, request method, peer address, or the entity data. akka.http.javadsl.server.values.FormFieldsCookies Contains request values representing cookies. diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala b/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala index ffdbda4a6e..c2318537d3 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala @@ -36,6 +36,7 @@ object FormFields { def hexIntValue(name: String): FormField[jl.Integer] = FormFieldImpl(name.as(Unmarshaller.HexInt)) def hexLongValue(name: String): FormField[jl.Long] = FormFieldImpl(name.as(Unmarshaller.HexLong)) + /** Unmarshals the `name` field using the provided `convert` function. */ def fromString[T](name: String, convert: Function[String, T], clazz: Class[T]): FormField[T] = { implicit val tTag: ClassTag[T] = ClassTag(clazz) FormFieldImpl(name.as(Util.fromStringUnmarshallerFromFunction(convert))) From 4e7999cf0a11d1b4a70238dffda4b3a8b03b91c4 Mon Sep 17 00:00:00 2001 From: Konrad Malawski Date: Thu, 8 Oct 2015 10:25:47 +0200 Subject: [PATCH 3/3] +htc,doc #18657,#18665 FormData javadsl and FormField docs --- .../FormFieldRequestValsExampleTest.java | 26 ++++++++----- .../request-vals/form-field-request-vals.rst | 18 +++------ .../request-vals/header-request-vals.rst | 4 +- .../akka/http/javadsl/model/FormData.java | 37 +++++++++++++++++++ .../akka/http/scaladsl/model/FormData.scala | 22 ++++++++++- .../javadsl/server/values/FormField.scala | 8 ++-- .../javadsl/server/values/Parameter.scala | 16 +++----- .../PredefinedToEntityMarshallers.scala | 7 +--- 8 files changed, 93 insertions(+), 45 deletions(-) create mode 100644 akka-http-core/src/main/java/akka/http/javadsl/model/FormData.java diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java index 8b44a5dc6d..d79636ba9a 100644 --- a/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java +++ b/akka-docs-dev/rst/java/code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java @@ -5,6 +5,7 @@ package docs.http.javadsl.server; import akka.http.javadsl.model.ContentTypes; +import akka.http.javadsl.model.FormData; import akka.http.javadsl.model.HttpRequest; import akka.http.javadsl.model.headers.RawHeader; import akka.http.javadsl.server.Marshallers; @@ -14,7 +15,9 @@ import akka.http.javadsl.server.values.FormField; import akka.http.javadsl.server.values.FormFields; import akka.http.javadsl.server.values.Headers; import akka.http.javadsl.testkit.JUnitRouteTest; +import akka.japi.Pair; import docs.http.scaladsl.server.directives.Person; +import org.junit.Ignore; import org.junit.Test; public class FormFieldRequestValsExampleTest extends JUnitRouteTest { @@ -33,11 +36,14 @@ public class FormFieldRequestValsExampleTest extends JUnitRouteTest { ); // tests: + final FormData formData = FormData.create( + Pair.create("name", "Blippy"), + Pair.create("age", "42")); final HttpRequest request = HttpRequest - .POST("/"); - // .withFormData(); // FIXME awaits resolution of https://github.com/akka/akka/issues/18665 - testRoute(route).run(request).assertEntity("Name: ..., age: ..."); + .POST("/") + .withEntity(formData.toEntity()); + testRoute(route).run(request).assertEntity("Name: Blippy, age: 42"); //#simple } @@ -45,21 +51,22 @@ public class FormFieldRequestValsExampleTest extends JUnitRouteTest { @Test public void testFormFieldValsUnmarshaling() { //#custom-unmarshal - FormField sampleId = FormFields.fromString("id", s -> new SampleId(Integer.valueOf(s)), SampleId.class); + FormField sampleId = FormFields.fromString("id", SampleId.class, s -> new SampleId(Integer.valueOf(s))); final Route route = route( - handleWith1(sampleId, (ctx, id) -> - ctx.complete(String.format("SampleId: %s", id)) + handleWith1(sampleId, (ctx, sid) -> + ctx.complete(String.format("SampleId: %s", sid.id)) ) ); // tests: + final FormData formData = FormData.create(Pair.create("id", "1337")); final HttpRequest request = HttpRequest - .POST("/"); - // .withFormData(); // FIXME awaits resolution of https://github.com/akka/akka/issues/18665 - testRoute(route).run(request).assertEntity("Name: ..., age: ..."); + .POST("/") + .withEntity(formData.toEntity()); + testRoute(route).run(request).assertEntity("SampleId: 1337"); //#custom-unmarshal } @@ -72,4 +79,5 @@ public class FormFieldRequestValsExampleTest extends JUnitRouteTest { } } + } \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst index dfe95a1bfc..c72031a706 100644 --- a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst +++ b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/form-field-request-vals.rst @@ -7,27 +7,19 @@ A collection of pre-defined :ref:`request-vals-java` that can be used to extract Description ----------- -Header request values allow extracting ``HttpHeader`` values or concrete instances from HTTP requests. +``FormField`` request values allow extracting fields submitted as ``application/x-www-form-urlencoded`` values or concrete instances from HTTP requests. The ``RequestVal`` builder is made up of 2 steps, initially you need to pick which Header to extract (``byName`` or ``byClass``) and then you need to pick if the header is optionally available or required (i.e. the route should not match if the header is not present in the request). This is done using one of the below depicted methods:: - RequestVal instance() - RequestVal<> optionalInstance() - - RequestVal value() - RequestVal> optionalValue() - Examples -------- -``Headers.byClass(Class[HttpHeader])`` +Extracting form fields of a certain primitive type from a request: -.. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java - :include: by-class +.. includecode:: ../../../code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java#simple -``Headers.byName(String)`` +Extracting values of custom type from a request by providing a conversion function: -.. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java - :include: by-name +.. includecode:: ../../../code/docs/http/javadsl/server/FormFieldRequestValsExampleTest.java#custom-unmarshal diff --git a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst index 3f363d82c4..f73bf5317e 100644 --- a/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst +++ b/akka-docs-dev/rst/java/http/routing-dsl/request-vals/header-request-vals.rst @@ -22,12 +22,12 @@ match if the header is not present in the request). This is done using one of th Examples -------- -``Headers.byClass(Class[HttpHeader])`` +Extracting a header by using a specific ``Header`` class (which are pre-defined in ``akka.http.javadsl.model.headers.*``): .. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java :include: by-class -``Headers.byName(String)`` +Extracting arbitrary headers by their name, for example custom headers (usually starting with ``X-...``): .. includecode:: ../../../code/docs/http/javadsl/server/HeaderRequestValsExampleTest.java :include: by-name diff --git a/akka-http-core/src/main/java/akka/http/javadsl/model/FormData.java b/akka-http-core/src/main/java/akka/http/javadsl/model/FormData.java new file mode 100644 index 0000000000..1936758d72 --- /dev/null +++ b/akka-http-core/src/main/java/akka/http/javadsl/model/FormData.java @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ + +package akka.http.javadsl.model; + +import akka.http.impl.model.parser.CharacterClasses; +import akka.http.impl.util.JavaMapping; +import akka.http.impl.util.StringRendering; +import akka.http.scaladsl.model.Uri.Query; +import akka.http.scaladsl.model.UriRendering; +import akka.japi.Pair; + +/** + * Simple model for `application/x-www-form-urlencoded` form data. + */ +public abstract class FormData { + + public abstract Query fields(); + + public RequestEntity toEntity() { + return toEntity(HttpCharsets.UTF_8); + } + + public RequestEntity toEntity(HttpCharset charset) { + // TODO this logic is duplicated in scaladsl.model.FormData, spent hours trying to DRY it but compiler freaked out in a number of ways... -- ktoso + final akka.http.scaladsl.model.HttpCharset c = (akka.http.scaladsl.model.HttpCharset) charset; + final StringRendering render = (StringRendering) UriRendering.renderQuery(new StringRendering(), this.fields(), c.nioCharset(), CharacterClasses.unreserved()); + return HttpEntities.create(ContentType.create(MediaTypes.APPLICATION_X_WWW_FORM_URLENCODED, charset), render.get()); + } + + @SafeVarargs + public static FormData create(Pair... fields) { + return akka.http.scaladsl.model.FormData.create(fields); + } + +} diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/FormData.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/FormData.scala index 5f208471b3..6ad16b3d9c 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/FormData.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/FormData.scala @@ -4,10 +4,25 @@ package akka.http.scaladsl.model +import akka.http.impl.model.parser.CharacterClasses +import akka.http.impl.util.StringRendering +import akka.http.javadsl.{ model ⇒ jm } +import akka.http.scaladsl.model.HttpCharsets._ +import akka.http.scaladsl.model.MediaTypes._ + /** * Simple model for `application/x-www-form-urlencoded` form data. */ -final case class FormData(fields: Uri.Query) +final case class FormData(fields: Uri.Query) extends jm.FormData { + override def toEntity: akka.http.scaladsl.model.RequestEntity = + toEntity(HttpCharsets.`UTF-8`) + + def toEntity(charset: HttpCharset): akka.http.scaladsl.model.RequestEntity = { + // TODO this logic is duplicated in javadsl.model.FormData, spent hours trying to DRY it but compiler freaked out in a number of ways... -- ktoso + val render: StringRendering = UriRendering.renderQuery(new StringRendering, this.fields, charset.nioCharset, CharacterClasses.unreserved) + HttpEntity(ContentType(`application/x-www-form-urlencoded`, `UTF-8`), render.get) + } +} object FormData { val Empty = FormData(Uri.Query.Empty) @@ -17,4 +32,7 @@ object FormData { def apply(fields: (String, String)*): FormData = if (fields.isEmpty) Empty else FormData(Uri.Query(fields: _*)) -} \ No newline at end of file + + def create(fields: Array[akka.japi.Pair[String, String]]): FormData = + if (fields.isEmpty) Empty else FormData(Uri.Query(fields.map(_.toScala): _*)) +} diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala b/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala index c2318537d3..beb9448dda 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/values/FormField.scala @@ -6,12 +6,12 @@ package akka.http.javadsl.server package values import java.{ lang ⇒ jl } + +import akka.http.impl.server.{ FormFieldImpl, Util } +import akka.http.scaladsl.unmarshalling._ import akka.japi.function.Function import akka.japi.{ Option ⇒ JOption } -import akka.http.impl.server.{ Util, FormFieldImpl } -import akka.http.scaladsl.unmarshalling._ - import scala.reflect.ClassTag trait FormField[T] extends RequestVal[T] { @@ -37,7 +37,7 @@ object FormFields { def hexLongValue(name: String): FormField[jl.Long] = FormFieldImpl(name.as(Unmarshaller.HexLong)) /** Unmarshals the `name` field using the provided `convert` function. */ - def fromString[T](name: String, convert: Function[String, T], clazz: Class[T]): FormField[T] = { + def fromString[T](name: String, clazz: Class[T], convert: Function[String, T]): FormField[T] = { implicit val tTag: ClassTag[T] = ClassTag(clazz) FormFieldImpl(name.as(Util.fromStringUnmarshallerFromFunction(convert))) } diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/values/Parameter.scala b/akka-http/src/main/scala/akka/http/javadsl/server/values/Parameter.scala index b1c4865517..093d6e8967 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/values/Parameter.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/values/Parameter.scala @@ -5,22 +5,17 @@ package akka.http.javadsl.server.values import java.util.AbstractMap.SimpleEntry +import java.util.{ Collection ⇒ JCollection, Map ⇒ JMap } import java.{ lang ⇒ jl } -import java.util.{ Map ⇒ JMap, Collection ⇒ JCollection } - +import akka.http.impl.server.{ ParameterImpl, StandaloneExtractionImpl, Util } +import akka.http.javadsl.server.RequestVal import akka.http.scaladsl.server.directives.ParameterDirectives import akka.http.scaladsl.unmarshalling.Unmarshaller import akka.japi.function.Function - -import scala.reflect.ClassTag - import akka.japi.{ Option ⇒ JOption } -import akka.http.impl.server.{ Util, StandaloneExtractionImpl, ParameterImpl } -import akka.http.javadsl.server.RequestVal -import akka.http.scaladsl.server.Directive1 -import akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet +import scala.reflect.ClassTag /** * A RequestVal representing a query parameter of type T. @@ -65,7 +60,8 @@ object Parameters { def asCollection: RequestVal[JCollection[JMap.Entry[String, String]]] = StandaloneExtractionImpl(ParameterDirectives.parameterSeq.map(_.map(e ⇒ new SimpleEntry(e._1, e._2): JMap.Entry[String, String]).asJavaCollection)) - def fromString[T](name: String, convert: Function[String, T], clazz: Class[T]): Parameter[T] = { + /** Unmarshals the `name` field using the provided `convert` function. */ + def fromString[T](name: String, clazz: Class[T], convert: Function[String, T]): Parameter[T] = { implicit val tTag: ClassTag[T] = ClassTag(clazz) ParameterImpl(name.as(Util.fromStringUnmarshallerFromFunction(convert))) } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/marshalling/PredefinedToEntityMarshallers.scala b/akka-http/src/main/scala/akka/http/scaladsl/marshalling/PredefinedToEntityMarshallers.scala index 42ca0cf716..04e1f7aafe 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/marshalling/PredefinedToEntityMarshallers.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/marshalling/PredefinedToEntityMarshallers.scala @@ -5,10 +5,9 @@ package akka.http.scaladsl.marshalling import java.nio.CharBuffer -import akka.http.impl.model.parser.CharacterClasses + import akka.http.scaladsl.model.MediaTypes._ import akka.http.scaladsl.model._ -import akka.http.impl.util.StringRendering import akka.util.ByteString trait PredefinedToEntityMarshallers extends MultipartMarshallers { @@ -53,9 +52,7 @@ trait PredefinedToEntityMarshallers extends MultipartMarshallers { implicit val FormDataMarshaller: ToEntityMarshaller[FormData] = Marshaller.withOpenCharset(`application/x-www-form-urlencoded`) { (formData, charset) ⇒ - val query = Uri.Query(formData.fields: _*) - val string = UriRendering.renderQuery(new StringRendering, query, charset.nioCharset, CharacterClasses.unreserved).get - HttpEntity(ContentType(`application/x-www-form-urlencoded`, charset), string) + formData.toEntity(charset) } implicit val MessageEntityMarshaller: ToEntityMarshaller[MessageEntity] = Marshaller strict { value ⇒