Remove Akka-HTTP sources from akka/akka, moving to akka/akka-http! (#21690)

This commit is contained in:
Konrad Malawski 2016-10-18 15:17:17 +02:00 committed by GitHub
parent 09a6d2ede1
commit a6a5556a8f
1155 changed files with 20 additions and 96517 deletions

View file

@ -1,209 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl;
import akka.Done;
import akka.actor.AbstractActor;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.HostConnectionPool;
import akka.japi.Pair;
import akka.japi.pf.ReceiveBuilder;
import akka.stream.Materializer;
import akka.util.ByteString;
import scala.compat.java8.FutureConverters;
import scala.concurrent.ExecutionContextExecutor;
import scala.concurrent.Future;
import akka.stream.javadsl.*;
import akka.http.javadsl.OutgoingConnection;
import akka.http.javadsl.Http;
import static akka.http.javadsl.ConnectHttp.toHost;
import static akka.pattern.PatternsCS.*;
import java.util.concurrent.CompletionStage;
//#manual-entity-consume-example-1
import java.io.File;
import akka.actor.ActorSystem;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Framing;
import akka.http.javadsl.model.*;
import scala.concurrent.duration.FiniteDuration;
import scala.util.Try;
//#manual-entity-consume-example-1
@SuppressWarnings("unused")
public class HttpClientExampleDocTest {
HttpResponse responseFromSomewhere() {
return null;
}
void manualEntityComsumeExample() {
//#manual-entity-consume-example-1
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final HttpResponse response = responseFromSomewhere();
final Function<ByteString, ByteString> transformEachLine = line -> line /* some transformation here */;
final int maximumFrameLength = 256;
response.entity().getDataBytes()
.via(Framing.delimiter(ByteString.fromString("\n"), maximumFrameLength, FramingTruncation.ALLOW))
.map(transformEachLine::apply)
.runWith(FileIO.toPath(new File("/tmp/example.out").toPath()), materializer);
//#manual-entity-consume-example-1
}
private
//#manual-entity-consume-example-2
final class ExamplePerson {
final String name;
public ExamplePerson(String name) { this.name = name; }
}
public ExamplePerson parse(ByteString line) {
return new ExamplePerson(line.utf8String());
}
//#manual-entity-consume-example-2
void manualEntityConsumeExample2() {
//#manual-entity-consume-example-2
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final HttpResponse response = responseFromSomewhere();
// toStrict to enforce all data be loaded into memory from the connection
final CompletionStage<HttpEntity.Strict> strictEntity = response.entity()
.toStrict(FiniteDuration.create(3, TimeUnit.SECONDS).toMillis(), materializer);
// while API remains the same to consume dataBytes, now they're in memory already:
final CompletionStage<ExamplePerson> person =
strictEntity
.thenCompose(strict ->
strict.getDataBytes()
.runFold(ByteString.empty(), (acc, b) -> acc.concat(b), materializer)
.thenApply(this::parse)
);
//#manual-entity-consume-example-2
}
void manualEntityDiscardExample1() {
//#manual-entity-discard-example-1
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final HttpResponse response = responseFromSomewhere();
final HttpMessage.DiscardedEntity discarded = response.discardEntityBytes(materializer);
discarded.completionStage().whenComplete((done, ex) -> {
System.out.println("Entity discarded completely!");
});
//#manual-entity-discard-example-1
}
void manualEntityDiscardExample2() {
//#manual-entity-discard-example-2
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final HttpResponse response = responseFromSomewhere();
final CompletionStage<Done> discardingComplete = response.entity().getDataBytes().runWith(Sink.ignore(), materializer);
discardingComplete.whenComplete((done, ex) -> {
System.out.println("Entity discarded completely!");
});
//#manual-entity-discard-example-2
}
// compile only test
public void testConstructRequest() {
//#outgoing-connection-example
final ActorSystem system = ActorSystem.create();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Flow<HttpRequest, HttpResponse, CompletionStage<OutgoingConnection>> connectionFlow =
Http.get(system).outgoingConnection(toHost("akka.io", 80));
final CompletionStage<HttpResponse> responseFuture =
Source.single(HttpRequest.create("/"))
.via(connectionFlow)
.runWith(Sink.<HttpResponse>head(), materializer);
//#outgoing-connection-example
}
// compile only test
public void testHostLevelExample() {
//#host-level-example
final ActorSystem system = ActorSystem.create();
final ActorMaterializer materializer = ActorMaterializer.create(system);
// construct a pool client flow with context type `Integer`
final Flow<
Pair<HttpRequest, Integer>,
Pair<Try<HttpResponse>, Integer>,
HostConnectionPool> poolClientFlow =
Http.get(system).<Integer>cachedHostConnectionPool(toHost("akka.io", 80), materializer);
// construct a pool client flow with context type `Integer`
final CompletionStage<Pair<Try<HttpResponse>, Integer>> responseFuture =
Source
.single(Pair.create(HttpRequest.create("/"), 42))
.via(poolClientFlow)
.runWith(Sink.<Pair<Try<HttpResponse>, Integer>>head(), materializer);
//#host-level-example
}
// compile only test
public void testSingleRequestExample() {
//#single-request-example
final ActorSystem system = ActorSystem.create();
final Materializer materializer = ActorMaterializer.create(system);
final CompletionStage<HttpResponse> responseFuture =
Http.get(system)
.singleRequest(HttpRequest.create("http://akka.io"), materializer);
//#single-request-example
}
static
//#single-request-in-actor-example
class Myself extends AbstractActor {
final Http http = Http.get(context().system());
final ExecutionContextExecutor dispatcher = context().dispatcher();
final Materializer materializer = ActorMaterializer.create(context());
public Myself() {
receive(ReceiveBuilder
.match(String.class, url -> {
pipe(fetch (url), dispatcher).to(self());
}).build());
}
CompletionStage<HttpResponse> fetch(String url) {
return http.singleRequest(HttpRequest.create(url), materializer);
}
}
//#single-request-in-actor-example
}

View file

@ -1,49 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl;
import akka.actor.AbstractActor;
import akka.actor.ActorSystem;
import akka.http.javadsl.*;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.japi.Pair;
import akka.japi.pf.ReceiveBuilder;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import com.typesafe.sslconfig.akka.AkkaSSLConfig;
import scala.concurrent.ExecutionContextExecutor;
import scala.util.Try;
import java.util.concurrent.CompletionStage;
import static akka.http.javadsl.ConnectHttp.toHost;
import static akka.pattern.PatternsCS.pipe;
@SuppressWarnings("unused")
public class HttpsExamplesDocTest {
// compile only test
public void testConstructRequest() {
String unsafeHost = "example.com";
//#disable-sni-connection
final ActorSystem system = ActorSystem.create();
final ActorMaterializer mat = ActorMaterializer.create(system);
final Http http = Http.get(system);
// WARNING: disabling SNI is a very bad idea, please don't unless you have a very good reason to.
final AkkaSSLConfig defaultSSLConfig = AkkaSSLConfig.get(system);
final AkkaSSLConfig badSslConfig = defaultSSLConfig
.convertSettings(s -> s.withLoose(s.loose().withDisableSNI(true)));
final HttpsConnectionContext badCtx = http.createClientHttpsContext(badSslConfig);
http.outgoingConnection(ConnectHttp.toHostHttps(unsafeHost).withCustomHttpsContext(badCtx));
//#disable-sni-connection
}
}

View file

@ -1,91 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl;
import akka.util.ByteString;
import org.junit.Test;
//#import-model
import akka.http.javadsl.model.*;
import akka.http.javadsl.model.headers.*;
import java.util.Optional;
//#import-model
@SuppressWarnings("unused")
public class ModelDocTest {
@Test
public void testConstructRequest() {
//#construct-request
// construct a simple GET request to `homeUri`
Uri homeUri = Uri.create("/home");
HttpRequest request1 = HttpRequest.create().withUri(homeUri);
// construct simple GET request to "/index" using helper methods
HttpRequest request2 = HttpRequest.GET("/index");
// construct simple POST request containing entity
ByteString data = ByteString.fromString("abc");
HttpRequest postRequest1 = HttpRequest.POST("/receive").withEntity(data);
// customize every detail of HTTP request
//import HttpProtocols._
//import MediaTypes._
Authorization authorization = Authorization.basic("user", "pass");
HttpRequest complexRequest =
HttpRequest.PUT("/user")
.withEntity(HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, "abc"))
.addHeader(authorization)
.withProtocol(HttpProtocols.HTTP_1_0);
//#construct-request
}
@Test
public void testConstructResponse() {
//#construct-response
// simple OK response without data created using the integer status code
HttpResponse ok = HttpResponse.create().withStatus(200);
// 404 response created using the named StatusCode constant
HttpResponse notFound = HttpResponse.create().withStatus(StatusCodes.NOT_FOUND);
// 404 response with a body explaining the error
HttpResponse notFoundCustom =
HttpResponse.create()
.withStatus(404)
.withEntity("Unfortunately, the resource couldn't be found.");
// A redirecting response containing an extra header
Location locationHeader = Location.create("http://example.com/other");
HttpResponse redirectResponse =
HttpResponse.create()
.withStatus(StatusCodes.FOUND)
.addHeader(locationHeader);
//#construct-response
}
@Test
public void testDealWithHeaders() {
//#headers
// create a ``Location`` header
Location locationHeader = Location.create("http://example.com/other");
// create an ``Authorization`` header with HTTP Basic authentication data
Authorization authorization = Authorization.basic("user", "pass");
//#headers
}
//#headers
// a method that extracts basic HTTP credentials from a request
private Optional<BasicHttpCredentials> getCredentialsOfRequest(HttpRequest request) {
Optional<Authorization> auth = request.getHeader(Authorization.class);
if (auth.isPresent() && auth.get().credentials() instanceof BasicHttpCredentials)
return Optional.of((BasicHttpCredentials) auth.get().credentials());
else
return Optional.empty();
}
//#headers
}

View file

