=doc #18657 Doc host and path directives

* also including docs of RequestVals.matchAndExtractHost
  and RequestVals.matchAndExtractHost
* and add Host.create factory methods
* add missing HttpRequest PATCH and OPTIONS
* change to val in matchAndExtractHost for
  fail fast exception
This commit is contained in:
Patrik Nordwall 2015-10-07 12:07:26 +02:00
parent 5753cd6074
commit 3081893bfd
20 changed files with 519 additions and 2 deletions

View file

@ -0,0 +1,102 @@
/*
* Copyright (C) 2015 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.http.javadsl.server.directives;
import java.util.Arrays;
import java.util.regex.Pattern;
import akka.http.javadsl.model.HttpMethod;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.server.*;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
public class HostDirectivesExamplesTest extends JUnitRouteTest {
//FIXME The GET requests should work with HttpRequest.GET("/").addHeader(Host.create
// instead of absolute paths. That is tracked by issue: https://github.com/akka/akka/issues/18661
@Test
public void testListOfHost() {
//#host1
final Route matchListOfHosts = host(
Arrays.asList("api.company.com", "rest.company.com"),
completeWithStatus(StatusCodes.OK));
testRoute(matchListOfHosts).run(HttpRequest.GET("http://api.company.com/"))
.assertStatusCode(StatusCodes.OK);
//#host1
}
@Test
public void testHostPredicate() {
//#host2
final Route shortOnly = host(hostname -> hostname.length() < 10,
completeWithStatus(StatusCodes.OK));
testRoute(shortOnly).run(HttpRequest.GET("http://short.com/"))
.assertStatusCode(StatusCodes.OK);
testRoute(shortOnly).run(HttpRequest.GET("http://verylonghostname.com/"))
.assertStatusCode(StatusCodes.NOT_FOUND);
//#host2
}
@Test
public void testExtractHost() {
//#extractHostname
final RequestVal<String> host = RequestVals.host();
final Route route = handleWith1(host,
(ctx, hn) -> ctx.complete("Hostname: " + hn));
testRoute(route).run(HttpRequest.GET("http://company.com:9090/"))
.assertEntity("Hostname: company.com");
//#extractHostname
}
@Test
public void testMatchAndExtractHost() {
//#matchAndExtractHost
final RequestVal<String> hostPrefix = RequestVals
.matchAndExtractHost(Pattern.compile("api|rest"));
final Route hostPrefixRoute = handleWith1(hostPrefix,
(ctx, prefix) -> ctx.complete("Extracted prefix: " + prefix));
final RequestVal<String> hostPart = RequestVals.matchAndExtractHost(Pattern
.compile("public.(my|your)company.com"));
final Route hostPartRoute = handleWith1(
hostPart,
(ctx, captured) -> ctx.complete("You came through " + captured
+ " company"));
final Route route = route(hostPrefixRoute, hostPartRoute);
testRoute(route).run(HttpRequest.GET("http://api.company.com/"))
.assertStatusCode(StatusCodes.OK).assertEntity("Extracted prefix: api");
testRoute(route).run(HttpRequest.GET("http://public.mycompany.com/"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("You came through my company");
//#matchAndExtractHost
}
@SuppressWarnings("unused")
@Test(expected = IllegalArgumentException.class)
public void testFailingMatchAndExtractHost() {
//#failing-matchAndExtractHost
// this will throw IllegalArgumentException
final RequestVal<String> hostRegex = RequestVals
.matchAndExtractHost(Pattern
.compile("server-([0-9]).company.(com|net|org)"));
//#failing-matchAndExtractHost
}
}

View file

@ -0,0 +1,124 @@
/*
* Copyright (C) 2015 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpMethod;
import akka.http.javadsl.model.HttpMethods;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.*;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
public class MethodDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testDelete() {
//#delete
final Route route = delete(complete("This is a DELETE request."));
testRoute(route).run(HttpRequest.DELETE("/")).assertEntity(
"This is a DELETE request.");
//#delete
}
@Test
public void testGet() {
//#get
final Route route = get(complete("This is a GET request."));
testRoute(route).run(HttpRequest.GET("/")).assertEntity(
"This is a GET request.");
//#get
}
@Test
public void testHead() {
//#head
final Route route = head(complete("This is a HEAD request."));
testRoute(route).run(HttpRequest.HEAD("/")).assertEntity(
"This is a HEAD request.");
//#head
}
@Test
public void testOptions() {
//#options
final Route route = options(complete("This is a OPTIONS request."));
testRoute(route).run(HttpRequest.OPTIONS("/")).assertEntity(
"This is a OPTIONS request.");
//#options
}
@Test
public void testPatch() {
//#patch
final Route route = patch(complete("This is a PATCH request."));
testRoute(route).run(HttpRequest.PATCH("/").withEntity("patch content"))
.assertEntity("This is a PATCH request.");
//#patch
}
@Test
public void testPost() {
//#post
final Route route = post(complete("This is a POST request."));
testRoute(route).run(HttpRequest.POST("/").withEntity("post content"))
.assertEntity("This is a POST request.");
//#post
}
@Test
public void testPut() {
//#put
final Route route = put(complete("This is a PUT request."));
testRoute(route).run(HttpRequest.PUT("/").withEntity("put content"))
.assertEntity("This is a PUT request.");
//#put
}
@Test
public void testMethodExample() {
//#method-example
final Route route = method(HttpMethods.PUT,
complete("This is a PUT request."));
testRoute(route).run(HttpRequest.PUT("/").withEntity("put content"))
.assertEntity("This is a PUT request.");
testRoute(route).run(HttpRequest.GET("/")).assertStatusCode(
StatusCodes.METHOD_NOT_ALLOWED);
//#method-example
}
@Test
public void testExtractMethodExample() {
//#extractMethod
final RequestVal<HttpMethod> requestMethod = RequestVals.requestMethod();
final Route otherMethod = handleWith1(
requestMethod,
(ctx, method) -> ctx.complete("This " + method.value()
+ " request, clearly is not a GET!"));
final Route route = route(get(complete("This is a GET request.")),
otherMethod);
testRoute(route).run(HttpRequest.GET("/")).assertEntity(
"This is a GET request.");
testRoute(route).run(HttpRequest.PUT("/").withEntity("put content"))
.assertEntity("This PUT request, clearly is not a GET!");
testRoute(route).run(HttpRequest.HEAD("/")).assertEntity(
"This HEAD request, clearly is not a GET!");
//#extractMethod
}
}

View file

@ -0,0 +1,13 @@
.. _-extractHost-java-:
RequestVals.host
================
Extract the hostname part of the ``Host`` request header and expose it as a ``String`` extraction
to its inner route.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java#extractHostname

View file

@ -0,0 +1,44 @@
.. _-host-java-:
host
====
Filter requests matching conditions against the hostname part of the Host header value
in the request.
There are a few variants:
* reject all requests with a hostname different from the given ones
* reject all requests for which the hostname does not satisfy the given predicate
* reject all requests for which the hostname does not satisfy the given regular expression
The regular expression matching works a little bit different: it rejects all requests with a hostname
that doesn't have a prefix matching the given regular expression and also extracts a ``String`` to its
inner route following this rules:
* For all matching requests the prefix string matching the regex is extracted and passed to the inner route.
* If the regex contains a capturing group only the string matched by this group is extracted.
* If the regex contains more than one capturing group an ``IllegalArgumentException`` is thrown.
Example
-------
Matching a list of hosts:
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java#host1
Making sure the host satisfies the given predicate
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java#host2
Using a regular expressions:
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java#matchAndExtractHost
Beware that in the case of introducing multiple capturing groups in the regex such as in the case bellow, the
directive will fail at runtime, at the moment the route tree is evaluated for the first time. This might cause
your http handler actor to enter in a fail/restart loop depending on your supervision strategy.
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/HostDirectivesExamplesTest.java#failing-matchAndExtractHost

View file

@ -0,0 +1,15 @@
.. _HostDirectives-java:
HostDirectives
==============
HostDirectives allow you to filter requests based on the hostname part of the ``Host`` header
contained in incoming requests as well as extracting its value for usage in inner routes.
.. toctree::
:maxdepth: 1
host
extractHost

View file

@ -58,9 +58,13 @@ SchemeDirectives
WebsocketDirectives
Contains directives to support answering Websocket requests.
TODO this page should be rewritten as the corresponding Scala page
.. toctree::
:maxdepth: 1
path-directives
method-directives/index
host-directives/index
.. _`RFC 7234`: http://tools.ietf.org/html/rfc7234

View file

@ -0,0 +1,17 @@
.. _-delete-java-:
delete
======
Matches requests with HTTP method ``DELETE``.
This directive filters an incoming request by its HTTP method. Only requests with
method ``DELETE`` are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#delete

View file

@ -0,0 +1,16 @@
.. _-extractMethod-java-:
extractMethod
=============
Extracts the :class:`HttpMethod` from the request context and provides it for use for other directives explicitly.
Example
-------
In the below example our route first matches all ``GET`` requests, and if an incoming request wasn't a ``GET``,
the matching continues and the extractMethod route will be applied which we can use to programatically
print what type of request it was - independent of what actual HttpMethod it was:
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#extractMethod

View file

@ -0,0 +1,17 @@
.. _-get-java-:
get
===
Matches requests with HTTP method ``GET``.
This directive filters the incoming request by its HTTP method. Only requests with
method ``GET`` are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#get

View file

@ -0,0 +1,20 @@
.. _-head-java-:
head
====
Matches requests with HTTP method ``HEAD``.
This directive filters the incoming request by its HTTP method. Only requests with
method ``HEAD`` are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
.. note:: By default, akka-http handles HEAD-requests transparently by dispatching a GET-request to the handler and
stripping of the result body. See the ``akka.http.server.transparent-head-requests`` setting for how to disable
this behavior.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#head

View file

@ -0,0 +1,18 @@
.. _MethodDirectives:
MethodDirectives
================
.. toctree::
:maxdepth: 1
delete
extractMethod
get
head
method
options
overrideMethodWithParameter
patch
post
put

View file

@ -0,0 +1,19 @@
.. _-method-java-:
method
======
Matches HTTP requests based on their method.
Description
-----------
This directive filters the incoming request by its HTTP method. Only requests with
the specified method are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#method-example

View file

@ -0,0 +1,16 @@
.. _-options-java-:
options
=======
Matches requests with HTTP method ``OPTIONS``.
This directive filters the incoming request by its HTTP method. Only requests with
method ``OPTIONS`` are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#options

View file

@ -0,0 +1,11 @@
.. _-overrideMethodWithParameter-java-:
overrideMethodWithParameter
===========================
TODO ...
Example
-------
TODO sample is missing, also in Scala documentation

View file

@ -0,0 +1,17 @@
.. _-patch-java-:
patch
=====
Matches requests with HTTP method ``PATCH``.
This directive filters the incoming request by its HTTP method. Only requests with
method ``PATCH`` are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#patch

View file

@ -0,0 +1,17 @@
.. _-post-java-:
post
====
Matches requests with HTTP method ``POST``.
This directive filters the incoming request by its HTTP method. Only requests with
method ``POST`` are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#post

View file

@ -0,0 +1,16 @@
.. _-put-java-:
put
===
Matches requests with HTTP method ``PUT``.
This directive filters the incoming request by its HTTP method. Only requests with
method ``PUT`` are passed on to the inner route. All others are rejected with a
``MethodRejection``, which is translated into a ``405 Method Not Allowed`` response
by the default ``RejectionHandler``.
Example
-------
.. includecode:: ../../../../code/docs/http/javadsl/server/directives/MethodDirectivesExamplesTest.java#put