@ -1,241 +0,0 @@
/*
* Copyright (C) 2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl;
import akka.Done;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.Http;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.Authorization;
import akka.http.javadsl.model.ws.Message;
import akka.http.javadsl.model.ws.TextMessage;
import akka.http.javadsl.model.ws.WebSocketRequest;
import akka.http.javadsl.model.ws.WebSocketUpgradeResponse;
import akka.japi.Pair;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Keep;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
@SuppressWarnings("unused")
public class WebSocketClientExampleTest {
// compile only test
public void testSingleWebSocketRequest() {
//#single-WebSocket-request
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Http http = Http.get(system);
// print each incoming text message
// would throw exception on non strict or binary message
final Sink<Message, CompletionStage<Done>> printSink =
Sink.foreach((message) ->
System.out.println("Got message: " + message.asTextMessage().getStrictText())
);
// send this as a message over the WebSocket
final Source<Message, NotUsed> helloSource =
Source.single(TextMessage.create("hello world"));
// the CompletionStage<Done> is the materialized value of Sink.foreach
// and it is completed when the stream completes
final Flow<Message, Message, CompletionStage<Done>> flow =
Flow.fromSinkAndSourceMat(printSink, helloSource, Keep.left());
final Pair<CompletionStage<WebSocketUpgradeResponse>, CompletionStage<Done>> pair =
http.singleWebSocketRequest(
WebSocketRequest.create("ws://echo.websocket.org"),
flow,
materializer
);
// The first value in the pair is a CompletionStage<WebSocketUpgradeResponse> that
// completes when the WebSocket request has connected successfully (or failed)
final CompletionStage<Done> connected = pair.first().thenApply(upgrade -> {
// just like a regular http request we can access response status which is available via upgrade.response.status
// status code 101 (Switching Protocols) indicates that server support WebSockets
if (upgrade.response().status().equals(StatusCodes.SWITCHING_PROTOCOLS)) {
return Done.getInstance();
} else {
throw new RuntimeException("Connection failed: " + upgrade.response().status());
}
});
// the second value is the completion of the sink from above
// in other words, it completes when the WebSocket disconnects
final CompletionStage<Done> closed = pair.second();
// in a real application you would not side effect here
// and handle errors more carefully
connected.thenAccept(done -> System.out.println("Connected"));
closed.thenAccept(done -> System.out.println("Connection closed"));
//#single-WebSocket-request
}
// compile only test
public void halfClosedWebSocketClosingExample() {
final ActorSystem system = ActorSystem.create();
final Materializer materializer = ActorMaterializer.create(system);
final Http http = Http.get(system);
//#half-closed-WebSocket-closing
// we may expect to be able to to just tail
// the server websocket output like this
final Flow<Message, Message, NotUsed> flow =
Flow.fromSinkAndSource(
Sink.foreach(System.out::println),
Source.empty());
http.singleWebSocketRequest(
WebSocketRequest.create("ws://example.com:8080/some/path"),
flow,
materializer);
//#half-closed-WebSocket-closing
}
public void halfClosedWebSocketWorkingExample() {
final ActorSystem system = ActorSystem.create();
final Materializer materializer = ActorMaterializer.create(system);
final Http http = Http.get(system);
//#half-closed-WebSocket-working
// using Source.maybe materializes into a completable future
// which will allow us to complete the source later
final Flow<Message, Message, CompletableFuture<Optional<Message>>> flow =
Flow.fromSinkAndSourceMat(
Sink.foreach(System.out::println),
Source.maybe(),
Keep.right());
final Pair<CompletionStage<WebSocketUpgradeResponse>, CompletableFuture<Optional<Message>>> pair =
http.singleWebSocketRequest(
WebSocketRequest.create("ws://example.com:8080/some/path"),
flow,
materializer);
// at some later time we want to disconnect
pair.second().complete(Optional.empty());
//#half-closed-WebSocket-working
}
public void halfClosedWebSocketFiniteWorkingExample() {
final ActorSystem system = ActorSystem.create();
final Materializer materializer = ActorMaterializer.create(system);
final Http http = Http.get(system);
//#half-closed-WebSocket-finite
// emit "one" and then "two" and then keep the source from completing
final Source<Message, CompletableFuture<Optional<Message>>> source =
Source.from(Arrays.<Message>asList(TextMessage.create("one"), TextMessage.create("two")))
.concatMat(Source.maybe(), Keep.right());
final Flow<Message, Message, CompletableFuture<Optional<Message>>> flow =
Flow.fromSinkAndSourceMat(
Sink.foreach(System.out::println),
source,
Keep.right());
final Pair<CompletionStage<WebSocketUpgradeResponse>, CompletableFuture<Optional<Message>>> pair =
http.singleWebSocketRequest(
WebSocketRequest.create("ws://example.com:8080/some/path"),
flow,
materializer);
// at some later time we want to disconnect
pair.second().complete(Optional.empty());
//#half-closed-WebSocket-finite
}
// compile time only test
public void testAuthorizedSingleWebSocketRequest() {
Materializer materializer = null;
Http http = null;
Flow<Message, Message, NotUsed> flow = null;
//#authorized-single-WebSocket-request
http.singleWebSocketRequest(
WebSocketRequest.create("ws://example.com:8080/some/path")
.addHeader(Authorization.basic("johan", "correcthorsebatterystaple")),
flow,
materializer);
//#authorized-single-WebSocket-request
}
// compile time only test
public void testWebSocketClientFlow() {
//#WebSocket-client-flow
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Http http = Http.get(system);
// print each incoming text message
// would throw exception on non strict or binary message
Sink<Message, CompletionStage<Done>> printSink =
Sink.foreach((message) ->
System.out.println("Got message: " + message.asTextMessage().getStrictText())
);
// send this as a message over the WebSocket
Source<Message, NotUsed> helloSource =
Source.single(TextMessage.create("hello world"));
Flow<Message, Message, CompletionStage<WebSocketUpgradeResponse>> webSocketFlow =
http.webSocketClientFlow(WebSocketRequest.create("ws://echo.websocket.org"));
Pair<CompletionStage<WebSocketUpgradeResponse>, CompletionStage<Done>> pair =
helloSource.viaMat(webSocketFlow, Keep.right())
.toMat(printSink, Keep.both())
.run(materializer);
// The first value in the pair is a CompletionStage<WebSocketUpgradeResponse> that
// completes when the WebSocket request has connected successfully (or failed)
CompletionStage<WebSocketUpgradeResponse> upgradeCompletion = pair.first();
// the second value is the completion of the sink from above
// in other words, it completes when the WebSocket disconnects
CompletionStage<Done> closed = pair.second();
CompletionStage<Done> connected = upgradeCompletion.thenApply(upgrade->
{
// just like a regular http request we can access response status which is available via upgrade.response.status
// status code 101 (Switching Protocols) indicates that server support WebSockets
if (upgrade.response().status().equals(StatusCodes.SWITCHING_PROTOCOLS)) {
return Done.getInstance();
} else {
throw new RuntimeException(("Connection failed: " + upgrade.response().status()));
}
});
// in a real application you would not side effect here
// and handle errors more carefully
connected.thenAccept(done -> System.out.println("Connected"));
closed.thenAccept(done -> System.out.println("Connection closed"));
//#WebSocket-client-flow
}
}

View file

@ -1,75 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import org.junit.Test;
import akka.http.javadsl.model.FormData;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.unmarshalling.StringUnmarshallers;
import akka.http.javadsl.unmarshalling.StringUnmarshaller;
import akka.http.javadsl.unmarshalling.Unmarshaller;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.japi.Pair;
public class FormFieldRequestValsExampleTest extends JUnitRouteTest {
@Test
public void testFormFieldVals() {
//#simple
final Route route =
formField("name", n ->
formField(StringUnmarshallers.INTEGER, "age", a ->
complete(String.format("Name: %s, age: %d", n, a))
)
);
// tests:
final FormData formData = FormData.create(
Pair.create("name", "Blippy"),
Pair.create("age", "42"));
final HttpRequest request =
HttpRequest
.POST("/")
.withEntity(formData.toEntity());
testRoute(route).run(request).assertEntity("Name: Blippy, age: 42");
//#simple
}
@Test
public void testFormFieldValsUnmarshaling() {
//#custom-unmarshal
Unmarshaller<String, SampleId> SAMPLE_ID = StringUnmarshaller.sync(s -> new SampleId(Integer.valueOf(s)));
final Route route =
formField(SAMPLE_ID, "id", sid ->
complete(String.format("SampleId: %s", sid.id))
);
// tests:
final FormData formData = FormData.create(Pair.create("id", "1337"));
final HttpRequest request =
HttpRequest
.POST("/")
.withEntity(formData.toEntity());
testRoute(route).run(request).assertEntity("SampleId: 1337");
//#custom-unmarshal
}
static class SampleId {
public final int id;
SampleId(int id) {
this.id = id;
}
}
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import org.junit.Test;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.model.headers.RawHeader;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
public class HeaderRequestValsExampleTest extends JUnitRouteTest {
@Test
public void testHeaderVals() {
//#by-class
final Route route =
extractHost(host ->
complete(String.format("Host header was: %s", host))
);
// tests:
final HttpRequest request =
HttpRequest
.GET("http://akka.io/")
.addHeader(Host.create("akka.io"));
testRoute(route).run(request).assertEntity("Host header was: akka.io");
//#by-class
}
@Test
public void testHeaderByName() {
//#by-name
final Route route =
// extract the `value` of the header:
headerValueByName("X-Fish-Name", xFishName ->
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
}
}

View file

@ -1,45 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
//#binding-failure-high-level-example
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.Http;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import java.io.IOException;
import java.util.concurrent.CompletionStage;
public class HighLevelServerBindFailureExample {
public static void main(String[] args) throws IOException {
// boot up server using the route as defined below
final ActorSystem system = ActorSystem.create();
final ActorMaterializer materializer = ActorMaterializer.create(system);
// HttpApp.bindRoute expects a route being provided by HttpApp.createRoute
final HighLevelServerExample app = new HighLevelServerExample();
final Route route = app.createRoute();
final Flow<HttpRequest, HttpResponse, NotUsed> handler = route.flow(system, materializer);
final CompletionStage<ServerBinding> binding = Http.get(system).bindAndHandle(handler, ConnectHttp.toHost("127.0.0.1", 8080), materializer);
binding.exceptionally(failure -> {
System.err.println("Something very bad happened! " + failure.getMessage());
system.terminate();
return null;
});
system.terminate();
}
}
//#binding-failure-high-level-example

View file

@ -1,77 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
//#high-level-server-example
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.ContentTypes;
import akka.http.javadsl.model.HttpEntities;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import java.io.IOException;
import java.util.concurrent.CompletionStage;
public class HighLevelServerExample extends AllDirectives {
public static void main(String[] args) throws IOException {
// boot up server using the route as defined below
ActorSystem system = ActorSystem.create();
// HttpApp.bindRoute expects a route being provided by HttpApp.createRoute
final HighLevelServerExample app = new HighLevelServerExample();
final Http http = Http.get(system);
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Flow<HttpRequest, HttpResponse, NotUsed> routeFlow = app.createRoute().flow(system, materializer);
final CompletionStage<ServerBinding> binding = http.bindAndHandle(routeFlow, ConnectHttp.toHost("localhost", 8080), materializer);
System.out.println("Type RETURN to exit");
System.in.read();
binding
.thenCompose(ServerBinding::unbind)
.thenAccept(unbound -> system.terminate());
}
public Route createRoute() {
// This handler generates responses to `/hello?name=XXX` requests
Route helloRoute =
parameterOptional("name", optName -> {
String name = optName.orElse("Mister X");
return complete("Hello " + name + "!");
});
return
// here the complete behavior for this server is defined
// only handle GET requests
get(() -> route(
// matches the empty path
pathSingleSlash(() ->
// return a constant string with a certain content type
complete(HttpEntities.create(ContentTypes.TEXT_HTML_UTF8, "<html><body>Hello world!</body></html>"))
),
path("ping", () ->
// return a simple `text/plain` response
complete("PONG!")
),
path("hello", () ->
// uses the route defined above
helloRoute
)
));
}
}
//#high-level-server-example

View file

@ -1,55 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import java.util.Optional;
import org.junit.Test;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.scaladsl.model.headers.Authorization;
public class HttpBasicAuthenticatorExample extends JUnitRouteTest {
private final String hardcodedPassword = "correcthorsebatterystaple";
private Optional<String> authenticate(Optional<ProvidedCredentials> creds) {
// this is where your actual authentication logic would go
return creds
.filter(c -> c.verify(hardcodedPassword)) // Only allow users that provide the right password
.map(c -> c.identifier()); // Provide the username down to the inner route
}
@Test
public void testBasicAuthenticator() {
//#basic-authenticator-java
final Route route =
authenticateBasic("My realm", this::authenticate, user ->
complete("Hello " + user + "!")
);
// tests:
final HttpRequest okRequest =
HttpRequest
.GET("http://akka.io/")
.addHeader(Host.create("akka.io"))
.addHeader(Authorization.basic("randal", "correcthorsebatterystaple"));
testRoute(route).run(okRequest).assertEntity("Hello randal!");
final HttpRequest badRequest =
HttpRequest
.GET("http://akka.io/")
.addHeader(Host.create("akka.io"))
.addHeader(Authorization.basic("randal", "123abc"));
testRoute(route).run(badRequest).assertStatusCode(401);
//#basic-authenticator-java
}
}

View file

@ -1,328 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import akka.Done;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.IncomingConnection;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.marshallers.jackson.Jackson;
import akka.http.javadsl.model.*;
import akka.http.javadsl.model.headers.Connection;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.unmarshalling.Unmarshaller;
import akka.japi.function.Function;
import akka.stream.ActorMaterializer;
import akka.stream.IOResult;
import akka.stream.Materializer;
import akka.stream.javadsl.FileIO;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import akka.util.ByteString;
import scala.concurrent.ExecutionContextExecutor;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import static akka.http.javadsl.server.Directives.*;
@SuppressWarnings("unused")
public class HttpServerExampleDocTest {
public static void bindingExample() throws Exception {
//#binding-example
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind(ConnectHttp.toHost("localhost", 8080), materializer);
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}
)).run(materializer);
//#binding-example
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void bindingFailureExample() throws Exception {
//#binding-failure-handling
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind(ConnectHttp.toHost("localhost", 80), materializer);
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}
)).run(materializer);
serverBindingFuture.whenCompleteAsync((binding, failure) -> {
// possibly report the failure somewhere...
}, system.dispatcher());
//#binding-failure-handling
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void connectionSourceFailureExample() throws Exception {
//#incoming-connections-source-failure-handling
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind(ConnectHttp.toHost("localhost", 8080), materializer);
Flow<IncomingConnection, IncomingConnection, NotUsed> failureDetection =
Flow.of(IncomingConnection.class).watchTermination((notUsed, termination) -> {
termination.whenComplete((done, cause) -> {
if (cause != null) {
// signal the failure to external monitoring service!
}
});
return NotUsed.getInstance();
});
CompletionStage<ServerBinding> serverBindingFuture =
serverSource
.via(failureDetection) // feed signals through our custom stage
.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
// ... and then actually handle the connection
}))
.run(materializer);
//#incoming-connections-source-failure-handling
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void connectionStreamFailureExample() throws Exception {
//#connection-stream-failure-handling
ActorSystem system = ActorSystem.create();
Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind(ConnectHttp.toHost("localhost", 8080), materializer);
Flow<HttpRequest, HttpRequest, NotUsed> failureDetection =
Flow.of(HttpRequest.class)
.watchTermination((notUsed, termination) -> {
termination.whenComplete((done, cause) -> {
if (cause != null) {
// signal the failure to external monitoring service!
}
});
return NotUsed.getInstance();
});
Flow<HttpRequest, HttpResponse, NotUsed> httpEcho =
Flow.of(HttpRequest.class)
.via(failureDetection)
.map(request -> {
Source<ByteString, Object> bytes = request.entity().getDataBytes();
HttpEntity.Chunked entity = HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, bytes);
return HttpResponse.create()
.withEntity(entity);
});
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(conn -> {
System.out.println("Accepted new connection from " + conn.remoteAddress());
conn.handleWith(httpEcho, materializer);
}
)).run(materializer);
//#connection-stream-failure-handling
serverBindingFuture.toCompletableFuture().get(3, TimeUnit.SECONDS);
}
public static void fullServerExample() throws Exception {
//#full-server-example
ActorSystem system = ActorSystem.create();
//#full-server-example
try {
//#full-server-example
final Materializer materializer = ActorMaterializer.create(system);
Source<IncomingConnection, CompletionStage<ServerBinding>> serverSource =
Http.get(system).bind(ConnectHttp.toHost("localhost", 8080), materializer);
//#request-handler
final Function<HttpRequest, HttpResponse> requestHandler =
new Function<HttpRequest, HttpResponse>() {
private final HttpResponse NOT_FOUND =
HttpResponse.create()
.withStatus(404)
.withEntity("Unknown resource!");
@Override
public HttpResponse apply(HttpRequest request) throws Exception {
Uri uri = request.getUri();
if (request.method() == HttpMethods.GET) {
if (uri.path().equals("/")) {
return
HttpResponse.create()
.withEntity(ContentTypes.TEXT_HTML_UTF8,
"<html><body>Hello world!</body></html>");
} else if (uri.path().equals("/hello")) {
String name = uri.query().get("name").orElse("Mister X");
return
HttpResponse.create()
.withEntity("Hello " + name + "!");
} else if (uri.path().equals("/ping")) {
return HttpResponse.create().withEntity("PONG!");
} else {
return NOT_FOUND;
}
} else {
return NOT_FOUND;
}
}
};
//#request-handler
CompletionStage<ServerBinding> serverBindingFuture =
serverSource.to(Sink.foreach(connection -> {
System.out.println("Accepted new connection from " + connection.remoteAddress());
connection.handleWithSyncHandler(requestHandler, materializer);
// this is equivalent to
//connection.handleWith(Flow.of(HttpRequest.class).map(requestHandler), materializer);
})).run(materializer);
//#full-server-example
serverBindingFuture.toCompletableFuture().get(1, TimeUnit.SECONDS); // will throw if binding fails
System.out.println("Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
} finally {
system.terminate();
}
}
public static void main(String[] args) throws Exception {
fullServerExample();
}
//#consume-entity-directive
class Bid {
final String userId;
final int bid;
Bid(String userId, int bid) {
this.userId = userId;
this.bid = bid;
}
}
//#consume-entity-directive
void consumeEntityUsingEntityDirective() {
//#consume-entity-directive
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Unmarshaller<HttpEntity, Bid> asBid = Jackson.unmarshaller(Bid.class);
final Route s = path("bid", () ->
put(() ->
entity(asBid, bid ->
// incoming entity is fully consumed and converted into a Bid
complete("The bid was: " + bid)
)
)
);
//#consume-entity-directive
}
void consumeEntityUsingRawDataBytes() {
//#consume-raw-dataBytes
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Route s =
put(() ->
path("lines", () ->
withoutSizeLimit(() ->
extractDataBytes(bytes -> {
final CompletionStage<IOResult> res = bytes.runWith(FileIO.toPath(new File("/tmp/example.out").toPath()), materializer);
return onComplete(() -> res, ioResult ->
// we only want to respond once the incoming data has been handled:
complete("Finished writing data :" + ioResult));
})
)
)
);
//#consume-raw-dataBytes
}
void discardEntityUsingRawBytes() {
//#discard-discardEntityBytes
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Route s =
put(() ->
path("lines", () ->
withoutSizeLimit(() ->
extractRequest(r -> {
final CompletionStage<Done> res = r.discardEntityBytes(materializer).completionStage();
return onComplete(() -> res, done ->
// we only want to respond once the incoming data has been handled:
complete("Finished writing data :" + done));
})
)
)
);
//#discard-discardEntityBytes
}
void discardEntityManuallyCloseConnections() {
//#discard-close-connections
final ActorSystem system = ActorSystem.create();
final ExecutionContextExecutor dispatcher = system.dispatcher();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final Route s =
put(() ->
path("lines", () ->
withoutSizeLimit(() ->
extractDataBytes(bytes -> {
// Closing connections, method 1 (eager):
// we deem this request as illegal, and close the connection right away:
bytes.runWith(Sink.cancelled(), materializer); // "brutally" closes the connection
// Closing connections, method 2 (graceful):
// consider draining connection and replying with `Connection: Close` header
// if you want the client to close after this request/reply cycle instead:
return respondWithHeader(Connection.create("close"), () ->
complete(StatusCodes.FORBIDDEN, "Not allowed!")
);
})
)
)
);
//#discard-close-connections
}
}

View file

@ -1,27 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import akka.actor.ActorSystem;
import com.typesafe.sslconfig.akka.AkkaSSLConfig;
import org.junit.Test;
import org.scalatest.junit.JUnitSuite;
/* COMPILE ONLY TEST */
public class HttpsServerExampleTest extends JUnitSuite {
@Test
public void compileOnlySpec() throws Exception {
// just making sure for it to be really compiled / run even if empty
}
void sslConfigGet() {
//#akka-ssl-config
final ActorSystem system = ActorSystem.create();
final AkkaSSLConfig sslConfig = AkkaSSLConfig.get(system);
//#
}
}

View file

@ -1,179 +0,0 @@
/*
* Copyright (C) 2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import akka.NotUsed;
import akka.http.javadsl.common.CsvEntityStreamingSupport;
import akka.http.javadsl.common.JsonEntityStreamingSupport;
import akka.http.javadsl.marshallers.jackson.Jackson;
import akka.http.javadsl.marshalling.Marshaller;
import akka.http.javadsl.model.*;
import akka.http.javadsl.model.headers.Accept;
import akka.http.javadsl.server.*;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.javadsl.testkit.TestRoute;
import akka.http.javadsl.unmarshalling.StringUnmarshallers;
import akka.http.javadsl.common.EntityStreamingSupport;
import akka.http.javadsl.unmarshalling.Unmarshaller;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import akka.util.ByteString;
import org.junit.Test;
import java.util.concurrent.CompletionStage;
public class JsonStreamingExamplesTest extends JUnitRouteTest {
//#routes
final Route tweets() {
//#formats
final Unmarshaller<ByteString, JavaTweet> JavaTweets = Jackson.byteStringUnmarshaller(JavaTweet.class);
//#formats
//#response-streaming
// Step 1: Enable JSON streaming
// we're not using this in the example, but it's the simplest way to start:
// The default rendering is a JSON array: `[el, el, el , ...]`
final JsonEntityStreamingSupport jsonStreaming = EntityStreamingSupport.json();
// Step 1.1: Enable and customise how we'll render the JSON, as a compact array:
final ByteString start = ByteString.fromString("[");
final ByteString between = ByteString.fromString(",");
final ByteString end = ByteString.fromString("]");
final Flow<ByteString, ByteString, NotUsed> compactArrayRendering =
Flow.of(ByteString.class).intersperse(start, between, end);
final JsonEntityStreamingSupport compactJsonSupport = EntityStreamingSupport.json()
.withFramingRendererFlow(compactArrayRendering);
// Step 2: implement the route
final Route responseStreaming = path("tweets", () ->
get(() ->
parameter(StringUnmarshallers.INTEGER, "n", n -> {
final Source<JavaTweet, NotUsed> tws =
Source.repeat(new JavaTweet(12, "Hello World!")).take(n);
// Step 3: call complete* with your source, marshaller, and stream rendering mode
return completeOKWithSource(tws, Jackson.marshaller(), compactJsonSupport);
})
)
);
//#response-streaming
//#incoming-request-streaming
final Route incomingStreaming = path("tweets", () ->
post(() ->
extractMaterializer(mat -> {
final JsonEntityStreamingSupport jsonSupport = EntityStreamingSupport.json();
return entityAsSourceOf(JavaTweets, jsonSupport, sourceOfTweets -> {
final CompletionStage<Integer> tweetsCount = sourceOfTweets.runFold(0, (acc, tweet) -> acc + 1, mat);
return onComplete(tweetsCount, c -> complete("Total number of tweets: " + c));
});
}
)
)
);
//#incoming-request-streaming
return responseStreaming.orElse(incomingStreaming);
}
final Route csvTweets() {
//#csv-example
final Marshaller<JavaTweet, ByteString> renderAsCsv =
Marshaller.withFixedContentType(ContentTypes.TEXT_CSV_UTF8, t ->
ByteString.fromString(t.getId() + "," + t.getMessage())
);
final CsvEntityStreamingSupport compactJsonSupport = EntityStreamingSupport.csv();
final Route responseStreaming = path("tweets", () ->
get(() ->
parameter(StringUnmarshallers.INTEGER, "n", n -> {
final Source<JavaTweet, NotUsed> tws =
Source.repeat(new JavaTweet(12, "Hello World!")).take(n);
return completeWithSource(tws, renderAsCsv, compactJsonSupport);
})
)
);
//#csv-example
return responseStreaming;
}
//#routes
@Test
public void getTweetsTest() {
//#response-streaming
// tests:
final TestRoute routes = testRoute(tweets());
// test happy path
final Accept acceptApplication = Accept.create(MediaRanges.create(MediaTypes.APPLICATION_JSON));
routes.run(HttpRequest.GET("/tweets?n=2").addHeader(acceptApplication))
.assertStatusCode(200)
.assertEntity("[{\"id\":12,\"message\":\"Hello World!\"},{\"id\":12,\"message\":\"Hello World!\"}]");
// test responses to potential errors
final Accept acceptText = Accept.create(MediaRanges.ALL_TEXT);
routes.run(HttpRequest.GET("/tweets?n=3").addHeader(acceptText))
.assertStatusCode(StatusCodes.NOT_ACCEPTABLE) // 406
.assertEntity("Resource representation is only available with these types:\napplication/json");
//#response-streaming
}
@Test
public void csvExampleTweetsTest() {
//#response-streaming
// tests --------------------------------------------
final TestRoute routes = testRoute(csvTweets());
// test happy path
final Accept acceptCsv = Accept.create(MediaRanges.create(MediaTypes.TEXT_CSV));
routes.run(HttpRequest.GET("/tweets?n=2").addHeader(acceptCsv))
.assertStatusCode(200)
.assertEntity("12,Hello World!\n" +
"12,Hello World!");
// test responses to potential errors
final Accept acceptText = Accept.create(MediaRanges.ALL_APPLICATION);
routes.run(HttpRequest.GET("/tweets?n=3").addHeader(acceptText))
.assertStatusCode(StatusCodes.NOT_ACCEPTABLE) // 406
.assertEntity("Resource representation is only available with these types:\ntext/csv; charset=UTF-8");
//#response-streaming
}
//#models
private static final class JavaTweet {
private int id;
private String message;
public JavaTweet(int id, String message) {
this.id = id;
this.message = message;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
//#models
}

View file

@ -1,59 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.scaladsl.model.headers.Authorization;
import java.util.Optional;
import org.junit.Test;
public class OAuth2AuthenticatorExample extends JUnitRouteTest {
private final String hardcodedToken = "token";
private Optional<String> authenticate(Optional<ProvidedCredentials> creds) {
// this is where your actual authentication logic would go, looking up the user
// based on the token or something in that direction
// We will not allow anonymous access.
return creds
.filter(c -> c.verify(hardcodedToken)) //
.map(c -> c.identifier()); // Provide the "identifier" down to the inner route
// (for OAuth2, that's actually just the token)
}
@Test
public void testOAuth2Authenticator() {
//#oauth2-authenticator-java
final Route route =
authenticateOAuth2("My realm", this::authenticate, token ->
complete("The secret token is: " + token)
);
// tests:
final HttpRequest okRequest =
HttpRequest
.GET("http://akka.io/")
.addHeader(Host.create("akka.io"))
.addHeader(Authorization.oauth2("token"));
testRoute(route).run(okRequest).assertEntity("The secret token is: token");
final HttpRequest badRequest =
HttpRequest
.GET("http://akka.io/")
.addHeader(Host.create("akka.io"))
.addHeader(Authorization.oauth2("wrong"));
testRoute(route).run(badRequest).assertStatusCode(401);
//#oauth2-authenticator-java
}
}

View file

@ -1,79 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.PathMatchers;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
public class PathDirectiveExampleTest extends JUnitRouteTest {
@Test
public void testPathPrefix() {
//#path-examples
// matches "/test"
path("test", () ->
complete(StatusCodes.OK)
);
// matches "/test", as well
path(PathMatchers.segment("test"), () ->
complete(StatusCodes.OK)
);
// matches "/admin/user"
path(PathMatchers.segment("admin")
.slash("user"), () ->
complete(StatusCodes.OK)
);
// matches "/admin/user", as well
pathPrefix("admin", () ->
path("user", () ->
complete(StatusCodes.OK)
)
);
// matches "/admin/user/<user-id>"
path(PathMatchers.segment("admin")
.slash("user")
.slash(PathMatchers.integerSegment()), userId -> {
return complete("Hello user " + userId);
}
);
// matches "/admin/user/<user-id>", as well
pathPrefix("admin", () ->
path("user", () ->
path(PathMatchers.integerSegment(), userId ->
complete("Hello user " + userId)
)
)
);
// never matches
path("admin", () -> // oops this only matches "/admin", and no sub-paths
path("user", () ->
complete(StatusCodes.OK)
)
);
// matches "/user/" with the first subroute, "/user" (without a trailing slash)
// with the second subroute, and "/user/<user-id>" with the last one.
pathPrefix("user", () -> route(
pathSingleSlash(() ->
complete(StatusCodes.OK)
),
pathEnd(() ->
complete(StatusCodes.OK)
),
path(PathMatchers.integerSegment(), userId ->
complete("Hello user " + userId)
)
));
//#path-examples
}
}

View file

@ -1,105 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
//#websocket-example-using-core
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
import akka.NotUsed;
import akka.http.javadsl.ConnectHttp;
import akka.japi.Function;
import akka.japi.JavaPartialFunction;
import akka.stream.ActorMaterializer;
import akka.stream.Materializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import akka.actor.ActorSystem;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.ws.Message;
import akka.http.javadsl.model.ws.TextMessage;
import akka.http.javadsl.model.ws.WebSocket;
@SuppressWarnings("Convert2MethodRef")
public class WebSocketCoreExample {
//#websocket-handling
public static HttpResponse handleRequest(HttpRequest request) {
System.out.println("Handling request to " + request.getUri());
if (request.getUri().path().equals("/greeter")) {
final Flow<Message, Message, NotUsed> greeterFlow = greeter();
return WebSocket.handleWebSocketRequestWith(request, greeterFlow);
} else {
return HttpResponse.create().withStatus(404);
}
}
//#websocket-handling
public static void main(String[] args) throws Exception {
ActorSystem system = ActorSystem.create();
try {
final Materializer materializer = ActorMaterializer.create(system);
final Function<HttpRequest, HttpResponse> handler = request -> handleRequest(request);
CompletionStage<ServerBinding> serverBindingFuture =
Http.get(system).bindAndHandleSync(
handler, ConnectHttp.toHost("localhost", 8080), materializer);
// will throw if binding fails
serverBindingFuture.toCompletableFuture().get(1, TimeUnit.SECONDS);
System.out.println("Press ENTER to stop.");
new BufferedReader(new InputStreamReader(System.in)).readLine();
} finally {
system.terminate();
}
}
//#websocket-handler
/**
* A handler that treats incoming messages as a name,
* and responds with a greeting to that name
*/
public static Flow<Message, Message, NotUsed> greeter() {
return
Flow.<Message>create()
.collect(new JavaPartialFunction<Message, Message>() {
@Override
public Message apply(Message msg, boolean isCheck) throws Exception {
if (isCheck) {
if (msg.isText()) {
return null;
} else {
throw noMatch();
}
} else {
return handleTextMessage(msg.asTextMessage());
}
}
});
}
public static TextMessage handleTextMessage(TextMessage msg) {
if (msg.isStrict()) // optimization that directly creates a simple response...
{
return TextMessage.create("Hello " + msg.getStrictText());
} else // ... this would suffice to handle all text messages in a streaming fashion
{
return TextMessage.create(Source.single("Hello ").concat(msg.getStreamedText()));
}
}
//#websocket-handler
}
//#websocket-example-using-core

View file

@ -1,54 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server;
import akka.NotUsed;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;
import akka.japi.JavaPartialFunction;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import akka.http.javadsl.model.ws.Message;
import akka.http.javadsl.model.ws.TextMessage;
public class WebSocketRoutingExample extends AllDirectives {
//#websocket-route
public Route createRoute() {
return
path("greeter", () ->
handleWebSocketMessages(greeter())
);
}
//#websocket-route
/**
* A handler that treats incoming messages as a name,
* and responds with a greeting to that name
*/
public static Flow<Message, Message, NotUsed> greeter() {
return
Flow.<Message>create()
.collect(new JavaPartialFunction<Message, Message>() {
@Override
public Message apply(Message msg, boolean isCheck) throws Exception {
if (isCheck) {
if (msg.isText()) return null;
else throw noMatch();
} else return handleTextMessage(msg.asTextMessage());
}
});
}
public static TextMessage handleTextMessage(TextMessage msg) {
if (msg.isStrict()) // optimization that directly creates a simple response...
{
return TextMessage.create("Hello " + msg.getStrictText());
} else // ... this would suffice to handle all text messages in a streaming fashion
{
return TextMessage.create(Source.single("Hello ").concat(msg.getStreamedText()));
}
}
}

View file

@ -1,893 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.dispatch.ExecutionContexts;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.http.javadsl.model.ContentTypes;
import akka.http.javadsl.model.HttpEntities;
import akka.http.javadsl.model.HttpEntity;
import akka.http.javadsl.model.HttpMethods;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.ResponseEntity;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.RawHeader;
import akka.http.javadsl.model.headers.Server;
import akka.http.javadsl.model.headers.ProductVersion;
import akka.http.javadsl.settings.RoutingSettings;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.javadsl.server.*;
import akka.japi.pf.PFBuilder;
import akka.stream.ActorMaterializer;
import akka.stream.ActorMaterializerSettings;
import akka.stream.javadsl.FileIO;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import akka.util.ByteString;
import org.junit.Ignore;
import org.junit.Test;
import scala.concurrent.ExecutionContextExecutor;
import scala.concurrent.duration.FiniteDuration;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.StreamSupport;
public class BasicDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testExtract() {
//#extract
final Route route = extract(
ctx -> ctx.getRequest().getUri().toString().length(),
len -> complete("The length of the request URI is " + len)
);
// tests:
testRoute(route).run(HttpRequest.GET("/abcdef"))
.assertEntity("The length of the request URI is 25");
//#extract
}
@Test
public void testExtractLog() {
//#extractLog
final Route route = extractLog(log -> {
log.debug("I'm logging things in much detail..!");
return complete("It's amazing!");
});
// tests:
testRoute(route).run(HttpRequest.GET("/abcdef"))
.assertEntity("It's amazing!");
//#extractLog
}
@Test
public void testWithMaterializer() {
//#withMaterializer
final ActorMaterializerSettings settings = ActorMaterializerSettings.create(system());
final ActorMaterializer special = ActorMaterializer.create(settings, system(), "special");
final Route sample = path("sample", () ->
extractMaterializer(mat ->
onSuccess(() ->
// explicitly use the materializer:
Source.single("Materialized by " + mat.hashCode() + "!")
.runWith(Sink.head(), mat), this::complete
)
)
);
final Route route = route(
pathPrefix("special", () ->
withMaterializer(special, () -> sample) // `special` materializer will be used
),
sample // default materializer will be used
);
// tests:
testRoute(route).run(HttpRequest.GET("/sample"))
.assertEntity("Materialized by " + materializer().hashCode()+ "!");
testRoute(route).run(HttpRequest.GET("/special/sample"))
.assertEntity("Materialized by " + special.hashCode()+ "!");
//#withMaterializer
}
@Test
public void testExtractMaterializer() {
//#extractMaterializer
final Route route = path("sample", () ->
extractMaterializer(mat ->
onSuccess(() ->
// explicitly use the materializer:
Source.single("Materialized by " + mat.hashCode() + "!")
.runWith(Sink.head(), mat), this::complete
)
)
); // default materializer will be used
testRoute(route).run(HttpRequest.GET("/sample"))
.assertEntity("Materialized by " + materializer().hashCode()+ "!");
//#extractMaterializer
}
@Test
public void testWithExecutionContext() {
//#withExecutionContext
final ExecutionContextExecutor special =
ExecutionContexts.fromExecutor(Executors.newFixedThreadPool(1));
final Route sample = path("sample", () ->
extractExecutionContext(executor ->
onSuccess(() ->
CompletableFuture.supplyAsync(() ->
"Run on " + executor.hashCode() + "!", executor
), this::complete
)
)
);
final Route route = route(
pathPrefix("special", () ->
// `special` execution context will be used
withExecutionContext(special, () -> sample)
),
sample // default execution context will be used
);
// tests:
testRoute(route).run(HttpRequest.GET("/sample"))
.assertEntity("Run on " + system().dispatcher().hashCode() + "!");
testRoute(route).run(HttpRequest.GET("/special/sample"))
.assertEntity("Run on " + special.hashCode() + "!");
//#withExecutionContext
}
@Test
public void testExtractExecutionContext() {
//#extractExecutionContext
final Route route = path("sample", () ->
extractExecutionContext(executor ->
onSuccess(() ->
CompletableFuture.supplyAsync(
// uses the `executor` ExecutionContext
() -> "Run on " + executor.hashCode() + "!", executor
), str -> complete(str)
)
)
);
//tests:
testRoute(route).run(HttpRequest.GET("/sample"))
.assertEntity("Run on " + system().dispatcher().hashCode() + "!");
//#extractExecutionContext
}
@Test
public void testWithLog() {
//#withLog
final LoggingAdapter special = Logging.getLogger(system(), "SpecialRoutes");
final Route sample = path("sample", () ->
extractLog(log -> {
final String msg = "Logging using " + log + "!";
log.debug(msg);
return complete(msg);
}
)
);
final Route route = route(
pathPrefix("special", () ->
withLog(special, () -> sample)
),
sample
);
// tests:
testRoute(route).run(HttpRequest.GET("/sample"))
.assertEntity("Logging using " + system().log() + "!");
testRoute(route).run(HttpRequest.GET("/special/sample"))
.assertEntity("Logging using " + special + "!");
//#withLog
}
@Ignore("Ignore compile-only test")
@Test
public void testWithSettings() {
//#withSettings
final RoutingSettings special =
RoutingSettings
.create(system().settings().config())
.withFileIODispatcher("special-io-dispatcher");
final Route sample = path("sample", () -> {
// internally uses the configured fileIODispatcher:
// ContentTypes.APPLICATION_JSON, source
final Source<ByteString, Object> source =
FileIO.fromPath(Paths.get("example.json"))
.mapMaterializedValue(completionStage -> (Object) completionStage);
return complete(
HttpResponse.create()
.withEntity(HttpEntities.create(ContentTypes.APPLICATION_JSON, source))
);
});
final Route route = get(() ->
route(
pathPrefix("special", () ->
// `special` file-io-dispatcher will be used to read the file
withSettings(special, () -> sample)
),
sample // default file-io-dispatcher will be used to read the file
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/special/sample"))
.assertEntity("{}");
testRoute(route).run(HttpRequest.GET("/sample"))
.assertEntity("{}");
//#withSettings
}
@Test
public void testMapResponse() {
//#mapResponse
final Route route = mapResponse(
response -> response.withStatus(StatusCodes.BAD_GATEWAY),
() -> complete("abc")
);
// tests:
testRoute(route).run(HttpRequest.GET("/abcdef?ghi=12"))
.assertStatusCode(StatusCodes.BAD_GATEWAY);
//#mapResponse
}
@Test
public void testMapResponseAdvanced() {
//#mapResponse-advanced
class ApiRoute {
private final ActorSystem system;
private final LoggingAdapter log;
private final HttpEntity nullJsonEntity =
HttpEntities.create(ContentTypes.APPLICATION_JSON, "{}");
public ApiRoute(ActorSystem system) {
this.system = system;
this.log = Logging.getLogger(system, "ApiRoutes");
}
private HttpResponse nonSuccessToEmptyJsonEntity(HttpResponse response) {
if (response.status().isSuccess()) {
return response;
} else {
log.warning(
"Dropping response entity since response status code was: " + response.status());
return response.withEntity((ResponseEntity) nullJsonEntity);
}
}
/** Wrapper for all of our JSON API routes */
private Route apiRoute(Supplier<Route> innerRoutes) {
return mapResponse(this::nonSuccessToEmptyJsonEntity, innerRoutes);
}
}
final ApiRoute api = new ApiRoute(system());
final Route route = api.apiRoute(() ->
get(() -> complete(StatusCodes.INTERNAL_SERVER_ERROR))
);
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("{}");
//#mapResponse-advanced
}
@Test
public void testMapRouteResult() {
//#mapRouteResult
// this directive is a joke, don't do that :-)
final Route route = mapRouteResult(r -> {
if (r instanceof Complete) {
final HttpResponse response = ((Complete) r).getResponse();
return RouteResults.complete(response.withStatus(200));
} else {
return r;
}
}, () -> complete(StatusCodes.ACCEPTED));
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.OK);
//#mapRouteResult
}
@Test
public void testMapRouteResultFuture() {
//#mapRouteResultFuture
final Route route = mapRouteResultFuture(cr ->
cr.exceptionally(t -> {
if (t instanceof IllegalArgumentException) {
return RouteResults.complete(
HttpResponse.create().withStatus(StatusCodes.INTERNAL_SERVER_ERROR));
} else {
return null;
}
}).thenApply(rr -> {
if (rr instanceof Complete) {
final HttpResponse res = ((Complete) rr).getResponse();
return RouteResults.complete(
res.addHeader(Server.create(ProductVersion.create("MyServer", "1.0"))));
} else {
return rr;
}
}), () -> complete("Hello world!"));
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.OK)
.assertHeaderExists(Server.create(ProductVersion.create("MyServer", "1.0")));
//#mapRouteResultFuture
}
@Test
public void testMapResponseEntity() {
//#mapResponseEntity
final Function<ResponseEntity, ResponseEntity> prefixEntity = entity -> {
if (entity instanceof HttpEntity.Strict) {
final HttpEntity.Strict strict = (HttpEntity.Strict) entity;
return HttpEntities.create(
strict.getContentType(),
ByteString.fromString("test").concat(strict.getData()));
} else {
throw new IllegalStateException("Unexpected entity type");
}
};
final Route route = mapResponseEntity(prefixEntity, () -> complete("abc"));
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("testabc");
//#mapResponseEntity
}
@Test
public void testMapResponseHeaders() {
//#mapResponseHeaders
// adds all request headers to the response
final Route echoRequestHeaders = extract(
ctx -> ctx.getRequest().getHeaders(),
headers -> respondWithHeaders(headers, () -> complete("test"))
);
final Route route = mapResponseHeaders(headers -> {
headers.removeIf(header -> header.lowercaseName().equals("id"));
return headers;
}, () -> echoRequestHeaders);
// tests:
testRoute(route).run(HttpRequest.GET("/").addHeaders(
Arrays.asList(RawHeader.create("id", "12345"),RawHeader.create("id2", "67890"))))
.assertHeaderKindNotExists("id")
.assertHeaderExists("id2", "67890");
//#mapResponseHeaders
}
@Ignore("Not implemented yet")
@Test
public void testMapInnerRoute() {
//#mapInnerRoute
// TODO: implement mapInnerRoute
//#mapInnerRoute
}
@Test
public void testMapRejections() {
//#mapRejections
// ignore any rejections and replace them by AuthorizationFailedRejection
final Route route = mapRejections(
rejections -> Collections.singletonList((Rejection) Rejections.authorizationFailed()),
() -> path("abc", () -> complete("abc"))
);
// tests:
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections(Rejections.authorizationFailed());
testRoute(route).run(HttpRequest.GET("/abc"))
.assertStatusCode(StatusCodes.OK);
//#mapRejections
}
@Test
public void testRecoverRejections() {
//#recoverRejections
final Function<Optional<ProvidedCredentials>, Optional<Object>> neverAuth =
creds -> Optional.empty();
final Function<Optional<ProvidedCredentials>, Optional<Object>> alwaysAuth =
creds -> Optional.of("id");
final Route originalRoute = pathPrefix("auth", () ->
route(
path("never", () ->
authenticateBasic("my-realm", neverAuth, obj -> complete("Welcome to the bat-cave!"))
),
path("always", () ->
authenticateBasic("my-realm", alwaysAuth, obj -> complete("Welcome to the secret place!"))
)
)
);
final Function<Iterable<Rejection>, Boolean> existsAuthenticationFailedRejection =
rejections ->
StreamSupport.stream(rejections.spliterator(), false)
.anyMatch(r -> r instanceof AuthenticationFailedRejection);
final Route route = recoverRejections(rejections -> {
if (existsAuthenticationFailedRejection.apply(rejections)) {
return RouteResults.complete(
HttpResponse.create().withEntity("Nothing to see here, move along."));
} else if (!rejections.iterator().hasNext()) { // see "Empty Rejections" for more details
return RouteResults.complete(
HttpResponse.create().withStatus(StatusCodes.NOT_FOUND)
.withEntity("Literally nothing to see here."));
} else {
return RouteResults.rejected(rejections);
}
}, () -> originalRoute);
// tests:
testRoute(route).run(HttpRequest.GET("/auth/never"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("Nothing to see here, move along.");
testRoute(route).run(HttpRequest.GET("/auth/always"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("Welcome to the secret place!");
testRoute(route).run(HttpRequest.GET("/auth/does_not_exist"))
.assertStatusCode(StatusCodes.NOT_FOUND)
.assertEntity("Literally nothing to see here.");
//#recoverRejections
}
@Test
public void testRecoverRejectionsWith() {
//#recoverRejectionsWith
final Function<Optional<ProvidedCredentials>, Optional<Object>> neverAuth =
creds -> Optional.empty();
final Route originalRoute = pathPrefix("auth", () ->
path("never", () ->
authenticateBasic("my-realm", neverAuth, obj -> complete("Welcome to the bat-cave!"))
)
);
final Function<Iterable<Rejection>, Boolean> existsAuthenticationFailedRejection =
rejections ->
StreamSupport.stream(rejections.spliterator(), false)
.anyMatch(r -> r instanceof AuthenticationFailedRejection);
final Route route = recoverRejectionsWith(
rejections -> CompletableFuture.supplyAsync(() -> {
if (existsAuthenticationFailedRejection.apply(rejections)) {
return RouteResults.complete(
HttpResponse.create().withEntity("Nothing to see here, move along."));
} else {
return RouteResults.rejected(rejections);
}
}), () -> originalRoute);
// tests:
testRoute(route).run(HttpRequest.GET("/auth/never"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("Nothing to see here, move along.");
//#recoverRejectionsWith
}
@Test
public void testMapRequest() {
//#mapRequest
final Route route = mapRequest(req ->
req.withMethod(HttpMethods.POST), () ->
extractRequest(req -> complete("The request method was " + req.method().name()))
);
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("The request method was POST");
//#mapRequest
}
@Test
public void testMapRequestContext() {
//#mapRequestContext
final Route route = mapRequestContext(ctx ->
ctx.withRequest(HttpRequest.create().withMethod(HttpMethods.POST)), () ->
extractRequest(req -> complete(req.method().value()))
);
// tests:
testRoute(route).run(HttpRequest.GET("/abc/def/ghi"))
.assertEntity("POST");
//#mapRequestContext
}
@Test
public void testMapRouteResult0() {
//#mapRouteResult
final Route route = mapRouteResult(rr -> {
final Iterable<Rejection> rejections = Collections.singletonList(Rejections.authorizationFailed());
return RouteResults.rejected(rejections);
}, () -> complete("abc"));
// tests:
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections(Rejections.authorizationFailed());
//#mapRouteResult
}
public static final class MyCustomRejection implements CustomRejection {}
@Test
public void testMapRouteResultPF() {
//#mapRouteResultPF
final Route route = mapRouteResultPF(
new PFBuilder<RouteResult, RouteResult>()
.match(Rejected.class, rejected -> {
final Iterable<Rejection> rejections =
Collections.singletonList(Rejections.authorizationFailed());
return RouteResults.rejected(rejections);
}).build(), () -> reject(new MyCustomRejection()));
// tests:
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections(Rejections.authorizationFailed());
//#mapRouteResultPF
}
@Test
public void testMapRouteResultWithPF() {
//#mapRouteResultWithPF
final Route route = mapRouteResultWithPF(
new PFBuilder<RouteResult, CompletionStage<RouteResult>>()
.match(Rejected.class, rejected -> CompletableFuture.supplyAsync(() -> {
final Iterable<Rejection> rejections =
Collections.singletonList(Rejections.authorizationFailed());
return RouteResults.rejected(rejections);
})
).build(), () -> reject(new MyCustomRejection()));
// tests:
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections(Rejections.authorizationFailed());
//#mapRouteResultWithPF
}
@Test
public void testMapRouteResultWith() {
//#mapRouteResultWith
final Route route = mapRouteResultWith(rr -> CompletableFuture.supplyAsync(() -> {
if (rr instanceof Rejected) {
final Iterable<Rejection> rejections =
Collections.singletonList(Rejections.authorizationFailed());
return RouteResults.rejected(rejections);
} else {
return rr;
}
}), () -> reject(new MyCustomRejection()));
// tests:
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections(Rejections.authorizationFailed());
//#mapRouteResultWith
}
@Test
public void testPass() {
//#pass
final Route route = pass(() -> complete("abc"));
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("abc");
//#pass
}
private Route providePrefixedStringRoute(String value) {
return provide("prefix:" + value, this::complete);
}
@Test
public void testProvide() {
//#provide
final Route route = providePrefixedStringRoute("test");
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("prefix:test");
//#provide
}
@Ignore("Test failed")
@Test
public void testCancelRejections() {
//#cancelRejections
final Predicate<Rejection> isMethodRejection = p -> p instanceof MethodRejection;
final Route route = cancelRejections(
isMethodRejection, () -> post(() -> complete("Result"))
);
// tests:
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections();
//#cancelRejections
}
@Ignore("Test failed")
@Test
public void testCancelRejection() {
//#cancelRejection
final Route route = cancelRejection(Rejections.method(HttpMethods.POST), () ->
post(() -> complete("Result"))
);
// tests:
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections();
//#cancelRejection
}
@Test
public void testExtractRequest() {
//#extractRequest
final Route route = extractRequest(request ->
complete("Request method is " + request.method().name() +
" and content-type is " + request.entity().getContentType())
);
// tests:
testRoute(route).run(HttpRequest.POST("/").withEntity("text"))
.assertEntity("Request method is POST and content-type is text/plain; charset=UTF-8");
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("Request method is GET and content-type is none/none");
//#extractRequest
}
@Test
public void testExtractSettings() {
//#extractSettings
final Route route = extractSettings(settings ->
complete("RoutingSettings.renderVanityFooter = " + settings.getRenderVanityFooter())
);
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("RoutingSettings.renderVanityFooter = true");
//#extractSettings
}
@Test
public void testMapSettings() {
//#mapSettings
final Route route = mapSettings(settings ->
settings.withFileGetConditional(false), () ->
extractSettings(settings ->
complete("RoutingSettings.fileGetConditional = " + settings.getFileGetConditional())
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("RoutingSettings.fileGetConditional = false");
//#mapSettings
}
@Test
public void testExtractRequestContext() {
//#extractRequestContext
final Route route = extractRequestContext(ctx -> {
ctx.getLog().debug("Using access to additional context availablethings, like the logger.");
final HttpRequest request = ctx.getRequest();
return complete("Request method is " + request.method().name() +
" and content-type is " + request.entity().getContentType());
});
// tests:
testRoute(route).run(HttpRequest.POST("/").withEntity("text"))
.assertEntity("Request method is POST and content-type is text/plain; charset=UTF-8");
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("Request method is GET and content-type is none/none");
//#extractRequestContext
}
@Test
public void testExtractUri() {
//#extractUri
final Route route = extractUri(uri ->
complete("Full URI: " + uri)
);
// tests:
// tests are executed with the host assumed to be "example.com"
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("Full URI: http://example.com/");
testRoute(route).run(HttpRequest.GET("/test"))
.assertEntity("Full URI: http://example.com/test");
//#extractUri
}
@Test
public void testMapUnmatchedPath() {
//#mapUnmatchedPath
final Function<String, String> ignore456 = path -> {
int slashPos = path.indexOf("/");
if (slashPos != -1) {
String head = path.substring(0, slashPos);
String tail = path.substring(slashPos);
if (head.length() <= 3) {
return tail;
} else {
return path.substring(3);
}
} else {
return path;
}
};
final Route route = pathPrefix("123", () ->
mapUnmatchedPath(ignore456, () ->
path("abc", () ->
complete("Content")
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/123/abc"))
.assertEntity("Content");
testRoute(route).run(HttpRequest.GET("/123456/abc"))
.assertEntity("Content");
//#mapUnmatchedPath
}
@Test
public void testExtractUnmatchedPath() {
//#extractUnmatchedPath
final Route route = pathPrefix("abc", () ->
extractUnmatchedPath(remaining ->
complete("Unmatched: '" + remaining + "'")
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/abc"))
.assertEntity("Unmatched: ''");
testRoute(route).run(HttpRequest.GET("/abc/456"))
.assertEntity("Unmatched: '/456'");
//#extractUnmatchedPath
}
@Test
public void testExtractRequestEntity() {
//#extractRequestEntity
final Route route = extractRequestEntity(entity ->
complete("Request entity content-type is " + entity.getContentType())
);
// tests:
testRoute(route).run(
HttpRequest.POST("/abc")
.withEntity(HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, "req"))
).assertEntity("Request entity content-type is text/plain; charset=UTF-8");
//#extractRequestEntity
}
@Test
public void testExtractDataBytes() {
//#extractDataBytes
final Route route = extractDataBytes(data -> {
final CompletionStage<Integer> sum = data.runFold(0, (acc, i) ->
acc + Integer.valueOf(i.utf8String()), materializer());
return onSuccess(() -> sum, s ->
complete(HttpResponse.create().withEntity(HttpEntities.create(s.toString()))));
});
// tests:
final Iterator iterator = Arrays.asList(
ByteString.fromString("1"),
ByteString.fromString("2"),
ByteString.fromString("3")).iterator();
final Source<ByteString, NotUsed> dataBytes = Source.fromIterator(() -> iterator);
testRoute(route).run(
HttpRequest.POST("abc")
.withEntity(HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, dataBytes))
).assertEntity("6");
//#extractDataBytes
}
@Test
public void testExtractStrictEntity() {
//#extractStrictEntity
final FiniteDuration timeout = FiniteDuration.create(3, TimeUnit.SECONDS);
final Route route = extractStrictEntity(timeout, strict ->
complete(strict.getData().utf8String())
);
// tests:
final Iterator iterator = Arrays.asList(
ByteString.fromString("1"),
ByteString.fromString("2"),
ByteString.fromString("3")).iterator();
final Source<ByteString, NotUsed> dataBytes = Source.fromIterator(() -> iterator);
testRoute(route).run(
HttpRequest.POST("/")
.withEntity(HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, dataBytes))
).assertEntity("123");
//#extractStrictEntity
}
@Test
public void testToStrictEntity() {
//#toStrictEntity
final FiniteDuration timeout = FiniteDuration.create(3, TimeUnit.SECONDS);
final Route route = toStrictEntity(timeout, () ->
extractRequest(req -> {
if (req.entity() instanceof HttpEntity.Strict) {
final HttpEntity.Strict strict = (HttpEntity.Strict)req.entity();
return complete("Request entity is strict, data=" + strict.getData().utf8String());
} else {
return complete("Ooops, request entity is not strict!");
}
})
);
// tests:
final Iterator iterator = Arrays.asList(
ByteString.fromString("1"),
ByteString.fromString("2"),
ByteString.fromString("3")).iterator();
final Source<ByteString, NotUsed> dataBytes = Source.fromIterator(() -> iterator);
testRoute(route).run(
HttpRequest.POST("/")
.withEntity(HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8, dataBytes))
).assertEntity("Request entity is strict, data=123");
//#toStrictEntity
}
@Test
public void testExtractActorSystem() {
//#extractActorSystem
final Route route = extractActorSystem(actorSystem ->
complete("Actor System extracted, hash=" + actorSystem.hashCode())
);
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("Actor System extracted, hash=" + system().hashCode());
//#extractActorSystem
}
}

View file

@ -1,156 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.headers.AcceptEncoding;
import akka.http.javadsl.model.headers.ContentEncoding;
import akka.http.javadsl.model.headers.HttpEncodings;
import akka.http.javadsl.coding.Coder;
import akka.http.javadsl.server.Rejections;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.util.ByteString;
import org.junit.Test;
import java.util.Collections;
import static akka.http.javadsl.unmarshalling.Unmarshaller.entityToString;
public class CodingDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testResponseEncodingAccepted() {
//#responseEncodingAccepted
final Route route = responseEncodingAccepted(HttpEncodings.GZIP, () ->
complete("content")
);
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("content");
runRouteUnSealed(route,
HttpRequest.GET("/")
.addHeader(AcceptEncoding.create(HttpEncodings.DEFLATE)))
.assertRejections(Rejections.unacceptedResponseEncoding(HttpEncodings.GZIP));
//#responseEncodingAccepted
}
@Test
public void testEncodeResponse() {
//#encodeResponse
final Route route = encodeResponse(() -> complete("content"));
// tests:
testRoute(route).run(
HttpRequest.GET("/")
.addHeader(AcceptEncoding.create(HttpEncodings.GZIP))
.addHeader(AcceptEncoding.create(HttpEncodings.DEFLATE))
).assertHeaderExists(ContentEncoding.create(HttpEncodings.GZIP));
testRoute(route).run(
HttpRequest.GET("/")
.addHeader(AcceptEncoding.create(HttpEncodings.DEFLATE))
).assertHeaderExists(ContentEncoding.create(HttpEncodings.DEFLATE));
// This case failed!
// testRoute(route).run(
// HttpRequest.GET("/")
// .addHeader(AcceptEncoding.create(HttpEncodings.IDENTITY))
// ).assertHeaderExists(ContentEncoding.create(HttpEncodings.IDENTITY));
//#encodeResponse
}
@Test
public void testEncodeResponseWith() {
//#encodeResponseWith
final Route route = encodeResponseWith(
Collections.singletonList(Coder.Gzip),
() -> complete("content")
);
// tests:
testRoute(route).run(HttpRequest.GET("/"))
.assertHeaderExists(ContentEncoding.create(HttpEncodings.GZIP));
testRoute(route).run(
HttpRequest.GET("/")
.addHeader(AcceptEncoding.create(HttpEncodings.GZIP))
.addHeader(AcceptEncoding.create(HttpEncodings.DEFLATE))
).assertHeaderExists(ContentEncoding.create(HttpEncodings.GZIP));
runRouteUnSealed(route,
HttpRequest.GET("/")
.addHeader(AcceptEncoding.create(HttpEncodings.DEFLATE))
).assertRejections(Rejections.unacceptedResponseEncoding(HttpEncodings.GZIP));
runRouteUnSealed(route,
HttpRequest.GET("/")
.addHeader(AcceptEncoding.create(HttpEncodings.IDENTITY))
).assertRejections(Rejections.unacceptedResponseEncoding(HttpEncodings.GZIP));
//#encodeResponseWith
}
@Test
public void testDecodeRequest() {
//#decodeRequest
final ByteString helloGzipped = Coder.Gzip.encode(ByteString.fromString("Hello"));
final ByteString helloDeflated = Coder.Deflate.encode(ByteString.fromString("Hello"));
final Route route = decodeRequest(() ->
entity(entityToString(), content ->
complete("Request content: '" + content + "'")
)
);
// tests:
testRoute(route).run(
HttpRequest.POST("/").withEntity(helloGzipped)
.addHeader(ContentEncoding.create(HttpEncodings.GZIP)))
.assertEntity("Request content: 'Hello'");
testRoute(route).run(
HttpRequest.POST("/").withEntity(helloDeflated)
.addHeader(ContentEncoding.create(HttpEncodings.DEFLATE)))
.assertEntity("Request content: 'Hello'");
testRoute(route).run(
HttpRequest.POST("/").withEntity("hello uncompressed")
.addHeader(ContentEncoding.create(HttpEncodings.IDENTITY)))
.assertEntity( "Request content: 'hello uncompressed'");
//#decodeRequest
}
@Test
public void testDecodeRequestWith() {
//#decodeRequestWith
final ByteString helloGzipped = Coder.Gzip.encode(ByteString.fromString("Hello"));
final ByteString helloDeflated = Coder.Deflate.encode(ByteString.fromString("Hello"));
final Route route = decodeRequestWith(Coder.Gzip, () ->
entity(entityToString(), content ->
complete("Request content: '" + content + "'")
)
);
// tests:
testRoute(route).run(
HttpRequest.POST("/").withEntity(helloGzipped)
.addHeader(ContentEncoding.create(HttpEncodings.GZIP)))
.assertEntity("Request content: 'Hello'");
runRouteUnSealed(route,
HttpRequest.POST("/").withEntity(helloDeflated)
.addHeader(ContentEncoding.create(HttpEncodings.DEFLATE)))
.assertRejections(Rejections.unsupportedRequestEncoding(HttpEncodings.GZIP));
runRouteUnSealed(route,
HttpRequest.POST("/").withEntity("hello")
.addHeader(ContentEncoding.create(HttpEncodings.IDENTITY)))
.assertRejections(Rejections.unsupportedRequestEncoding(HttpEncodings.GZIP));
//#decodeRequestWith
}
}

View file

@ -1,102 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpHeader;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.headers.Cookie;
import akka.http.javadsl.model.headers.HttpCookie;
import akka.http.javadsl.model.headers.SetCookie;
import akka.http.javadsl.server.Rejections;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.scaladsl.model.DateTime;
import org.junit.Test;
import java.util.Optional;
import java.util.OptionalLong;
public class CookieDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testCookie() {
//#cookie
final Route route = cookie("userName", nameCookie ->
complete("The logged in user is '" + nameCookie.value() + "'")
);
// tests:
testRoute(route).run(HttpRequest.GET("/").addHeader(Cookie.create("userName", "paul")))
.assertEntity("The logged in user is 'paul'");
// missing cookie
runRouteUnSealed(route, HttpRequest.GET("/"))
.assertRejections(Rejections.missingCookie("userName"));
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("Request is missing required cookie 'userName'");
//#cookie
}
@Test
public void testOptionalCookie() {
//#optionalCookie
final Route route = optionalCookie("userName", optNameCookie -> {
if (optNameCookie.isPresent()) {
return complete("The logged in user is '" + optNameCookie.get().value() + "'");
} else {
return complete("No user logged in");
}
}
);
// tests:
testRoute(route).run(HttpRequest.GET("/").addHeader(Cookie.create("userName", "paul")))
.assertEntity("The logged in user is 'paul'");
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("No user logged in");
//#optionalCookie
}
@Test
public void testDeleteCookie() {
//#deleteCookie
final Route route = deleteCookie("userName", () ->
complete("The user was logged out")
);
// tests:
final HttpHeader expected = SetCookie.create(
HttpCookie.create(
"userName",
"deleted",
Optional.of(DateTime.MinValue()),
OptionalLong.empty(),
Optional.empty(),
Optional.empty(),
false,
false,
Optional.empty()));
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("The user was logged out")
.assertHeaderExists(expected);
//#deleteCookie
}
@Test
public void testSetCookie() {
//#setCookie
final Route route = setCookie(HttpCookie.create("userName", "paul"), () ->
complete("The user was logged in")
);
// tests:
final HttpHeader expected = SetCookie.create(HttpCookie.create("userName", "paul"));
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("The user was logged in")
.assertHeaderExists(expected);
//#setCookie
}
}

View file

@ -1,126 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.RawHeader;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
import java.util.function.Function;
public class CustomDirectivesExamplesTest extends JUnitRouteTest {
//#labeling-1
public Route getOrPut(Supplier<Route> inner) {
return get(inner).orElse(put(inner));
}
//#
@Test
public void testLabeling() {
// tests:
//#labeling-2
Route route = getOrPut(() -> complete("ok"));
//#
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.OK);
testRoute(route).run(HttpRequest.PUT("/"))
.assertStatusCode(StatusCodes.OK);
}
public static class MyCredentials {
private final String userId;
private final String secret;
public MyCredentials(String userId, String secret) {
this.userId = userId;
this.secret = secret;
}
public String getUserId() {
return userId;
}
public boolean safeSecretVerification(String correct) {
// of course this is not what you would do in a real app
return correct.equals(secret);
}
}
public static enum MyRole {
USER,
ADMIN
}
//#composition-1
// the composed custom directive
/**
* @param authenticate A function returns a set of roles for the credentials of a user
* @param inner Inner route to execute if the provided credentials has the given role
* if not, the request is completed with a
*/
public Route headerBasedAuth(Function<MyCredentials, Set<MyRole>> authenticate, MyRole requiredRole, Supplier<Route> inner) {
return headerValueByName("X-My-User-Id", (userId) -> {
return headerValueByName("X-My-User-Secret", (secret) -> {
Set<MyRole> userRoles = authenticate.apply(new MyCredentials(userId, secret));
if (userRoles.contains(requiredRole)) {
return inner.get();
} else {
return complete(StatusCodes.FORBIDDEN, "Role " + requiredRole + " required for access");
}
});
});
}
//#
@Test
public void testComposition() {
// tests:
//#composition-2
// a function for authentication
Function<MyCredentials, Set<MyRole>> authLogic =
(credentials) -> {
if (credentials.userId.equals("admin") && credentials.safeSecretVerification("secret"))
return new HashSet<>(Arrays.asList(MyRole.USER, MyRole.ADMIN));
else
return Collections.emptySet();
};
// and then using the custom route
Route route = get(() ->
path("admin", () ->
headerBasedAuth(authLogic, MyRole.ADMIN, () -> complete(StatusCodes.OK, "admin stuff"))
)
);
//#
testRoute(route).run(HttpRequest.GET("/admin"))
.assertStatusCode(StatusCodes.BAD_REQUEST);
testRoute(route).run(HttpRequest.GET("/admin").addHeaders(
Arrays.asList(RawHeader.create("X-My-User-Id", "user"), RawHeader.create("X-My-User-Secret", "wrong"))))
.assertStatusCode(StatusCodes.FORBIDDEN);
testRoute(route).run(HttpRequest.GET("/admin").addHeaders(
Arrays.asList(RawHeader.create("X-My-User-Id", "admin"), RawHeader.create("X-My-User-Secret", "secret"))))
.assertStatusCode(StatusCodes.OK);
}
}

View file

@ -1,77 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.event.LoggingAdapter;
import akka.event.NoLogging;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.*;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.settings.ParserSettings;
import akka.http.javadsl.settings.ServerSettings;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.stream.Materializer;
import akka.stream.javadsl.Flow;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import static akka.http.javadsl.model.HttpProtocols.HTTP_1_0;
import static akka.http.javadsl.model.RequestEntityAcceptances.Expected;
public class CustomHttpMethodExamplesTest extends JUnitRouteTest {
@Test
public void testComposition() throws InterruptedException, ExecutionException {
ActorSystem system = system();
Materializer materializer = materializer();
LoggingAdapter loggingAdapter = NoLogging.getInstance();
int port = 9090;
String host = "127.0.0.1";
//#customHttpMethod
HttpMethod BOLT =
HttpMethods.createCustom("BOLT", false, true, Expected);
final ParserSettings parserSettings =
ParserSettings.create(system).withCustomMethods(BOLT);
final ServerSettings serverSettings =
ServerSettings.create(system).withParserSettings(parserSettings);
final Route routes = route(
extractMethod( method ->
complete( "This is a " + method.name() + " request.")
)
);
final Flow<HttpRequest, HttpResponse, NotUsed> handler = routes.flow(system, materializer);
final Http http = Http.get(system);
final CompletionStage<ServerBinding> binding =
http.bindAndHandle(
handler,
ConnectHttp.toHost(host, port),
serverSettings,
loggingAdapter,
materializer);
HttpRequest request = HttpRequest.create()
.withUri("http://" + host + ":" + Integer.toString(port))
.withMethod(BOLT)
.withProtocol(HTTP_1_0);
CompletionStage<HttpResponse> response = http.singleRequest(request, materializer);
//#customHttpMethod
assertEquals(StatusCodes.OK, response.toCompletableFuture().get().status());
assertEquals(
"This is a BOLT request.",
response.toCompletableFuture().get().entity().toStrict(3000, materializer).toCompletableFuture().get().getData().utf8String()
);
}
}

View file

@ -1,181 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import java.util.Arrays;
import java.util.regex.Pattern;
import org.junit.Test;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.server.RequestContext;
import akka.http.javadsl.testkit.JUnitRouteTest;
import java.util.function.Function;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import akka.http.javadsl.model.Uri;
import akka.http.javadsl.model.headers.Location;
import akka.http.javadsl.server.directives.DebuggingDirectives;
import akka.http.javadsl.server.directives.RouteDirectives;
import akka.event.Logging;
import akka.event.Logging.LogLevel;
import akka.http.javadsl.server.directives.LogEntry;
import java.util.List;
import akka.http.javadsl.server.Rejection;
import static akka.event.Logging.InfoLevel;
import java.util.stream.Collectors;
import java.util.Optional;
public class DebuggingDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testLogRequest() {
//#logRequest
// logs request with "get-user"
final Route routeBasicLogRequest = get(() ->
logRequest("get-user", () -> complete("logged")));
// logs request with "get-user" as Info
final Route routeBasicLogRequestAsInfo = get(() ->
logRequest("get-user", InfoLevel(), () -> complete("logged")));
// logs just the request method at info level
Function<HttpRequest, LogEntry> requestMethodAsInfo = (request) ->
LogEntry.create(request.method().name(), InfoLevel());
final Route routeUsingFunction = get(() ->
logRequest(requestMethodAsInfo, () -> complete("logged")));
// tests:
testRoute(routeBasicLogRequest).run(HttpRequest.GET("/"))
.assertEntity("logged");
//#logRequest
}
@Test
public void testLogRequestResult() {
//#logRequestResult
// using logRequestResult
// handle request to optionally generate a log entry
BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>> requestMethodAsInfo =
(request, response) ->
(response.status().isSuccess()) ?
Optional.of(
LogEntry.create(
request.method().name() + ":" + response.status().intValue(),
InfoLevel()))
: Optional.empty(); // not a successful response
// handle rejections to optionally generate a log entry
BiFunction<HttpRequest, List<Rejection>, Optional<LogEntry>> rejectionsAsInfo =
(request, rejections) ->
(!rejections.isEmpty()) ?
Optional.of(
LogEntry.create(
rejections
.stream()
.map(Rejection::toString)
.collect(Collectors.joining(", ")),
InfoLevel()))
: Optional.empty(); // no rejections
final Route route = get(() -> logRequestResultOptional(
requestMethodAsInfo,
rejectionsAsInfo,
() -> complete("logged")));
// tests:
testRoute(route).run(HttpRequest.GET("/")).assertEntity("logged");
//#logRequestResult
}
@Test
public void testLogResult() {
//#logResult
// logs result with "get-user"
final Route routeBasicLogResult = get(() ->
logResult("get-user", () -> complete("logged")));
// logs result with "get-user" as Info
final Route routeBasicLogResultAsInfo = get(() ->
logResult("get-user", InfoLevel(), () -> complete("logged")));
// logs the result and the rejections as LogEntry
Function<HttpResponse, LogEntry> showSuccessAsInfo = (response) ->
LogEntry.create(String.format("Response code '%d'", response.status().intValue()),
InfoLevel());
Function<List<Rejection>, LogEntry> showRejectionAsInfo = (rejections) ->
LogEntry.create(
rejections
.stream()
.map(rejection -> rejection.toString())
.collect(Collectors.joining(", ")),
InfoLevel());
final Route routeUsingFunction = get(() ->
logResult(showSuccessAsInfo, showRejectionAsInfo, () -> complete("logged")));
// tests:
testRoute(routeBasicLogResult).run(HttpRequest.GET("/"))
.assertEntity("logged");
//#logResult
}
@Test
public void testLogRequestResultWithResponseTime() {
//#logRequestResultWithResponseTime
// using logRequestResultOptional for generating Response Time
// handle request to optionally generate a log entry
BiFunction<HttpRequest, HttpResponse, Optional<LogEntry>> requestMethodAsInfo =
(request, response) -> {
Long requestTime = System.nanoTime();
return printResponseTime(request, response, requestTime);
};
// handle rejections to optionally generate a log entry
BiFunction<HttpRequest, List<Rejection>, Optional<LogEntry>> rejectionsAsInfo =
(request, rejections) ->
(!rejections.isEmpty()) ?
Optional.of(
LogEntry.create(
rejections
.stream()
.map(Rejection::toString)
.collect(Collectors.joining(", ")),
InfoLevel()))
: Optional.empty(); // no rejections
final Route route = get(() -> logRequestResultOptional(
requestMethodAsInfo,
rejectionsAsInfo,
() -> complete("logged")));
// tests:
testRoute(route).run(HttpRequest.GET("/")).assertEntity("logged");
//#logRequestResult
}
// A function for the logging of Time
public static Optional<LogEntry> printResponseTime(HttpRequest request, HttpResponse response, Long requestTime) {
if (response.status().isSuccess()) {
Long elapsedTime = (requestTime - System.nanoTime()) / 1000000;
return Optional.of(
LogEntry.create(
"Logged Request:" + request.method().name() + ":" + request.getUri() + ":" + response.status() + ":" + elapsedTime,
InfoLevel()));
} else {
return Optional.empty(); //not a successfull response
}
}
}

View file

@ -1,75 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.ExceptionHandler;
import akka.http.javadsl.server.PathMatchers;
import akka.http.javadsl.server.RejectionHandler;
import akka.http.javadsl.server.Rejections;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.server.ValidationRejection;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
import static akka.http.javadsl.server.PathMatchers.integerSegment;
public class ExecutionDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testHandleExceptions() {
//#handleExceptions
final ExceptionHandler divByZeroHandler = ExceptionHandler.newBuilder()
.match(ArithmeticException.class, x ->
complete(StatusCodes.BAD_REQUEST, "You've got your arithmetic wrong, fool!"))
.build();
final Route route =
path(PathMatchers.segment("divide").slash(integerSegment()).slash(integerSegment()), (a, b) ->
handleExceptions(divByZeroHandler, () -> complete("The result is " + (a / b)))
);
// tests:
testRoute(route).run(HttpRequest.GET("/divide/10/5"))
.assertEntity("The result is 2");
testRoute(route).run(HttpRequest.GET("/divide/10/0"))
.assertStatusCode(StatusCodes.BAD_REQUEST)
.assertEntity("You've got your arithmetic wrong, fool!");
//#handleExceptions
}
@Test
public void testHandleRejections() {
//#handleRejections
final RejectionHandler totallyMissingHandler = RejectionHandler.newBuilder()
.handleNotFound(complete(StatusCodes.NOT_FOUND, "Oh man, what you are looking for is long gone."))
.handle(ValidationRejection.class, r -> complete(StatusCodes.INTERNAL_SERVER_ERROR, r.message()))
.build();
final Route route = pathPrefix("handled", () ->
handleRejections(totallyMissingHandler, () ->
route(
path("existing", () -> complete("This path exists")),
path("boom", () -> reject(Rejections.validationRejection("This didn't work.")))
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/handled/existing"))
.assertEntity("This path exists");
// applies default handler
testRoute(route).run(HttpRequest.GET("/missing"))
.assertStatusCode(StatusCodes.NOT_FOUND)
.assertEntity("The requested resource could not be found.");
testRoute(route).run(HttpRequest.GET("/handled/missing"))
.assertStatusCode(StatusCodes.NOT_FOUND)
.assertEntity("Oh man, what you are looking for is long gone.");
testRoute(route).run(HttpRequest.GET("/handled/boom"))
.assertStatusCode(StatusCodes.INTERNAL_SERVER_ERROR)
.assertEntity("This didn't work.");
//#handleRejections
}
}

View file

@ -1,124 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.PathMatchers;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.server.directives.DirectoryRenderer;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Ignore;
import org.junit.Test;
import scala.NotImplementedError;
import static akka.http.javadsl.server.PathMatchers.segment;
public class FileAndResourceDirectivesExamplesTest extends JUnitRouteTest {
@Ignore("Compile only test")
@Test
public void testGetFromFile() {
//#getFromFile
final Route route = path(PathMatchers.segment("logs").slash(segment()), name ->
getFromFile(name + ".log")
);
// tests:
testRoute(route).run(HttpRequest.GET("/logs/example"))
.assertEntity("example file contents");
//#getFromFile
}
@Ignore("Compile only test")
@Test
public void testGetFromResource() {
//#getFromResource
final Route route = path(PathMatchers.segment("logs").slash(segment()), name ->
getFromResource(name + ".log")
);
// tests:
testRoute(route).run(HttpRequest.GET("/logs/example"))
.assertEntity("example file contents");
//#getFromResource
}
@Ignore("Compile only test")
@Test
public void testListDirectoryContents() {
//#listDirectoryContents
final Route route = route(
path("tmp", () -> listDirectoryContents("/tmp")),
path("custom", () -> {
// implement your custom renderer here
final DirectoryRenderer renderer = renderVanityFooter -> {
throw new NotImplementedError();
};
return listDirectoryContents(renderer, "/tmp");
})
);
// tests:
testRoute(route).run(HttpRequest.GET("/logs/example"))
.assertEntity("example file contents");
//#listDirectoryContents
}
@Ignore("Compile only test")
@Test
public void testGetFromBrowseableDirectory() {
//#getFromBrowseableDirectory
final Route route = path("tmp", () ->
getFromBrowseableDirectory("/tmp")
);
// tests:
testRoute(route).run(HttpRequest.GET("/tmp"))
.assertStatusCode(StatusCodes.OK);
//#getFromBrowseableDirectory
}
@Ignore("Compile only test")
@Test
public void testGetFromBrowseableDirectories() {
//#getFromBrowseableDirectories
final Route route = path("tmp", () ->
getFromBrowseableDirectories("/main", "/backups")
);
// tests:
testRoute(route).run(HttpRequest.GET("/tmp"))
.assertStatusCode(StatusCodes.OK);
//#getFromBrowseableDirectories
}
@Ignore("Compile only test")
@Test
public void testGetFromDirectory() {
//#getFromDirectory
final Route route = pathPrefix("tmp", () ->
getFromDirectory("/tmp")
);
// tests:
testRoute(route).run(HttpRequest.GET("/tmp/example"))
.assertEntity("example file contents");
//#getFromDirectory
}
@Ignore("Compile only test")
@Test
public void testGetFromResourceDirectory() {
//#getFromResourceDirectory
final Route route = pathPrefix("examples", () ->
getFromResourceDirectory("/examples")
);
// tests:
testRoute(route).run(HttpRequest.GET("/examples/example-1"))
.assertEntity("example file contents");
//#getFromResourceDirectory
}
}

View file

@ -1,137 +0,0 @@
/**
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.impl.engine.rendering.BodyPartRenderer;
import akka.http.javadsl.model.*;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.unmarshalling.Unmarshaller;
import akka.http.javadsl.server.directives.FileInfo;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.stream.javadsl.Framing;
import akka.stream.javadsl.Source;
import akka.util.ByteString;
import org.junit.Ignore;
import org.junit.Test;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.function.BiFunction;
public class FileUploadDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testUploadedFile() {
//#uploadedFile
// function (FileInfo, File) => Route to process the file metadata and file itself
BiFunction<FileInfo, File, Route> infoFileRoute =
(info, file) -> {
// do something with the file and file metadata ...
file.delete();
return complete(StatusCodes.OK);
};
final Route route = uploadedFile("csv", infoFileRoute);
Map<String, String> filenameMapping = new HashMap<>();
filenameMapping.put("filename", "data.csv");
akka.http.javadsl.model.Multipart.FormData multipartForm =
Multiparts.createStrictFormDataFromParts(Multiparts.createFormDataBodyPartStrict("csv",
HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8,
"1,5,7\n11,13,17"), filenameMapping));
// test:
testRoute(route).run(HttpRequest.POST("/")
.withEntity(
multipartForm.toEntity(HttpCharsets.UTF_8,
BodyPartRenderer
.randomBoundaryWithDefaults())))
.assertStatusCode(StatusCodes.OK);
//#
}
@Test
public void testFileUpload() {
//#fileUpload
final Route route = extractRequestContext(ctx -> {
// function (FileInfo, Source<ByteString,Object>) => Route to process the file contents
BiFunction<FileInfo, Source<ByteString, Object>, Route> processUploadedFile =
(metadata, byteSource) -> {
CompletionStage<Integer> sumF = byteSource.via(Framing.delimiter(
ByteString.fromString("\n"), 1024))
.mapConcat(bs -> Arrays.asList(bs.utf8String().split(",")))
.map(s -> Integer.parseInt(s))
.runFold(0, (acc, n) -> acc + n, ctx.getMaterializer());
return onSuccess(() -> sumF, sum -> complete("Sum: " + sum));
};
return fileUpload("csv", processUploadedFile);
});
Map<String, String> filenameMapping = new HashMap<>();
filenameMapping.put("filename", "primes.csv");
akka.http.javadsl.model.Multipart.FormData multipartForm =
Multiparts.createStrictFormDataFromParts(
Multiparts.createFormDataBodyPartStrict("csv",
HttpEntities.create(ContentTypes.TEXT_PLAIN_UTF8,
"2,3,5\n7,11,13,17,23\n29,31,37\n"), filenameMapping));
// test:
testRoute(route).run(HttpRequest.POST("/").withEntity(
multipartForm.toEntity(HttpCharsets.UTF_8, BodyPartRenderer.randomBoundaryWithDefaults())))
.assertStatusCode(StatusCodes.OK).assertEntityAs(Unmarshaller.entityToString(), "Sum: 178");
//#
}
@Ignore("compileOnly")
@Test
public void testFileProcessing() {
//#fileProcessing
final Route route = extractRequestContext(ctx -> {
// function (FileInfo, Source<ByteString,Object>) => Route to process the file contents
BiFunction<FileInfo, Source<ByteString, Object>, Route> processUploadedFile =
(metadata, byteSource) -> {
CompletionStage<Integer> sumF = byteSource.via(Framing.delimiter(
ByteString.fromString("\n"), 1024))
.mapConcat(bs -> Arrays.asList(bs.utf8String().split(",")))
.map(s -> Integer.parseInt(s))
.runFold(0, (acc, n) -> acc + n, ctx.getMaterializer());
return onSuccess(() -> sumF, sum -> complete("Sum: " + sum));
};
return fileUpload("csv", processUploadedFile);
});
Map<String, String> filenameMapping = new HashMap<>();
filenameMapping.put("filename", "primes.csv");
String prefix = "primes";
String suffix = ".csv";
File tempFile = null;
try {
tempFile = File.createTempFile(prefix, suffix);
tempFile.deleteOnExit();
Files.write(tempFile.toPath(), Arrays.asList("2,3,5", "7,11,13,17,23", "29,31,37"), Charset.forName("UTF-8"));
} catch (Exception e) {
// ignore
}
akka.http.javadsl.model.Multipart.FormData multipartForm =
Multiparts.createFormDataFromPath("csv", ContentTypes.TEXT_PLAIN_UTF8, tempFile.toPath());
// test:
testRoute(route).run(HttpRequest.POST("/").withEntity(
multipartForm.toEntity(HttpCharsets.UTF_8, BodyPartRenderer.randomBoundaryWithDefaults())))
.assertStatusCode(StatusCodes.OK).assertEntityAs(Unmarshaller.entityToString(), "Sum: 178");
//#
}
}

View file

@ -1,137 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.FormData;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.unmarshalling.StringUnmarshallers;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.japi.Pair;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
public class FormFieldDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testFormField() {
//#formField
final Route route = route(
formField("color", color ->
complete("The color is '" + color + "'")
),
formField(StringUnmarshallers.INTEGER, "id", id ->
complete("The id is '" + id + "'")
)
);
// tests:
final FormData formData = FormData.create(Pair.create("color", "blue"));
testRoute(route).run(HttpRequest.POST("/").withEntity(formData.toEntity()))
.assertEntity("The color is 'blue'");
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.BAD_REQUEST)
.assertEntity("Request is missing required form field 'color'");
//#formField
}
@Test
public void testFormFieldMap() {
//#formFieldMap
final Function<Map<String, String>, String> mapToString = map ->
map.entrySet()
.stream()
.map(e -> e.getKey() + " = '" + e.getValue() +"'")
.collect(Collectors.joining(", "));
final Route route = formFieldMap(fields ->
complete("The form fields are " + mapToString.apply(fields))
);
// tests:
final FormData formDataDiffKey =
FormData.create(
Pair.create("color", "blue"),
Pair.create("count", "42"));
testRoute(route).run(HttpRequest.POST("/").withEntity(formDataDiffKey.toEntity()))
.assertEntity("The form fields are color = 'blue', count = '42'");
final FormData formDataSameKey =
FormData.create(
Pair.create("x", "1"),
Pair.create("x", "5"));
testRoute(route).run(HttpRequest.POST("/").withEntity(formDataSameKey.toEntity()))
.assertEntity( "The form fields are x = '5'");
//#formFieldMap
}
@Test
public void testFormFieldMultiMap() {
//#formFieldMultiMap
final Function<Map<String, List<String>>, String> mapToString = map ->
map.entrySet()
.stream()
.map(e -> e.getKey() + " -> " + e.getValue().size())
.collect(Collectors.joining(", "));
final Route route = formFieldMultiMap(fields ->
complete("There are form fields " + mapToString.apply(fields))
);
// test:
final FormData formDataDiffKey =
FormData.create(
Pair.create("color", "blue"),
Pair.create("count", "42"));
testRoute(route).run(HttpRequest.POST("/").withEntity(formDataDiffKey.toEntity()))
.assertEntity("There are form fields color -> 1, count -> 1");
final FormData formDataSameKey =
FormData.create(
Pair.create("x", "23"),
Pair.create("x", "4"),
Pair.create("x", "89"));
testRoute(route).run(HttpRequest.POST("/").withEntity(formDataSameKey.toEntity()))
.assertEntity("There are form fields x -> 3");
//#formFieldMultiMap
}
@Test
public void testFormFieldList() {
//#formFieldList
final Function<List<Entry<String, String>>, String> listToString = list ->
list.stream()
.map(e -> e.getKey() + " = '" + e.getValue() +"'")
.collect(Collectors.joining(", "));
final Route route = formFieldList(fields ->
complete("The form fields are " + listToString.apply(fields))
);
// tests:
final FormData formDataDiffKey =
FormData.create(
Pair.create("color", "blue"),
Pair.create("count", "42"));
testRoute(route).run(HttpRequest.POST("/").withEntity(formDataDiffKey.toEntity()))
.assertEntity("The form fields are color = 'blue', count = '42'");
final FormData formDataSameKey =
FormData.create(
Pair.create("x", "23"),
Pair.create("x", "4"),
Pair.create("x", "89"));
testRoute(route).run(HttpRequest.POST("/").withEntity(formDataSameKey.toEntity()))
.assertEntity("The form fields are x = '23', x = '4', x = '89'");
//#formFieldList
}
}

View file

@ -1,150 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.marshalling.Marshaller;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.scaladsl.model.StatusCodes;
import akka.japi.pf.PFBuilder;
import akka.pattern.CircuitBreaker;
import org.junit.Test;
import scala.concurrent.duration.FiniteDuration;
import static akka.http.javadsl.server.PathMatchers.*;
import static scala.compat.java8.JFunction.func;
public class FutureDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testOnComplete() {
//#onComplete
// import static scala.compat.java8.JFunction.func;
// import static akka.http.javadsl.server.PathMatchers.*;
final Route route = path(segment("divide").slash(integerSegment()).slash(integerSegment()),
(a, b) -> onComplete(
() -> CompletableFuture.supplyAsync(() -> a / b),
maybeResult -> maybeResult
.map(func(result -> complete("The result was " + result)))
.recover(new PFBuilder<Throwable, Route>()
.matchAny(ex -> complete(StatusCodes.InternalServerError(),
"An error occurred: " + ex.getMessage())
)
.build())
.get()
)
);
testRoute(route).run(HttpRequest.GET("/divide/10/2"))
.assertEntity("The result was 5");
testRoute(route).run(HttpRequest.GET("/divide/10/0"))
.assertStatusCode(StatusCodes.InternalServerError())
.assertEntity("An error occurred: / by zero");
//#onComplete
}
@Test
public void testOnSuccess() {
//#onSuccess
final Route route = path("success", () ->
onSuccess(() -> CompletableFuture.supplyAsync(() -> "Ok"),
extraction -> complete(extraction)
)
).orElse(path("failure", () ->
onSuccess(() -> CompletableFuture.supplyAsync(() -> {
throw new RuntimeException();
}),
extraction -> complete("never reaches here"))
));
testRoute(route).run(HttpRequest.GET("/success"))
.assertEntity("Ok");
testRoute(route).run(HttpRequest.GET("/failure"))
.assertStatusCode(StatusCodes.InternalServerError())
.assertEntity("There was an internal server error.");
//#onSuccess
}
@Test
public void testCompleteOrRecoverWith() {
//#completeOrRecoverWith
final Route route = path("success", () ->
completeOrRecoverWith(
() -> CompletableFuture.supplyAsync(() -> "Ok"),
Marshaller.stringToEntity(),
extraction -> failWith(extraction) // not executed
)
).orElse(path("failure", () ->
completeOrRecoverWith(
() -> CompletableFuture.supplyAsync(() -> {
throw new RuntimeException();
}),
Marshaller.stringToEntity(),
extraction -> failWith(extraction))
));
testRoute(route).run(HttpRequest.GET("/success"))
.assertEntity("Ok");
testRoute(route).run(HttpRequest.GET("/failure"))
.assertStatusCode(StatusCodes.InternalServerError())
.assertEntity("There was an internal server error.");
//#completeOrRecoverWith
}
@Test
public void testOnCompleteWithBreaker() throws InterruptedException {
//#onCompleteWithBreaker
// import static scala.compat.java8.JFunction.func;
// import static akka.http.javadsl.server.PathMatchers.*;
final int maxFailures = 1;
final FiniteDuration callTimeout = FiniteDuration.create(5, TimeUnit.SECONDS);
final FiniteDuration resetTimeout = FiniteDuration.create(1, TimeUnit.SECONDS);
final CircuitBreaker breaker = CircuitBreaker.create(system().scheduler(), maxFailures, callTimeout, resetTimeout);
final Route route = path(segment("divide").slash(integerSegment()).slash(integerSegment()),
(a, b) -> onCompleteWithBreaker(breaker,
() -> CompletableFuture.supplyAsync(() -> a / b),
maybeResult -> maybeResult
.map(func(result -> complete("The result was " + result)))
.recover(new PFBuilder<Throwable, Route>()
.matchAny(ex -> complete(StatusCodes.InternalServerError(),
"An error occurred: " + ex.getMessage())
)
.build())
.get()
)
);
testRoute(route).run(HttpRequest.GET("/divide/10/2"))
.assertEntity("The result was 5");
testRoute(route).run(HttpRequest.GET("/divide/10/0"))
.assertStatusCode(StatusCodes.InternalServerError())
.assertEntity("An error occurred: / by zero");
// opened the circuit-breaker
testRoute(route).run(HttpRequest.GET("/divide/10/0"))
.assertStatusCode(StatusCodes.ServiceUnavailable())
.assertEntity("The server is currently unavailable (because it is overloaded or down for maintenance).");
Thread.sleep(resetTimeout.toMillis() + 300);
// circuit breaker resets after this time
testRoute(route).run(HttpRequest.GET("/divide/8/2"))
.assertEntity("The result was 4");
//#onCompleteWithBreaker
}
}

View file

@ -1,261 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import java.util.Optional;
import java.util.function.Function;
import org.junit.Test;
import akka.http.javadsl.model.HttpHeader;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.model.headers.HttpOrigin;
import akka.http.javadsl.model.headers.HttpOriginRange;
import akka.http.javadsl.model.headers.Origin;
import akka.http.javadsl.model.headers.RawHeader;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.japi.JavaPartialFunction;
import akka.http.javadsl.testkit.TestRoute;
import scala.PartialFunction;
public class HeaderDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testHeaderValue() {
//#headerValue
final Function<HttpHeader, Optional<Host>> extractHostPort = header -> {
if (header instanceof Host) {
return Optional.of((Host) header);
} else {
return Optional.empty();
}
};
final Route route = headerValue(extractHostPort, host ->
complete("The port was " + host.port())
);
// tests:
testRoute(route).run(HttpRequest.GET("/").addHeader(Host.create("example.com", 5043)))
.assertEntity("The port was 5043");
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.NOT_FOUND)
.assertEntity("The requested resource could not be found.");
//#headerValue
}
@Test
public void testHeaderValueByName() {
//#headerValueByName
final Route route = headerValueByName("X-User-Id", userId ->
complete("The user is " + userId)
);
// tests:
final RawHeader header = RawHeader.create("X-User-Id", "Joe42");
testRoute(route).run(HttpRequest.GET("/").addHeader(header))
.assertEntity("The user is Joe42");
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.BAD_REQUEST)
.assertEntity("Request is missing required HTTP header 'X-User-Id'");
//#headerValueByName
}
@Test
public void testHeaderValueByType() {
//#headerValueByType
final Route route = headerValueByType(Origin.class, origin ->
complete("The first origin was " + origin.getOrigins().iterator().next())
);
// tests:
final Host host = Host.create("localhost", 8080);
final Origin originHeader = Origin.create(HttpOrigin.create("http", host));
testRoute(route).run(HttpRequest.GET("abc").addHeader(originHeader))
.assertEntity("The first origin was http://localhost:8080");
testRoute(route).run(HttpRequest.GET("abc"))
.assertStatusCode(StatusCodes.BAD_REQUEST)
.assertEntity("Request is missing required HTTP header 'Origin'");
//#headerValueByType
}
@Test
public void testHeaderValuePF() {
//#headerValuePF
final PartialFunction<HttpHeader, Integer> extractHostPort =
new JavaPartialFunction<HttpHeader, Integer>() {
@Override
public Integer apply(HttpHeader x, boolean isCheck) throws Exception {
if (x instanceof Host) {
if (isCheck) {
return null;
} else {
return ((Host) x).port();
}
} else {
throw noMatch();
}
}
};
final Route route = headerValuePF(extractHostPort, port ->
complete("The port was " + port)
);
// tests:
testRoute(route).run(HttpRequest.GET("/").addHeader(Host.create("example.com", 5043)))
.assertEntity("The port was 5043");
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.NOT_FOUND)
.assertEntity("The requested resource could not be found.");
//#headerValuePF
}
@Test
public void testOptionalHeaderValue() {
//#optionalHeaderValue
final Function<HttpHeader, Optional<Integer>> extractHostPort = header -> {
if (header instanceof Host) {
return Optional.of(((Host) header).port());
} else {
return Optional.empty();
}
};
final Route route = optionalHeaderValue(extractHostPort, port -> {
if (port.isPresent()) {
return complete("The port was " + port.get());
} else {
return complete("The port was not provided explicitly");
}
});
// tests:
testRoute(route).run(HttpRequest.GET("/").addHeader(Host.create("example.com", 5043)))
.assertEntity("The port was 5043");
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("The port was not provided explicitly");
//#optionalHeaderValue
}
@Test
public void testOptionalHeaderValueByName() {
//#optionalHeaderValueByName
final Route route = optionalHeaderValueByName("X-User-Id", userId -> {
if (userId.isPresent()) {
return complete("The user is " + userId.get());
} else {
return complete("No user was provided");
}
});
// tests:
final RawHeader header = RawHeader.create("X-User-Id", "Joe42");
testRoute(route).run(HttpRequest.GET("/").addHeader(header))
.assertEntity("The user is Joe42");
testRoute(route).run(HttpRequest.GET("/")).assertEntity("No user was provided");
//#optionalHeaderValueByName
}
@Test
public void testOptionalHeaderValueByType() {
//#optionalHeaderValueByType
final Route route = optionalHeaderValueByType(Origin.class, origin -> {
if (origin.isPresent()) {
return complete("The first origin was " + origin.get().getOrigins().iterator().next());
} else {
return complete("No Origin header found.");
}
});
// tests:
// extract Some(header) if the type is matching
Host host = Host.create("localhost", 8080);
Origin originHeader = Origin.create(HttpOrigin.create("http", host));
testRoute(route).run(HttpRequest.GET("abc").addHeader(originHeader))
.assertEntity("The first origin was http://localhost:8080");
// extract None if no header of the given type is present
testRoute(route).run(HttpRequest.GET("abc")).assertEntity("No Origin header found.");
//#optionalHeaderValueByType
}
@Test
public void testOptionalHeaderValuePF() {
//#optionalHeaderValuePF
final PartialFunction<HttpHeader, Integer> extractHostPort =
new JavaPartialFunction<HttpHeader, Integer>() {
@Override
public Integer apply(HttpHeader x, boolean isCheck) throws Exception {
if (x instanceof Host) {
if (isCheck) {
return null;
} else {
return ((Host) x).port();
}
} else {
throw noMatch();
}
}
};
final Route route = optionalHeaderValuePF(extractHostPort, port -> {
if (port.isPresent()) {
return complete("The port was " + port.get());
} else {
return complete("The port was not provided explicitly");
}
});
// tests:
testRoute(route).run(HttpRequest.GET("/").addHeader(Host.create("example.com", 5043)))
.assertEntity("The port was 5043");
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("The port was not provided explicitly");
//#optionalHeaderValuePF
}
@Test
public void testCheckSameOrigin() {
//#checkSameOrigin
final HttpOrigin validOriginHeader =
HttpOrigin.create("http://localhost", Host.create("8080"));
final HttpOriginRange validOriginRange = HttpOriginRange.create(validOriginHeader);
final TestRoute route = testRoute(
checkSameOrigin(validOriginRange,
() -> complete("Result")));
route
.run(HttpRequest.create().addHeader(Origin.create(validOriginHeader)))
.assertStatusCode(StatusCodes.OK)
.assertEntity("Result");
route
.run(HttpRequest.create())
.assertStatusCode(StatusCodes.BAD_REQUEST);
final HttpOrigin invalidOriginHeader =
HttpOrigin.create("http://invalid.com", Host.create("8080"));
route
.run(HttpRequest.create().addHeader(Origin.create(invalidOriginHeader)))
.assertStatusCode(StatusCodes.FORBIDDEN);
//#checkSameOrigin
}
}

View file

@ -1,92 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import java.util.Arrays;
import java.util.regex.Pattern;
import org.junit.Test;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
public class HostDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testListOfHost() {
//#host1
final Route matchListOfHosts = host(
Arrays.asList("api.company.com", "rest.company.com"),
() -> complete(StatusCodes.OK));
testRoute(matchListOfHosts).run(HttpRequest.GET("/").addHeader(Host.create("api.company.com")))
.assertStatusCode(StatusCodes.OK);
//#host1
}
@Test
public void testHostPredicate() {
//#host2
final Route shortOnly = host(hostname -> hostname.length() < 10,
() -> complete(StatusCodes.OK));
testRoute(shortOnly).run(HttpRequest.GET("/").addHeader(Host.create("short.com")))
.assertStatusCode(StatusCodes.OK);
testRoute(shortOnly).run(HttpRequest.GET("/").addHeader(Host.create("verylonghostname.com")))
.assertStatusCode(StatusCodes.NOT_FOUND);
//#host2
}
@Test
public void testExtractHost() {
//#extractHostname
final Route route = extractHost(hn ->
complete("Hostname: " + hn));
testRoute(route).run(HttpRequest.GET("/").addHeader(Host.create("company.com", 9090)))
.assertEntity("Hostname: company.com");
//#extractHostname
}
@Test
public void testMatchAndExtractHost() {
//#matchAndExtractHost
final Route hostPrefixRoute = host(Pattern.compile("api|rest"), prefix ->
complete("Extracted prefix: " + prefix));
final Route hostPartRoute = host(Pattern.compile("public.(my|your)company.com"), captured ->
complete("You came through " + captured
+ " company"));
final Route route = route(hostPrefixRoute, hostPartRoute);
testRoute(route).run(HttpRequest.GET("/").addHeader(Host.create("api.company.com")))
.assertStatusCode(StatusCodes.OK).assertEntity("Extracted prefix: api");
testRoute(route).run(HttpRequest.GET("/").addHeader(Host.create("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 Route hostRegex = host(Pattern.compile("server-([0-9]).company.(com|net|org)"), s ->
// will not reach here
complete(s)
);
//#failing-matchAndExtractHost
}
}

View file

@ -1,150 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import org.junit.Test;
import akka.http.javadsl.model.HttpMethods;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
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 Route route = route(
get(() ->
complete("This is a GET request.")
),
extractMethod(method ->
complete("This " + method.value() + " request, clearly is not a GET!")
)
);
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
}
@Test
public void testOverrideMethodWithParameter() {
//#overrideMethodWithParameter
final Route route = route(
overrideMethodWithParameter("method", () ->
route(
get(() -> complete("This looks like a GET request.")),
post(() -> complete("This looks like a POST request."))
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/?method=POST")).assertEntity(
"This looks like a POST request.");
testRoute(route).run(HttpRequest.POST("/?method=get"))
.assertEntity("This looks like a GET request.");
testRoute(route).run(HttpRequest.GET("/?method=hallo")).assertEntity(
"The server either does not recognize the request method, or it lacks the ability to fulfill the request.");
//#overrideMethodWithParameter
}
}

View file

@ -1,64 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.unmarshalling.Unmarshaller;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
import java.util.Arrays;
import java.util.function.Function;
public class MiscDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testWithSizeLimit() {
//#withSizeLimitExample
final Route route = withSizeLimit(500, () ->
entity(Unmarshaller.entityToString(), (entity) ->
complete("ok")
)
);
Function<Integer, HttpRequest> withEntityOfSize = (sizeLimit) -> {
char[] charArray = new char[sizeLimit];
Arrays.fill(charArray, '0');
return HttpRequest.POST("/").withEntity(new String(charArray));
};
// tests:
testRoute(route).run(withEntityOfSize.apply(500))
.assertStatusCode(StatusCodes.OK);
testRoute(route).run(withEntityOfSize.apply(501))
.assertStatusCode(StatusCodes.BAD_REQUEST);
//#withSizeLimitExample
}
@Test
public void testWithoutSizeLimit() {
//#withoutSizeLimitExample
final Route route = withoutSizeLimit(() ->
entity(Unmarshaller.entityToString(), (entity) ->
complete("ok")
)
);
Function<Integer, HttpRequest> withEntityOfSize = (sizeLimit) -> {
char[] charArray = new char[sizeLimit];
Arrays.fill(charArray, '0');
return HttpRequest.POST("/").withEntity(new String(charArray));
};
// tests:
// will work even if you have configured akka.http.parsing.max-content-length = 500
testRoute(route).run(withEntityOfSize.apply(501))
.assertStatusCode(StatusCodes.OK);
//#withoutSizeLimitExample
}
}

View file

@ -1,121 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ParameterDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testParameter() {
//#parameter
final Route route = parameter("color", color ->
complete("The color is '" + color + "'")
);
// tests:
testRoute(route).run(HttpRequest.GET("/?color=blue"))
.assertEntity("The color is 'blue'");
testRoute(route).run(HttpRequest.GET("/"))
.assertStatusCode(StatusCodes.NOT_FOUND)
.assertEntity("Request is missing required query parameter 'color'");
//#parameter
}
@Test
public void testParameters() {
//#parameters
final Route route = parameter("color", color ->
parameter("backgroundColor", backgroundColor ->
complete("The color is '" + color
+ "' and the background is '" + backgroundColor + "'")
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/?color=blue&backgroundColor=red"))
.assertEntity("The color is 'blue' and the background is 'red'");
testRoute(route).run(HttpRequest.GET("/?color=blue"))
.assertStatusCode(StatusCodes.NOT_FOUND)
.assertEntity("Request is missing required query parameter 'backgroundColor'");
//#parameters
}
@Test
public void testParameterMap() {
//#parameterMap
final Function<Entry, String> paramString =
entry -> entry.getKey() + " = '" + entry.getValue() + "'";
final Route route = parameterMap(params -> {
final String pString = params.entrySet()
.stream()
.map(paramString::apply)
.collect(Collectors.joining(", "));
return complete("The parameters are " + pString);
});
// tests:
testRoute(route).run(HttpRequest.GET("/?color=blue&count=42"))
.assertEntity("The parameters are color = 'blue', count = '42'");
testRoute(route).run(HttpRequest.GET("/?x=1&x=2"))
.assertEntity("The parameters are x = '2'");
//#parameterMap
}
@Test
public void testParameterMultiMap() {
//#parameterMultiMap
final Route route = parameterMultiMap(params -> {
final String pString = params.entrySet()
.stream()
.map(e -> e.getKey() + " -> " + e.getValue().size())
.collect(Collectors.joining(", "));
return complete("There are parameters " + pString);
});
// tests:
testRoute(route).run(HttpRequest.GET("/?color=blue&count=42"))
.assertEntity("There are parameters color -> 1, count -> 1");
testRoute(route).run(HttpRequest.GET("/?x=23&x=42"))
.assertEntity("There are parameters x -> 2");
//#parameterMultiMap
}
@Test
public void testParameterSeq() {
//#parameterSeq
final Function<Entry, String> paramString =
entry -> entry.getKey() + " = '" + entry.getValue() + "'";
final Route route = parameterList(params -> {
final String pString = params.stream()
.map(paramString::apply)
.collect(Collectors.joining(", "));
return complete("The parameters are " + pString);
});
// tests:
testRoute(route).run(HttpRequest.GET("/?color=blue&count=42"))
.assertEntity("The parameters are color = 'blue', count = '42'");
testRoute(route).run(HttpRequest.GET("/?x=1&x=2"))
.assertEntity("The parameters are x = '1', x = '2'");
//#parameterSeq
}
}

View file

@ -1,322 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import java.util.Arrays;
import java.util.regex.Pattern;
import org.junit.Test;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import static akka.http.javadsl.server.PathMatchers.segment;
import static akka.http.javadsl.server.PathMatchers.segments;
import static akka.http.javadsl.server.PathMatchers.integerSegment;
import static akka.http.javadsl.server.PathMatchers.neutral;
import static akka.http.javadsl.server.PathMatchers.slash;
import java.util.function.Supplier;
import akka.http.javadsl.server.directives.RouteAdapter;
import static java.util.regex.Pattern.compile;
public class PathDirectivesExamplesTest extends JUnitRouteTest {
//# path-prefix-test, path-suffix, raw-path-prefix, raw-path-prefix-test
Supplier<RouteAdapter> completeWithUnmatchedPath = ()->
extractUnmatchedPath((path) -> complete(path.toString()));
//#
@Test
public void testPathExamples() {
//# path-dsl
// matches /foo/
path(segment("foo").slash(), () -> complete(StatusCodes.OK));
// matches e.g. /foo/123 and extracts "123" as a String
path(segment("foo").slash(segment(compile("\\d+"))), (value) ->
complete(StatusCodes.OK));
// matches e.g. /foo/bar123 and extracts "123" as a String
path(segment("foo").slash(segment(compile("bar(\\d+)"))), (value) ->
complete(StatusCodes.OK));
// similar to `path(Segments)`
path(neutral().repeat(0, 10), () -> complete(StatusCodes.OK));
// identical to path("foo" ~ (PathEnd | Slash))
path(segment("foo").orElse(slash()), () -> complete(StatusCodes.OK));
//# path-dsl
}
@Test
public void testBasicExamples() {
path("test", () -> complete(StatusCodes.OK));
// matches "/test", as well
path(segment("test"), () -> complete(StatusCodes.OK));
}
@Test
public void testPathExample() {
//# pathPrefix
final Route route =
route(
path("foo", () -> complete("/foo")),
path(segment("foo").slash("bar"), () -> complete("/foo/bar")),
pathPrefix("ball", () ->
route(
pathEnd(() -> complete("/ball")),
path(integerSegment(), (i) ->
complete((i % 2 == 0) ? "even ball" : "odd ball"))
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/")).assertStatusCode(StatusCodes.NOT_FOUND);
testRoute(route).run(HttpRequest.GET("/foo")).assertEntity("/foo");
testRoute(route).run(HttpRequest.GET("/foo/bar")).assertEntity("/foo/bar");
testRoute(route).run(HttpRequest.GET("/ball/1337")).assertEntity("odd ball");
//# pathPrefix
}
@Test
public void testPathEnd() {
//# path-end
final Route route =
route(
pathPrefix("foo", () ->
route(
pathEnd(() -> complete("/foo")),
path("bar", () -> complete("/foo/bar"))
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo")).assertEntity("/foo");
testRoute(route).run(HttpRequest.GET("/foo/")).assertStatusCode(StatusCodes.NOT_FOUND);
testRoute(route).run(HttpRequest.GET("/foo/bar")).assertEntity("/foo/bar");
//# path-end
}
@Test
public void testPathEndOrSingleSlash() {
//# path-end-or-single-slash
final Route route =
route(
pathPrefix("foo", () ->
route(
pathEndOrSingleSlash(() -> complete("/foo")),
path("bar", () -> complete("/foo/bar"))
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo")).assertEntity("/foo");
testRoute(route).run(HttpRequest.GET("/foo/")).assertEntity("/foo");
testRoute(route).run(HttpRequest.GET("/foo/bar")).assertEntity("/foo/bar");
//# path-end-or-single-slash
}
@Test
public void testPathPrefix() {
//# path-prefix
final Route route =
route(
pathPrefix("ball", () ->
route(
pathEnd(() -> complete("/ball")),
path(integerSegment(), (i) ->
complete((i % 2 == 0) ? "even ball" : "odd ball"))
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/")).assertStatusCode(StatusCodes.NOT_FOUND);
testRoute(route).run(HttpRequest.GET("/ball")).assertEntity("/ball");
testRoute(route).run(HttpRequest.GET("/ball/1337")).assertEntity("odd ball");
//# path-prefix
}
@Test
public void testPathPrefixTest() {
//# path-prefix-test
final Route route =
route(
pathPrefixTest(segment("foo").orElse("bar"), () ->
route(
pathPrefix("foo", () -> completeWithUnmatchedPath.get()),
pathPrefix("bar", () -> completeWithUnmatchedPath.get())
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo/doo")).assertEntity("/doo");
testRoute(route).run(HttpRequest.GET("/bar/yes")).assertEntity("/yes");
//# path-prefix-test
}
@Test
public void testPathSingleSlash() {
//# path-single-slash
final Route route =
route(
pathSingleSlash(() -> complete("root")),
pathPrefix("ball", () ->
route(
pathSingleSlash(() -> complete("/ball/")),
path(integerSegment(), (i) -> complete((i % 2 == 0) ? "even ball" : "odd ball"))
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/")).assertEntity("root");
testRoute(route).run(HttpRequest.GET("/ball")).assertStatusCode(StatusCodes.NOT_FOUND);
testRoute(route).run(HttpRequest.GET("/ball/")).assertEntity("/ball/");
testRoute(route).run(HttpRequest.GET("/ball/1337")).assertEntity("odd ball");
//# path-single-slash
}
@Test
public void testPathSuffix() {
//# path-suffix
final Route route =
route(
pathPrefix("start", () ->
route(
pathSuffix("end", () -> completeWithUnmatchedPath.get()),
pathSuffix(segment("foo").slash("bar").concat("baz"), () ->
completeWithUnmatchedPath.get())
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/start/middle/end")).assertEntity("/middle/");
testRoute(route).run(HttpRequest.GET("/start/something/barbaz/foo")).assertEntity("/something/");
//# path-suffix
}
@Test
public void testPathSuffixTest() {
//# path-suffix-test
final Route route =
route(
pathSuffixTest(slash(), () -> complete("slashed")),
complete("unslashed")
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo/")).assertEntity("slashed");
testRoute(route).run(HttpRequest.GET("/foo")).assertEntity("unslashed");
//# path-suffix-test
}
@Test
public void testRawPathPrefix() {
//# raw-path-prefix
final Route route =
route(
pathPrefix("foo", () ->
route(
rawPathPrefix("bar", () -> completeWithUnmatchedPath.get()),
rawPathPrefix("doo", () -> completeWithUnmatchedPath.get())
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foobar/baz")).assertEntity("/baz");
testRoute(route).run(HttpRequest.GET("/foodoo/baz")).assertEntity("/baz");
//# raw-path-prefix
}
@Test
public void testRawPathPrefixTest() {
//# raw-path-prefix-test
final Route route =
route(
pathPrefix("foo", () ->
rawPathPrefixTest("bar", () -> completeWithUnmatchedPath.get())
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foobar")).assertEntity("bar");
testRoute(route).run(HttpRequest.GET("/foobaz")).assertStatusCode(StatusCodes.NOT_FOUND);
//# raw-path-prefix-test
}
@Test
public void testRedirectToNoTrailingSlashIfMissing() {
//# redirect-notrailing-slash-missing
final Route route =
redirectToTrailingSlashIfMissing(
StatusCodes.MOVED_PERMANENTLY, () ->
route(
path(segment("foo").slash(), () -> complete("OK")),
path(segment("bad-1"), () ->
// MISTAKE!
// Missing `/` in path, causes this path to never match,
// because it is inside a `redirectToTrailingSlashIfMissing`
complete(StatusCodes.NOT_IMPLEMENTED)
),
path(segment("bad-2").slash(), () ->
// MISTAKE!
// / should be explicit as path element separator and not *in* the path element
// So it should be: "bad-1" /
complete(StatusCodes.NOT_IMPLEMENTED)
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo"))
.assertStatusCode(StatusCodes.MOVED_PERMANENTLY)
.assertEntity("This and all future requests should be directed to " +
"<a href=\"http://example.com/foo/\">this URI</a>.");
testRoute(route).run(HttpRequest.GET("/foo/"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("OK");
testRoute(route).run(HttpRequest.GET("/bad-1/"))
.assertStatusCode(StatusCodes.NOT_FOUND);
//# redirect-notrailing-slash-missing
}
@Test
public void testRedirectToNoTrailingSlashIfPresent() {
//# redirect-notrailing-slash-present
final Route route =
redirectToNoTrailingSlashIfPresent(
StatusCodes.MOVED_PERMANENTLY, () ->
route(
path("foo", () -> complete("OK")),
path(segment("bad").slash(), () ->
// MISTAKE!
// Since inside a `redirectToNoTrailingSlashIfPresent` directive
// the matched path here will never contain a trailing slash,
// thus this path will never match.
//
// It should be `path("bad")` instead.
complete(StatusCodes.NOT_IMPLEMENTED)
)
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo/"))
.assertStatusCode(StatusCodes.MOVED_PERMANENTLY)
.assertEntity("This and all future requests should be directed to " +
"<a href=\"http://example.com/foo\">this URI</a>.");
testRoute(route).run(HttpRequest.GET("/foo"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("OK");
testRoute(route).run(HttpRequest.GET("/bad"))
.assertStatusCode(StatusCodes.NOT_FOUND);
//# redirect-notrailing-slash-present
}
}

View file

@ -1,89 +0,0 @@
/**
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.Multipart;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.ByteRange;
import akka.http.javadsl.model.headers.ContentRange;
import akka.http.javadsl.model.headers.Range;
import akka.http.javadsl.model.headers.RangeUnits;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.unmarshalling.Unmarshaller;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.javadsl.testkit.TestRouteResult;
import akka.stream.ActorMaterializer;
import akka.util.ByteString;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
public class RangeDirectivesExamplesTest extends JUnitRouteTest {
@Override
public Config additionalConfig() {
return ConfigFactory.parseString("akka.http.routing.range-coalescing-threshold=2");
}
@Test
public void testWithRangeSupport() {
//#withRangeSupport
final Route route = withRangeSupport(() -> complete("ABCDEFGH"));
// test:
final String bytes348Range = ContentRange.create(RangeUnits.BYTES,
akka.http.javadsl.model.ContentRange.create(3, 4, 8)).value();
final akka.http.javadsl.model.ContentRange bytes028Range =
akka.http.javadsl.model.ContentRange.create(0, 2, 8);
final akka.http.javadsl.model.ContentRange bytes678Range =
akka.http.javadsl.model.ContentRange.create(6, 7, 8);
final ActorMaterializer materializer = systemResource().materializer();
testRoute(route).run(HttpRequest.GET("/")
.addHeader(Range.create(RangeUnits.BYTES, ByteRange.createSlice(3, 4))))
.assertHeaderKindExists("Content-Range")
.assertHeaderExists("Content-Range", bytes348Range)
.assertStatusCode(StatusCodes.PARTIAL_CONTENT)
.assertEntity("DE");
// we set "akka.http.routing.range-coalescing-threshold = 2"
// above to make sure we get two BodyParts
final TestRouteResult response = testRoute(route).run(HttpRequest.GET("/")
.addHeader(Range.create(RangeUnits.BYTES,
ByteRange.createSlice(0, 1), ByteRange.createSlice(1, 2), ByteRange.createSlice(6, 7))));
response.assertHeaderKindNotExists("Content-Range");
final CompletionStage<List<Multipart.ByteRanges.BodyPart>> completionStage =
response.entity(Unmarshaller.entityToMultipartByteRanges()).getParts()
.runFold(new ArrayList<>(), (acc, n) -> {
acc.add(n);
return acc;
}, materializer);
try {
final List<Multipart.ByteRanges.BodyPart> bodyParts =
completionStage.toCompletableFuture().get(3, TimeUnit.SECONDS);
assertEquals(2, bodyParts.toArray().length);
final Multipart.ByteRanges.BodyPart part1 = bodyParts.get(0);
assertEquals(bytes028Range, part1.getContentRange());
assertEquals(ByteString.fromString("ABC"),
part1.toStrict(1000, materializer).toCompletableFuture().get().getEntity().getData());
final Multipart.ByteRanges.BodyPart part2 = bodyParts.get(1);
assertEquals(bytes678Range, part2.getContentRange());
assertEquals(ByteString.fromString("GH"),
part2.toStrict(1000, materializer).toCompletableFuture().get().getEntity().getData());
} catch (Exception e) {
// please handle this in production code
}
//#
}
}

View file

@ -1,135 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import java.util.List;
import akka.http.javadsl.model.HttpHeader;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.headers.HttpOrigin;
import akka.http.javadsl.model.headers.Origin;
import akka.http.javadsl.model.headers.RawHeader;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import com.google.common.collect.Lists;
import org.junit.Test;
public class RespondWithDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testRespondWithHeader() {
//#respondWithHeader
final Route route = path("foo", () ->
respondWithHeader(RawHeader.create("Funky-Muppet", "gonzo"), () ->
complete("beep")));
testRoute(route).run(HttpRequest.GET("/foo"))
.assertHeaderExists("Funky-Muppet", "gonzo")
.assertEntity("beep");
//#respondWithHeader
}
@Test
public void testRespondWithDefaultHeader() {
//#respondWithDefaultHeader
//custom headers
final RawHeader blippy = RawHeader.create("X-Fish-Name", "Blippy");
final RawHeader elTonno = RawHeader.create("X-Fish-Name", "El Tonno");
// format: OFF
// by default always include the Blippy header,
// unless a more specific X-Fish-Name is given by the inner route
final Route route =
respondWithDefaultHeader(blippy, () -> // blippy
respondWithHeader(elTonno, () -> // / el tonno
path("el-tonno", () -> // | /
complete("¡Ay blippy!") // | |- el tonno
).orElse( // | |
path("los-tonnos", () -> // | |
complete("¡Ay ay blippy!") // | |- el tonno
) // | |
) // | |
).orElse( // | x
complete("Blip!") // |- blippy
) // x
);
//format: ON
testRoute(route).run(HttpRequest.GET("/"))
.assertHeaderExists("X-Fish-Name", "Blippy")
.assertEntity("Blip!");
testRoute(route).run(HttpRequest.GET("/el-tonno"))
.assertHeaderExists("X-Fish-Name", "El Tonno")
.assertEntity("¡Ay blippy!");
testRoute(route).run(HttpRequest.GET("/los-tonnos"))
.assertHeaderExists("X-Fish-Name", "El Tonno")
.assertEntity("¡Ay ay blippy!");
//#respondWithDefaultHeader
}
@Test
public void respondWithHeaders() {
//#respondWithHeaders
final HttpHeader gonzo = RawHeader.create("Funky-Muppet", "gonzo");
final HttpHeader akka = Origin.create(HttpOrigin.parse("http://akka.io"));
final Route route = path("foo", () ->
respondWithHeaders(Lists.newArrayList(gonzo, akka), () ->
complete("beep")
)
);
testRoute(route).run(HttpRequest.GET("/foo"))
.assertHeaderExists("Funky-Muppet", "gonzo")
.assertHeaderExists("Origin", "http://akka.io")
.assertEntity("beep");
//#respondWithHeaders
}
@Test
public void testRespondWithDefaultHeaders() {
//#respondWithDefaultHeaders
//custom headers
final RawHeader blippy = RawHeader.create("X-Fish-Name", "Blippy");
final HttpHeader akka = Origin.create(HttpOrigin.parse("http://akka.io"));
final List<HttpHeader> defaultHeaders = Lists.newArrayList(blippy, akka);
final RawHeader elTonno = RawHeader.create("X-Fish-Name", "El Tonno");
// format: OFF
// by default always include the Blippy and Akka headers,
// unless a more specific X-Fish-Name is given by the inner route
final Route route =
respondWithDefaultHeaders(defaultHeaders, () -> // blippy and akka
respondWithHeader(elTonno, () -> // / el tonno
path("el-tonno", () -> // | /
complete("¡Ay blippy!") // | |- el tonno
).orElse( // | |
path("los-tonnos", () -> // | |
complete("¡Ay ay blippy!") // | |- el tonno
) // | |
) // | |
).orElse( // | x
complete("Blip!") // |- blippy and akka
) // x
);
//format: ON
testRoute(route).run(HttpRequest.GET("/"))
.assertHeaderExists("X-Fish-Name", "Blippy")
.assertHeaderExists("Origin", "http://akka.io")
.assertEntity("Blip!");
testRoute(route).run(HttpRequest.GET("/el-tonno"))
.assertHeaderExists("X-Fish-Name", "El Tonno")
.assertEntity("¡Ay blippy!");
testRoute(route).run(HttpRequest.GET("/los-tonnos"))
.assertHeaderExists("X-Fish-Name", "El Tonno")
.assertEntity("¡Ay ay blippy!");
//#respondWithDefaultHeaders
}
}

View file

@ -1,125 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpEntities;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.Uri;
import akka.http.javadsl.model.headers.ContentType;
import akka.http.javadsl.model.ContentTypes;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.Rejections;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import org.junit.Test;
import java.util.Collections;
public class RouteDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testComplete() {
//#complete
final Route route = route(
path("a", () -> complete(HttpResponse.create().withEntity("foo"))),
path("b", () -> complete(StatusCodes.OK)),
path("c", () -> complete(StatusCodes.CREATED, "bar")),
path("d", () -> complete(StatusCodes.get(201), "bar")),
path("e", () ->
complete(StatusCodes.CREATED,
Collections.singletonList(ContentType.create(ContentTypes.TEXT_PLAIN_UTF8)),
HttpEntities.create("bar"))),
path("f", () ->
complete(StatusCodes.get(201),
Collections.singletonList(ContentType.create(ContentTypes.TEXT_PLAIN_UTF8)),
HttpEntities.create("bar"))),
path("g", () -> complete("baz"))
);
// tests:
testRoute(route).run(HttpRequest.GET("/a"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("foo");
testRoute(route).run(HttpRequest.GET("/b"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("OK");
testRoute(route).run(HttpRequest.GET("/c"))
.assertStatusCode(StatusCodes.CREATED)
.assertEntity("bar");
testRoute(route).run(HttpRequest.GET("/d"))
.assertStatusCode(StatusCodes.CREATED)
.assertEntity("bar");
testRoute(route).run(HttpRequest.GET("/e"))
.assertStatusCode(StatusCodes.CREATED)
.assertHeaderExists(ContentType.create(ContentTypes.TEXT_PLAIN_UTF8))
.assertEntity("bar");
testRoute(route).run(HttpRequest.GET("/f"))
.assertStatusCode(StatusCodes.CREATED)
.assertHeaderExists(ContentType.create(ContentTypes.TEXT_PLAIN_UTF8))
.assertEntity("bar");
testRoute(route).run(HttpRequest.GET("/g"))
.assertStatusCode(StatusCodes.OK)
.assertEntity("baz");
//#complete
}
@Test
public void testReject() {
//#reject
final Route route = route(
path("a", this::reject), // don't handle here, continue on
path("a", () -> complete("foo")),
path("b", () -> reject(Rejections.validationRejection("Restricted!")))
);
// tests:
testRoute(route).run(HttpRequest.GET("/a"))
.assertEntity("foo");
runRouteUnSealed(route, HttpRequest.GET("/b"))
.assertRejections(Rejections.validationRejection("Restricted!"));
//#reject
}
@Test
public void testRedirect() {
//#redirect
final Route route = pathPrefix("foo", () ->
route(
pathSingleSlash(() -> complete("yes")),
pathEnd(() -> redirect(Uri.create("/foo/"), StatusCodes.PERMANENT_REDIRECT))
)
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo/"))
.assertEntity("yes");
testRoute(route).run(HttpRequest.GET("/foo"))
.assertStatusCode(StatusCodes.PERMANENT_REDIRECT)
.assertEntity("The request, and all future requests should be repeated using <a href=\"/foo/\">this URI</a>.");
//#redirect
}
@Test
public void testFailWith() {
//#failWith
final Route route = path("foo", () ->
failWith(new RuntimeException("Oops."))
);
// tests:
testRoute(route).run(HttpRequest.GET("/foo"))
.assertStatusCode(StatusCodes.INTERNAL_SERVER_ERROR)
.assertEntity("There was an internal server error.");
//#failWith
}
}

View file

@ -1,58 +0,0 @@
/*
* Copyright (C) 2015-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import java.util.Arrays;
import java.util.regex.Pattern;
import org.junit.Test;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.Host;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.server.RequestContext;
import akka.http.javadsl.testkit.JUnitRouteTest;
import java.util.function.Function;
import akka.http.javadsl.model.Uri;
import akka.http.javadsl.model.headers.Location;
public class SchemeDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testScheme() {
//#extractScheme
final Route route = extractScheme((scheme) ->
complete(String.format("The scheme is '%s'", scheme)));
testRoute(route).run(HttpRequest.GET("https://www.example.com/"))
.assertEntity("The scheme is 'https'");
//#extractScheme
}
@Test
public void testRedirection() {
//#scheme
final Route route = route(
scheme("http", ()->
extract((ctx) -> ctx.getRequest().getUri(), (uri)->
redirect(uri.scheme("https"), StatusCodes.MOVED_PERMANENTLY)
)
),
scheme("https", ()->
complete("Safe and secure!")
)
);
testRoute(route).run(HttpRequest.GET("http://www.example.com/hello"))
.assertStatusCode(StatusCodes.MOVED_PERMANENTLY)
.assertHeaderExists(Location.create("https://www.example.com/hello"))
;
testRoute(route).run(HttpRequest.GET("https://www.example.com/hello"))
.assertEntity("Safe and secure!");
//#scheme
}
}

View file

@ -1,364 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.headers.BasicHttpCredentials;
import akka.http.javadsl.model.headers.HttpChallenge;
import akka.http.javadsl.model.headers.HttpCredentials;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.japi.JavaPartialFunction;
import org.junit.Test;
import scala.PartialFunction;
import scala.util.Either;
import scala.util.Left;
import scala.util.Right;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;
import java.util.Optional;
public class SecurityDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testAuthenticateBasic() {
//#authenticateBasic
final Function<Optional<ProvidedCredentials>, Optional<String>> myUserPassAuthenticator =
credentials ->
credentials.filter(c -> c.verify("p4ssw0rd")).map(ProvidedCredentials::identifier);
final Route route = path("secured", () ->
authenticateBasic("secure site", myUserPassAuthenticator, userName ->
complete("The user is '" + userName + "'")
)
).seal(system(), materializer());
// tests:
testRoute(route).run(HttpRequest.GET("/secured"))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The resource requires authentication, which was not supplied with the request")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
final HttpCredentials validCredentials =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(validCredentials))
.assertEntity("The user is 'John'");
final HttpCredentials invalidCredentials =
BasicHttpCredentials.createBasicHttpCredentials("Peter", "pan");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(invalidCredentials))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The supplied authentication is invalid")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
//#authenticateBasic
}
@Test
public void testAuthenticateBasicPF() {
//#authenticateBasicPF
final PartialFunction<Optional<ProvidedCredentials>, String> myUserPassAuthenticator =
new JavaPartialFunction<Optional<ProvidedCredentials>, String>() {
@Override
public String apply(Optional<ProvidedCredentials> opt, boolean isCheck) throws Exception {
if (opt.filter(c -> (c != null) && c.verify("p4ssw0rd")).isPresent()) {
if (isCheck) return null;
else return opt.get().identifier();
} else if (opt.filter(c -> (c != null) && c.verify("p4ssw0rd-special")).isPresent()) {
if (isCheck) return null;
else return opt.get().identifier() + "-admin";
} else {
throw noMatch();
}
}
};
final Route route = path("secured", () ->
authenticateBasicPF("secure site", myUserPassAuthenticator, userName ->
complete("The user is '" + userName + "'")
)
).seal(system(), materializer());
// tests:
testRoute(route).run(HttpRequest.GET("/secured"))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The resource requires authentication, which was not supplied with the request")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
final HttpCredentials validCredentials =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(validCredentials))
.assertEntity("The user is 'John'");
final HttpCredentials validAdminCredentials =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd-special");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(validAdminCredentials))
.assertEntity("The user is 'John-admin'");
final HttpCredentials invalidCredentials =
BasicHttpCredentials.createBasicHttpCredentials("Peter", "pan");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(invalidCredentials))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The supplied authentication is invalid")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
//#authenticateBasicPF
}
@Test
public void testAuthenticateBasicPFAsync() {
//#authenticateBasicPFAsync
class User {
private final String id;
public User(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
final PartialFunction<Optional<ProvidedCredentials>, CompletionStage<User>> myUserPassAuthenticator =
new JavaPartialFunction<Optional<ProvidedCredentials>,CompletionStage<User>>() {
@Override
public CompletionStage<User> apply(Optional<ProvidedCredentials> opt, boolean isCheck) throws Exception {
if (opt.filter(c -> (c != null) && c.verify("p4ssw0rd")).isPresent()) {
if (isCheck) return CompletableFuture.completedFuture(null);
else return CompletableFuture.completedFuture(new User(opt.get().identifier()));
} else {
throw noMatch();
}
}
};
final Route route = path("secured", () ->
authenticateBasicPFAsync("secure site", myUserPassAuthenticator, user ->
complete("The user is '" + user.getId() + "'"))
).seal(system(), materializer());
// tests:
testRoute(route).run(HttpRequest.GET("/secured"))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The resource requires authentication, which was not supplied with the request")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
final HttpCredentials validCredentials =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(validCredentials))
.assertEntity("The user is 'John'");
final HttpCredentials invalidCredentials =
BasicHttpCredentials.createBasicHttpCredentials("Peter", "pan");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(invalidCredentials))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The supplied authentication is invalid")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
//#authenticateBasicPFAsync
}
@Test
public void testAuthenticateBasicAsync() {
//#authenticateBasicAsync
final Function<Optional<ProvidedCredentials>, CompletionStage<Optional<String>>> myUserPassAuthenticator = opt -> {
if (opt.filter(c -> (c != null) && c.verify("p4ssw0rd")).isPresent()) {
return CompletableFuture.completedFuture(Optional.of(opt.get().identifier()));
} else {
return CompletableFuture.completedFuture(Optional.empty());
}
};
final Route route = path("secured", () ->
authenticateBasicAsync("secure site", myUserPassAuthenticator, userName ->
complete("The user is '" + userName + "'")
)
).seal(system(), materializer());
// tests:
testRoute(route).run(HttpRequest.GET("/secured"))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The resource requires authentication, which was not supplied with the request")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
final HttpCredentials validCredentials =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(validCredentials))
.assertEntity("The user is 'John'");
final HttpCredentials invalidCredentials =
BasicHttpCredentials.createBasicHttpCredentials("Peter", "pan");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(invalidCredentials))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The supplied authentication is invalid")
.assertHeaderExists("WWW-Authenticate", "Basic realm=\"secure site\"");
//#authenticateBasicAsync
}
@Test
public void testAuthenticateOrRejectWithChallenge() {
//#authenticateOrRejectWithChallenge
final HttpChallenge challenge = HttpChallenge.create("MyAuth", "MyRealm");
// your custom authentication logic:
final Function<HttpCredentials, Boolean> auth = credentials -> true;
final Function<Optional<HttpCredentials>, CompletionStage<Either<HttpChallenge, String>>> myUserPassAuthenticator =
opt -> {
if (opt.isPresent() && auth.apply(opt.get())) {
return CompletableFuture.completedFuture(Right.apply("some-user-name-from-creds"));
} else {
return CompletableFuture.completedFuture(Left.apply(challenge));
}
};
final Route route = path("secured", () ->
authenticateOrRejectWithChallenge(myUserPassAuthenticator, userName ->
complete("Authenticated!")
)
).seal(system(), materializer());
// tests:
testRoute(route).run(HttpRequest.GET("/secured"))
.assertStatusCode(StatusCodes.UNAUTHORIZED)
.assertEntity("The resource requires authentication, which was not supplied with the request")
.assertHeaderExists("WWW-Authenticate", "MyAuth realm=\"MyRealm\"");
final HttpCredentials validCredentials =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/secured").addCredentials(validCredentials))
.assertStatusCode(StatusCodes.OK)
.assertEntity("Authenticated!");
//#authenticateOrRejectWithChallenge
}
@Test
public void testAuthorize() {
//#authorize
class User {
private final String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// authenticate the user:
final Function<Optional<ProvidedCredentials>, Optional<User>> myUserPassAuthenticator =
opt -> {
if (opt.isPresent()) {
return Optional.of(new User(opt.get().identifier()));
} else {
return Optional.empty();
}
};
// check if user is authorized to perform admin actions:
final Set<String> admins = new HashSet<>();
admins.add("Peter");
final Function<User, Boolean> hasAdminPermissions = user -> admins.contains(user.getName());
final Route route = authenticateBasic("secure site", myUserPassAuthenticator, user ->
path("peters-lair", () ->
authorize(() -> hasAdminPermissions.apply(user), () ->
complete("'" + user.getName() +"' visited Peter's lair")
)
)
).seal(system(), materializer());
// tests:
final HttpCredentials johnsCred =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/peters-lair").addCredentials(johnsCred))
.assertStatusCode(StatusCodes.FORBIDDEN)
.assertEntity("The supplied authentication is not authorized to access this resource");
final HttpCredentials petersCred =
BasicHttpCredentials.createBasicHttpCredentials("Peter", "pan");
testRoute(route).run(HttpRequest.GET("/peters-lair").addCredentials(petersCred))
.assertEntity("'Peter' visited Peter's lair");
//#authorize
}
@Test
public void testAuthorizeAsync() {
//#authorizeAsync
class User {
private final String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// authenticate the user:
final Function<Optional<ProvidedCredentials>, Optional<User>> myUserPassAuthenticator =
opt -> {
if (opt.isPresent()) {
return Optional.of(new User(opt.get().identifier()));
} else {
return Optional.empty();
}
};
// check if user is authorized to perform admin actions,
// this could potentially be a long operation so it would return a Future
final Set<String> admins = new HashSet<>();
admins.add("Peter");
final Set<String> synchronizedAdmins = Collections.synchronizedSet(admins);
final Function<User, CompletionStage<Object>> hasAdminPermissions =
user -> CompletableFuture.completedFuture(synchronizedAdmins.contains(user.getName()));
final Route route = authenticateBasic("secure site", myUserPassAuthenticator, user ->
path("peters-lair", () ->
authorizeAsync(() -> hasAdminPermissions.apply(user), () ->
complete("'" + user.getName() +"' visited Peter's lair")
)
)
).seal(system(), materializer());
// tests:
final HttpCredentials johnsCred =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/peters-lair").addCredentials(johnsCred))
.assertStatusCode(StatusCodes.FORBIDDEN)
.assertEntity("The supplied authentication is not authorized to access this resource");
final HttpCredentials petersCred =
BasicHttpCredentials.createBasicHttpCredentials("Peter", "pan");
testRoute(route).run(HttpRequest.GET("/peters-lair").addCredentials(petersCred))
.assertEntity("'Peter' visited Peter's lair");
//#authorizeAsync
}
@Test
public void testExtractCredentials() {
//#extractCredentials
final Route route = extractCredentials(optCreds -> {
if (optCreds.isPresent()) {
return complete("Credentials: " + optCreds.get());
} else {
return complete("No credentials");
}
});
// tests:
final HttpCredentials johnsCred =
BasicHttpCredentials.createBasicHttpCredentials("John", "p4ssw0rd");
testRoute(route).run(HttpRequest.GET("/").addCredentials(johnsCred))
.assertEntity("Credentials: Basic Sm9objpwNHNzdzByZA==");
testRoute(route).run(HttpRequest.GET("/"))
.assertEntity("No credentials");
//#extractCredentials
}
}

View file

@ -1,180 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.ServerBinding;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.HttpResponse;
import akka.http.javadsl.model.StatusCode;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;
import akka.http.scaladsl.TestUtils;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import akka.testkit.TestKit;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
import scala.Tuple2;
import scala.Tuple3;
import scala.concurrent.duration.Duration;
import scala.runtime.BoxedUnit;
import java.net.InetSocketAddress;
import java.util.Optional;
import java.util.concurrent.*;
public class TimeoutDirectivesExamplesTest extends AllDirectives {
//#testSetup
private final Config testConf = ConfigFactory.parseString("akka.loggers = [\"akka.testkit.TestEventListener\"]\n"
+ "akka.loglevel = ERROR\n"
+ "akka.stdout-loglevel = ERROR\n"
+ "windows-connection-abort-workaround-enabled = auto\n"
+ "akka.log-dead-letters = OFF\n"
+ "akka.http.server.request-timeout = 1000s");
// large timeout - 1000s (please note - setting to infinite will disable Timeout-Access header
// and withRequestTimeout will not work)
private final ActorSystem system = ActorSystem.create("TimeoutDirectivesExamplesTest", testConf);
private final ActorMaterializer materializer = ActorMaterializer.create(system);
private final Http http = Http.get(system);
private CompletionStage<Void> shutdown(CompletionStage<ServerBinding> binding) {
return binding.thenAccept(b -> {
System.out.println(String.format("Unbinding from %s", b.localAddress()));
final CompletionStage<BoxedUnit> unbound = b.unbind();
try {
unbound.toCompletableFuture().get(3, TimeUnit.SECONDS); // block...
} catch (TimeoutException | InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
});
}
private Optional<HttpResponse> runRoute(ActorSystem system, ActorMaterializer materializer, Route route, String routePath) {
final Tuple3<InetSocketAddress, String, Object> inetaddrHostAndPort = TestUtils.temporaryServerHostnameAndPort("127.0.0.1");
Tuple2<String, Integer> hostAndPort = new Tuple2<>(
inetaddrHostAndPort._2(),
(Integer) inetaddrHostAndPort._3()
);
final Flow<HttpRequest, HttpResponse, NotUsed> routeFlow = route.flow(system, materializer);
final CompletionStage<ServerBinding> binding = http.bindAndHandle(routeFlow, ConnectHttp.toHost(hostAndPort._1(), hostAndPort._2()), materializer);
final CompletionStage<HttpResponse> responseCompletionStage = http.singleRequest(HttpRequest.create("http://" + hostAndPort._1() + ":" + hostAndPort._2() + "/" + routePath), materializer);
CompletableFuture<HttpResponse> responseFuture = responseCompletionStage.toCompletableFuture();
Optional<HttpResponse> responseOptional;
try {
responseOptional = Optional.of(responseFuture.get(3, TimeUnit.SECONDS)); // patienceConfig
} catch (Exception e) {
responseOptional = Optional.empty();
}
shutdown(binding);
return responseOptional;
}
//#
@After
public void shutDown() {
TestKit.shutdownActorSystem(system, Duration.create(1, TimeUnit.SECONDS), false);
}
@Test
public void testRequestTimeoutIsConfigurable() {
//#withRequestTimeout-plain
final Duration timeout = Duration.create(1, TimeUnit.SECONDS);
CompletionStage<String> slowFuture = new CompletableFuture<>();
final Route route = path("timeout", () ->
withRequestTimeout(timeout, () -> {
return completeOKWithFutureString(slowFuture); // very slow
})
);
// test:
StatusCode statusCode = runRoute(system, materializer, route, "timeout").get().status();
assert (StatusCodes.SERVICE_UNAVAILABLE.equals(statusCode));
//#
}
@Test
public void testRequestWithoutTimeoutCancelsTimeout() {
//#withoutRequestTimeout-1
CompletionStage<String> slowFuture = new CompletableFuture<>();
final Route route = path("timeout", () ->
withoutRequestTimeout(() -> {
return completeOKWithFutureString(slowFuture); // very slow
})
);
// test:
Boolean receivedReply = runRoute(system, materializer, route, "timeout").isPresent();
assert (!receivedReply); // timed-out
//#
}
@Test
public void testRequestTimeoutAllowsCustomResponse() {
//#withRequestTimeout-with-handler
final Duration timeout = Duration.create(1, TimeUnit.MILLISECONDS);
CompletionStage<String> slowFuture = new CompletableFuture<>();
HttpResponse enhanceYourCalmResponse = HttpResponse.create()
.withStatus(StatusCodes.ENHANCE_YOUR_CALM)
.withEntity("Unable to serve response within time limit, please enhance your calm.");
final Route route = path("timeout", () ->
withRequestTimeout(timeout, (request) -> enhanceYourCalmResponse, () -> {
return completeOKWithFutureString(slowFuture); // very slow
})
);
// test:
StatusCode statusCode = runRoute(system, materializer, route, "timeout").get().status();
assert (StatusCodes.ENHANCE_YOUR_CALM.equals(statusCode));
//#
}
// make it compile only to avoid flaking in slow builds
@Ignore("Compile only test")
@Test
public void testRequestTimeoutCustomResponseCanBeAddedSeparately() {
//#withRequestTimeoutResponse
final Duration timeout = Duration.create(100, TimeUnit.MILLISECONDS);
CompletionStage<String> slowFuture = new CompletableFuture<>();
HttpResponse enhanceYourCalmResponse = HttpResponse.create()
.withStatus(StatusCodes.ENHANCE_YOUR_CALM)
.withEntity("Unable to serve response within time limit, please enhance your calm.");
final Route route = path("timeout", () ->
withRequestTimeout(timeout, () ->
// racy! for a very short timeout like 1.milli you can still get 503
withRequestTimeoutResponse((request) -> enhanceYourCalmResponse, () -> {
return completeOKWithFutureString(slowFuture); // very slow
}))
);
// test:
StatusCode statusCode = runRoute(system, materializer, route, "timeout").get().status();
assert (StatusCodes.ENHANCE_YOUR_CALM.equals(statusCode));
//#
}
}

View file

@ -1,121 +0,0 @@
/*
* Copyright (C) 2016-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.directives;
import akka.NotUsed;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.model.Uri;
import akka.http.javadsl.model.headers.SecWebSocketProtocol;
import akka.http.javadsl.model.ws.BinaryMessage;
import akka.http.javadsl.model.ws.Message;
import akka.http.javadsl.model.ws.TextMessage;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.javadsl.testkit.WSProbe;
import akka.stream.OverflowStrategy;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import akka.util.ByteString;
import org.junit.Test;
import scala.concurrent.duration.FiniteDuration;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
public class WebSocketDirectivesExamplesTest extends JUnitRouteTest {
@Test
public void testHandleWebSocketMessages() {
//#handleWebSocketMessages
final Flow<Message, Message, NotUsed> greeter = Flow.of(Message.class).mapConcat(msg -> {
if (msg instanceof TextMessage) {
final TextMessage tm = (TextMessage) msg;
final TextMessage ret = TextMessage.create(Source.single("Hello ").concat(tm.getStreamedText()).concat(Source.single("!")));
return Collections.singletonList(ret);
} else if (msg instanceof BinaryMessage) {
final BinaryMessage bm = (BinaryMessage) msg;
bm.getStreamedData().runWith(Sink.ignore(), materializer());
return Collections.emptyList();
} else {
throw new IllegalArgumentException("Unsupported message type!");
}
});
final Route websocketRoute = path("greeter", () ->
handleWebSocketMessages(greeter)
);
// create a testing probe representing the client-side
final WSProbe wsClient = WSProbe.create(system(), materializer());
// WS creates a WebSocket request for testing
testRoute(websocketRoute).run(WS(Uri.create("/greeter"), wsClient.flow(), materializer()))
.assertStatusCode(StatusCodes.SWITCHING_PROTOCOLS);
// manually run a WS conversation
wsClient.sendMessage("Peter");
wsClient.expectMessage("Hello Peter!");
wsClient.sendMessage(BinaryMessage.create(ByteString.fromString("abcdef")));
wsClient.expectNoMessage(FiniteDuration.create(100, TimeUnit.MILLISECONDS));
wsClient.sendMessage("John");
wsClient.expectMessage("Hello John!");
wsClient.sendCompletion();
wsClient.expectCompletion();
//#handleWebSocketMessages
}
@Test
public void testHandleWebSocketMessagesForProtocol() {
//#handleWebSocketMessagesForProtocol
final Flow<Message, Message, NotUsed> greeterService = Flow.of(Message.class).mapConcat(msg -> {
if (msg instanceof TextMessage) {
final TextMessage tm = (TextMessage) msg;
final TextMessage ret = TextMessage.create(Source.single("Hello ").concat(tm.getStreamedText()).concat(Source.single("!")));
return Collections.singletonList(ret);
} else if (msg instanceof BinaryMessage) {
final BinaryMessage bm = (BinaryMessage) msg;
bm.getStreamedData().runWith(Sink.ignore(), materializer());
return Collections.emptyList();
} else {
throw new IllegalArgumentException("Unsupported message type!");
}
});
final Flow<Message, Message, NotUsed> echoService = Flow.of(Message.class).buffer(1, OverflowStrategy.backpressure());
final Route websocketMultipleProtocolRoute = path("services", () ->
route(
handleWebSocketMessagesForProtocol(greeterService, "greeter"),
handleWebSocketMessagesForProtocol(echoService, "echo")
)
);
// create a testing probe representing the client-side
final WSProbe wsClient = WSProbe.create(system(), materializer());
// WS creates a WebSocket request for testing
testRoute(websocketMultipleProtocolRoute)
.run(WS(Uri.create("/services"), wsClient.flow(), materializer(), Arrays.asList("other", "echo")))
.assertHeaderExists(SecWebSocketProtocol.create("echo"));
wsClient.sendMessage("Peter");
wsClient.expectMessage("Peter");
wsClient.sendMessage(BinaryMessage.create(ByteString.fromString("abcdef")));
wsClient.expectMessage(ByteString.fromString("abcdef"));
wsClient.sendMessage("John");
wsClient.expectMessage("John");
wsClient.sendCompletion();
wsClient.expectCompletion();
//#handleWebSocketMessagesForProtocol
}
}

View file

@ -1,55 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.testkit;
//#simple-app
import akka.actor.ActorSystem;
import akka.http.javadsl.ConnectHttp;
import akka.http.javadsl.Http;
import akka.http.javadsl.server.AllDirectives;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.unmarshalling.StringUnmarshallers;
import akka.http.javadsl.server.examples.simple.SimpleServerApp;
import akka.stream.ActorMaterializer;
import java.io.IOException;
public class MyAppService extends AllDirectives {
public String add(double x, double y) {
return "x + y = " + (x + y);
}
public Route createRoute() {
return
get(() ->
pathPrefix("calculator", () ->
path("add", () ->
parameter(StringUnmarshallers.DOUBLE, "x", x ->
parameter(StringUnmarshallers.DOUBLE, "y", y ->
complete(add(x, y))
)
)
)
)
);
}
public static void main(String[] args) throws IOException {
final ActorSystem system = ActorSystem.create();
final ActorMaterializer materializer = ActorMaterializer.create(system);
final SimpleServerApp app = new SimpleServerApp();
final ConnectHttp host = ConnectHttp.toHost("127.0.0.1");
Http.get(system).bindAndHandle(app.createRoute().flow(system, materializer), host, materializer);
System.console().readLine("Type RETURN to exit...");
system.terminate();
}
}
//#simple-app

View file

@ -1,36 +0,0 @@
/*
* Copyright (C) 2009-2016 Lightbend Inc. <http://www.lightbend.com>
*/
package docs.http.javadsl.server.testkit;
//#simple-app-testing
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.javadsl.testkit.TestRoute;
import org.junit.Test;
public class TestkitExampleTest extends JUnitRouteTest {
TestRoute appRoute = testRoute(new MyAppService().createRoute());
@Test
public void testCalculatorAdd() {
// test happy path
appRoute.run(HttpRequest.GET("/calculator/add?x=4.2&y=2.3"))
.assertStatusCode(200)
.assertEntity("x + y = 6.5");
// test responses to potential errors
appRoute.run(HttpRequest.GET("/calculator/add?x=3.2"))
.assertStatusCode(StatusCodes.NOT_FOUND) // 404
.assertEntity("Request is missing required query parameter 'y'");
// test responses to potential errors
appRoute.run(HttpRequest.GET("/calculator/add?x=3.2&y=three"))
.assertStatusCode(StatusCodes.BAD_REQUEST)
.assertEntity("The query parameter 'y' was malformed:\n" +
"'three' is not a valid 64-bit floating point value");
}
}
//#simple-app-testing