=doc port over some http documentation from the scala side
This commit is contained in:
parent
16d4b4a331
commit
11d98a6593
18 changed files with 701 additions and 9 deletions
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package docs.http.javadsl;
|
||||||
|
|
||||||
|
import akka.actor.ActorSystem;
|
||||||
|
import akka.http.javadsl.Http;
|
||||||
|
import akka.http.javadsl.IncomingConnection;
|
||||||
|
import akka.http.javadsl.ServerBinding;
|
||||||
|
import akka.http.javadsl.model.*;
|
||||||
|
import akka.http.javadsl.model.ws.Websocket;
|
||||||
|
import akka.japi.function.Function;
|
||||||
|
import akka.japi.function.Procedure;
|
||||||
|
import akka.stream.ActorMaterializer;
|
||||||
|
import akka.stream.Materializer;
|
||||||
|
import akka.stream.javadsl.Flow;
|
||||||
|
import akka.stream.javadsl.Sink;
|
||||||
|
import akka.stream.javadsl.Source;
|
||||||
|
import org.junit.Test;
|
||||||
|
import scala.Function1;
|
||||||
|
import scala.concurrent.Await;
|
||||||
|
import scala.concurrent.Future;
|
||||||
|
import scala.concurrent.duration.FiniteDuration;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class HttpServerExampleSpec {
|
||||||
|
public void bindingExample() {
|
||||||
|
//#binding-example
|
||||||
|
ActorSystem system = ActorSystem.create();
|
||||||
|
Materializer materializer = ActorMaterializer.create(system);
|
||||||
|
|
||||||
|
Source<IncomingConnection, Future<ServerBinding>> serverSource =
|
||||||
|
Http.get(system).bind("localhost", 8080, materializer);
|
||||||
|
|
||||||
|
Future<ServerBinding> serverBindingFuture =
|
||||||
|
serverSource.to(Sink.foreach(
|
||||||
|
new Procedure<IncomingConnection>() {
|
||||||
|
@Override
|
||||||
|
public void apply(IncomingConnection connection) throws Exception {
|
||||||
|
System.out.println("Accepted new connection from " + connection.remoteAddress());
|
||||||
|
// ... and then actually handle the connection
|
||||||
|
}
|
||||||
|
})).run(materializer);
|
||||||
|
//#binding-example
|
||||||
|
}
|
||||||
|
public void fullServerExample() {
|
||||||
|
//#full-server-example
|
||||||
|
ActorSystem system = ActorSystem.create();
|
||||||
|
final Materializer materializer = ActorMaterializer.create(system);
|
||||||
|
|
||||||
|
Source<IncomingConnection, Future<ServerBinding>> serverSource =
|
||||||
|
Http.get(system).bind("localhost", 8080, materializer);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if (request.method() == HttpMethods.GET) {
|
||||||
|
if (request.getUri().path().equals("/"))
|
||||||
|
return
|
||||||
|
HttpResponse.create()
|
||||||
|
.withEntity(MediaTypes.TEXT_HTML.toContentType(),
|
||||||
|
"<html><body>Hello world!</body></html>");
|
||||||
|
else if (request.getUri().path().equals("/ping"))
|
||||||
|
return HttpResponse.create().withEntity("PONG!");
|
||||||
|
else
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
else return NOT_FOUND;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Future<ServerBinding> serverBindingFuture =
|
||||||
|
serverSource.to(Sink.foreach(
|
||||||
|
new Procedure<IncomingConnection>() {
|
||||||
|
@Override
|
||||||
|
public void apply(IncomingConnection connection) throws Exception {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
89
akka-docs-dev/rst/java/code/docs/http/javadsl/ModelSpec.java
Normal file
89
akka-docs-dev/rst/java/code/docs/http/javadsl/ModelSpec.java
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package docs.http.javadsl;
|
||||||
|
|
||||||
|
import akka.japi.Option;
|
||||||
|
import akka.util.ByteString;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
//#import-model
|
||||||
|
import akka.http.javadsl.model.*;
|
||||||
|
import akka.http.javadsl.model.headers.*;
|
||||||
|
//#import-model
|
||||||
|
|
||||||
|
public class ModelSpec {
|
||||||
|
@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(MediaTypes.TEXT_PLAIN.toContentType(), "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 Option<BasicHttpCredentials> getCredentialsOfRequest(HttpRequest request) {
|
||||||
|
Option<Authorization> auth = request.getHeader(Authorization.class);
|
||||||
|
if (auth.isDefined() && auth.get().credentials() instanceof BasicHttpCredentials)
|
||||||
|
return Option.some((BasicHttpCredentials) auth.get().credentials());
|
||||||
|
else
|
||||||
|
return Option.none();
|
||||||
|
}
|
||||||
|
//#headers
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
.. _ConnectionLevelApi-java:
|
||||||
|
|
||||||
|
Connection-Level Client-Side API
|
||||||
|
================================
|
||||||
4
akka-docs-dev/rst/java/http/client-side/host-level.rst
Normal file
4
akka-docs-dev/rst/java/http/client-side/host-level.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.. _HostLevelApi-java:
|
||||||
|
|
||||||
|
Host-Level Client-Side API
|
||||||
|
==========================
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
.. _clientSideHTTPS-java:
|
||||||
|
|
||||||
|
Client-Side HTTPS Support
|
||||||
|
=========================
|
||||||
15
akka-docs-dev/rst/java/http/client-side/index.rst
Normal file
15
akka-docs-dev/rst/java/http/client-side/index.rst
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
.. _http-client-side-java:
|
||||||
|
|
||||||
|
Consuming HTTP-based Services (Client-Side)
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
connection-level
|
||||||
|
host-level
|
||||||
|
request-level
|
||||||
|
https-support
|
||||||
|
websocket-support
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
.. _RequestLevelApi-java:
|
||||||
|
|
||||||
|
Request-Level Client-Side API
|
||||||
|
=============================
|
||||||
|
|
||||||
|
...
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
Client-Side WebSocket Support
|
||||||
|
=============================
|
||||||
|
|
||||||
|
TODO
|
||||||
28
akka-docs-dev/rst/java/http/configuration.rst
Normal file
28
akka-docs-dev/rst/java/http/configuration.rst
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
.. _akka-http-configuration-java:
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
Just like any other Akka module Akka HTTP is configured via `Typesafe Config`_.
|
||||||
|
Usually this means that you provide an ``application.conf`` which contains all the application-specific settings that
|
||||||
|
differ from the default ones provided by the reference configuration files from the individual Akka modules.
|
||||||
|
|
||||||
|
These are the relevant default configuration values for the Akka HTTP modules.
|
||||||
|
|
||||||
|
akka-http-core
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. literalinclude:: ../../../../akka-http-core/src/main/resources/reference.conf
|
||||||
|
:language: none
|
||||||
|
|
||||||
|
|
||||||
|
akka-http
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
.. literalinclude:: ../../../../akka-http/src/main/resources/reference.conf
|
||||||
|
:language: none
|
||||||
|
|
||||||
|
|
||||||
|
The other Akka HTTP modules do not offer any configuration via `Typesafe Config`_.
|
||||||
|
|
||||||
|
.. _Typesafe Config: https://github.com/typesafehub/config
|
||||||
233
akka-docs-dev/rst/java/http/http-model.rst
Normal file
233
akka-docs-dev/rst/java/http/http-model.rst
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
.. _http-model-java:
|
||||||
|
|
||||||
|
HTTP Model
|
||||||
|
==========
|
||||||
|
|
||||||
|
Akka HTTP model contains a deeply structured, fully immutable, case-class based model of all the major HTTP data
|
||||||
|
structures, like HTTP requests, responses and common headers.
|
||||||
|
It lives in the *akka-http-core* module and forms the basis for most of Akka HTTP's APIs.
|
||||||
|
|
||||||
|
Overview
|
||||||
|
--------
|
||||||
|
|
||||||
|
Since akka-http-core provides the central HTTP data structures you will find the following import in quite a
|
||||||
|
few places around the code base (and probably your own code as well):
|
||||||
|
|
||||||
|
.. includecode:: ../code/docs/http/javadsl/ModelSpec.java
|
||||||
|
:include: import-model
|
||||||
|
|
||||||
|
This brings all of the most relevant types in scope, mainly:
|
||||||
|
|
||||||
|
- ``HttpRequest`` and ``HttpResponse``, the central message model
|
||||||
|
- ``headers``, the package containing all the predefined HTTP header models and supporting types
|
||||||
|
- Supporting types like ``Uri``, ``HttpMethods``, ``MediaTypes``, ``StatusCodes``, etc.
|
||||||
|
|
||||||
|
A common pattern is that the model of a certain entity is represented by an immutable type (class or trait),
|
||||||
|
while the actual instances of the entity defined by the HTTP spec live in an accompanying object carrying the name of
|
||||||
|
the type plus a trailing plural 's'.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
- Defined ``HttpMethod`` instances are defined as static fields of the ``HttpMethods`` class.
|
||||||
|
- Defined ``HttpCharset`` instances are defined as static fields of the ``HttpCharsets`` class.
|
||||||
|
- Defined ``HttpEncoding`` instances are defined as static fields of the ``HttpEncodings`` class.
|
||||||
|
- Defined ``HttpProtocol`` instances are defined as static fields of the ``HttpProtocols`` class.
|
||||||
|
- Defined ``MediaType`` instances are defined as static fields of the ``MediaTypes`` class.
|
||||||
|
- Defined ``StatusCode`` instances are defined as static fields of the ``StatusCodes`` class.
|
||||||
|
|
||||||
|
HttpRequest
|
||||||
|
-----------
|
||||||
|
|
||||||
|
``HttpRequest`` and ``HttpResponse`` are the basic immutable classes representing HTTP messages.
|
||||||
|
|
||||||
|
An ``HttpRequest`` consists of
|
||||||
|
|
||||||
|
- a method (GET, POST, etc.)
|
||||||
|
- a URI
|
||||||
|
- a seq of headers
|
||||||
|
- an entity (body data)
|
||||||
|
- a protocol
|
||||||
|
|
||||||
|
Here are some examples how to construct an ``HttpRequest``:
|
||||||
|
|
||||||
|
.. includecode:: ../code/docs/http/javadsl/ModelSpec.java
|
||||||
|
:include: construct-request
|
||||||
|
|
||||||
|
In its basic form ``HttpRequest.create`` creates an empty default GET request without headers which can then be
|
||||||
|
transformed using one of the ``withX`` methods, ``addHeader``, or ``addHeaders``. Each of those will create a
|
||||||
|
new immutable instance, so instances can be shared freely. There exist some overloads for ``HttpRequest.create`` that
|
||||||
|
simplify creating requests for common cases. Also, to aid readability, there are predefined alternatives for ``create``
|
||||||
|
named after HTTP methods to create a request with a given method and uri directly.
|
||||||
|
|
||||||
|
HttpResponse
|
||||||
|
------------
|
||||||
|
|
||||||
|
An ``HttpResponse`` consists of
|
||||||
|
|
||||||
|
- a status code
|
||||||
|
- a list of headers
|
||||||
|
- an entity (body data)
|
||||||
|
- a protocol
|
||||||
|
|
||||||
|
Here are some examples how to construct an ``HttpResponse``:
|
||||||
|
|
||||||
|
.. includecode:: ../code/docs/http/javadsl/ModelSpec.java
|
||||||
|
:include: construct-response
|
||||||
|
|
||||||
|
In addition to the simple ``HttpEntities.create`` methods which create an entity from a fixed ``String`` or ``ByteString``
|
||||||
|
as shown here the Akka HTTP model defines a number of subclasses of ``HttpEntity`` which allow body data to be specified as a
|
||||||
|
stream of bytes. All of these types can be created using the method on ``HttpEntites``.
|
||||||
|
|
||||||
|
|
||||||
|
.. _HttpEntity-java:
|
||||||
|
|
||||||
|
HttpEntity
|
||||||
|
----------
|
||||||
|
|
||||||
|
An ``HttpEntity`` carries the data bytes of a message together with its Content-Type and, if known, its Content-Length.
|
||||||
|
In Akka HTTP there are five different kinds of entities which model the various ways that message content can be
|
||||||
|
received or sent:
|
||||||
|
|
||||||
|
HttpEntityStrict
|
||||||
|
The simplest entity, which is used when all the entity are already available in memory.
|
||||||
|
It wraps a plain ``ByteString`` and represents a standard, unchunked entity with a known ``Content-Length``.
|
||||||
|
|
||||||
|
|
||||||
|
HttpEntityDefault
|
||||||
|
The general, unchunked HTTP/1.1 message entity.
|
||||||
|
It has a known length and presents its data as a ``Source[ByteString]`` which can be only materialized once.
|
||||||
|
It is an error if the provided source doesn't produce exactly as many bytes as specified.
|
||||||
|
The distinction of ``HttpEntityStrict`` and ``HttpEntityDefault`` is an API-only one. One the wire,
|
||||||
|
both kinds of entities look the same.
|
||||||
|
|
||||||
|
|
||||||
|
HttpEntityChunked
|
||||||
|
The model for HTTP/1.1 `chunked content`__ (i.e. sent with ``Transfer-Encoding: chunked``).
|
||||||
|
The content length is unknown and the individual chunks are presented as a ``Source[ChunkStreamPart]``.
|
||||||
|
A ``ChunkStreamPart`` is either a non-empty chunk or the empty last chunk containing optional trailer headers.
|
||||||
|
The stream consists of zero or more non-empty chunks parts and can be terminated by an optional last chunk.
|
||||||
|
|
||||||
|
|
||||||
|
HttpEntityCloseDelimited
|
||||||
|
An unchunked entity of unknown length that is implicitly delimited by closing the connection (``Connection: close``).
|
||||||
|
Content data is presented as a ``Source[ByteString]``.
|
||||||
|
Since the connection must be closed after sending an entity of this type it can only be used on the server-side for
|
||||||
|
sending a response.
|
||||||
|
Also, the main purpose of ``CloseDelimited`` entities is compatibility with HTTP/1.0 peers, which do not support
|
||||||
|
chunked transfer encoding. If you are building a new application and are not constrained by legacy requirements you
|
||||||
|
shouldn't rely on ``CloseDelimited`` entities, since implicit terminate-by-connection-close is not a robust way of
|
||||||
|
signaling response end, especially in the presence of proxies. Additionally this type of entity prevents connection
|
||||||
|
reuse which can seriously degrade performance. Use ``HttpEntityChunked`` instead!
|
||||||
|
|
||||||
|
|
||||||
|
HttpEntityIndefiniteLength
|
||||||
|
A streaming entity of unspecified length for use in a ``Multipart.BodyPart``.
|
||||||
|
|
||||||
|
__ http://tools.ietf.org/html/rfc7230#section-4.1
|
||||||
|
|
||||||
|
Entity types ``HttpEntityStrict``, ``HttpEntityDefault``, and ``HttpEntityChunked`` are a subtype of ``RequestEntity``
|
||||||
|
which allows to use them for requests and responses. In contrast, ``HttpEntityCloseDelimited`` can only be used for responses.
|
||||||
|
|
||||||
|
Streaming entity types (i.e. all but ``HttpEntityStrict``) cannot be shared or serialized. To create a strict, sharable copy of an
|
||||||
|
entity or message use ``HttpEntity.toStrict`` or ``HttpMessage.toStrict`` which returns a ``Future`` of the object with
|
||||||
|
the body data collected into a ``ByteString``.
|
||||||
|
|
||||||
|
The class ``HttpEntities`` contains static methods to create entities from common types easily.
|
||||||
|
|
||||||
|
You can use the ``isX` methods of ``HttpEntity`` to find out of which subclass an entity is if you want to provide
|
||||||
|
special handling for each of the subtypes. However, in many cases a recipient of an ``HttpEntity`` doesn't care about
|
||||||
|
of which subtype an entity is (and how data is transported exactly on the HTTP layer). Therefore, a general
|
||||||
|
``HttpEntity::getDataBytes: Source<ByteString, ?>`` is provided which allows access to the data of an entity regardless
|
||||||
|
of its concrete subtype.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When to use which subtype?
|
||||||
|
- Use ``HttpEntityStrict`` if the amount of data is "small" and already available in memory (e.g. as a ``String`` or ``ByteString``)
|
||||||
|
- Use ``HttpEntityDefault`` if the data is generated by a streaming data source and the size of the data is known
|
||||||
|
- Use ``HttpEntityChunked`` for an entity of unknown length
|
||||||
|
- Use ``HttpEntityCloseDelimited`` for a response as a legacy alternative to ``HttpEntityChunked`` if the client
|
||||||
|
doesn't support chunked transfer encoding. Otherwise use ``HttpEntityChunked``!
|
||||||
|
- In a ``Multipart.Bodypart`` use ``HttpEntityIndefiniteLength`` for content of unknown length.
|
||||||
|
|
||||||
|
.. caution::
|
||||||
|
|
||||||
|
When you receive a non-strict message from a connection then additional data is only read from the network when you
|
||||||
|
request it by consuming the entity data stream. This means that, if you *don't* consume the entity stream then the
|
||||||
|
connection will effectively be stalled. In particular, no subsequent message (request or response) will be read from
|
||||||
|
the connection as the entity of the current message "blocks" the stream.
|
||||||
|
Therefore you must make sure that you always consume the entity data, even in the case that you are not actually
|
||||||
|
interested in it!
|
||||||
|
|
||||||
|
|
||||||
|
Header Model
|
||||||
|
------------
|
||||||
|
|
||||||
|
Akka HTTP contains a rich model of the most common HTTP headers. Parsing and rendering is done automatically so that
|
||||||
|
applications don't need to care for the actual syntax of headers. Headers not modelled explicitly are represented
|
||||||
|
as a ``RawHeader`` (which is essentially a String/String name/value pair).
|
||||||
|
|
||||||
|
See these examples of how to deal with headers:
|
||||||
|
|
||||||
|
.. includecode:: ../code/docs/http/javadsl/ModelSpec.java
|
||||||
|
:include: headers
|
||||||
|
|
||||||
|
|
||||||
|
HTTP Headers
|
||||||
|
------------
|
||||||
|
|
||||||
|
When the Akka HTTP server receives an HTTP request it tries to parse all its headers into their respective
|
||||||
|
model classes. Independently of whether this succeeds or not, the HTTP layer will
|
||||||
|
always pass on all received headers to the application. Unknown headers as well as ones with invalid syntax (according
|
||||||
|
to the header parser) will be made available as ``RawHeader`` instances. For the ones exhibiting parsing errors a
|
||||||
|
warning message is logged depending on the value of the ``illegal-header-warnings`` config setting.
|
||||||
|
|
||||||
|
Some headers have special status in HTTP and are therefore treated differently from "regular" headers:
|
||||||
|
|
||||||
|
Content-Type
|
||||||
|
The Content-Type of an HTTP message is modeled as the ``contentType`` field of the ``HttpEntity``.
|
||||||
|
The ``Content-Type`` header therefore doesn't appear in the ``headers`` sequence of a message.
|
||||||
|
Also, a ``Content-Type`` header instance that is explicitly added to the ``headers`` of a request or response will
|
||||||
|
not be rendered onto the wire and trigger a warning being logged instead!
|
||||||
|
|
||||||
|
Transfer-Encoding
|
||||||
|
Messages with ``Transfer-Encoding: chunked`` are represented as a ``HttpEntityChunked`` entity.
|
||||||
|
As such chunked messages that do not have another deeper nested transfer encoding will not have a ``Transfer-Encoding``
|
||||||
|
header in their ``headers`` list.
|
||||||
|
Similarly, a ``Transfer-Encoding`` header instance that is explicitly added to the ``headers`` of a request or
|
||||||
|
response will not be rendered onto the wire and trigger a warning being logged instead!
|
||||||
|
|
||||||
|
Content-Length
|
||||||
|
The content length of a message is modelled via its :ref:`HttpEntity-java`. As such no ``Content-Length`` header will ever
|
||||||
|
be part of a message's ``header`` sequence.
|
||||||
|
Similarly, a ``Content-Length`` header instance that is explicitly added to the ``headers`` of a request or
|
||||||
|
response will not be rendered onto the wire and trigger a warning being logged instead!
|
||||||
|
|
||||||
|
Server
|
||||||
|
A ``Server`` header is usually added automatically to any response and its value can be configured via the
|
||||||
|
``akka.http.server.server-header`` setting. Additionally an application can override the configured header with a
|
||||||
|
custom one by adding it to the response's ``header`` sequence.
|
||||||
|
|
||||||
|
User-Agent
|
||||||
|
A ``User-Agent`` header is usually added automatically to any request and its value can be configured via the
|
||||||
|
``akka.http.client.user-agent-header`` setting. Additionally an application can override the configured header with a
|
||||||
|
custom one by adding it to the request's ``header`` sequence.
|
||||||
|
|
||||||
|
Date
|
||||||
|
The ``Date`` response header is added automatically but can be overridden by supplying it manually.
|
||||||
|
|
||||||
|
Connection
|
||||||
|
On the server-side Akka HTTP watches for explicitly added ``Connection: close`` response headers and as such honors
|
||||||
|
the potential wish of the application to close the connection after the respective response has been sent out.
|
||||||
|
The actual logic for determining whether to close the connection is quite involved. It takes into account the
|
||||||
|
request's method, protocol and potential ``Connection`` header as well as the response's protocol, entity and
|
||||||
|
potential ``Connection`` header. See `this test`__ for a full table of what happens when.
|
||||||
|
|
||||||
|
__ @github@/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/ResponseRendererSpec.scala#L422
|
||||||
|
|
||||||
|
|
||||||
|
Parsing / Rendering
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Parsing and rendering of HTTP data structures is heavily optimized and for most types there's currently no public API
|
||||||
|
provided to parse (or render to) Strings or byte arrays.
|
||||||
|
|
@ -3,4 +3,12 @@
|
||||||
Akka HTTP
|
Akka HTTP
|
||||||
=========
|
=========
|
||||||
|
|
||||||
...
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
introduction
|
||||||
|
configuration
|
||||||
|
http-model
|
||||||
|
low-level-server-side-api
|
||||||
|
routing-dsl/index
|
||||||
|
client-side/index
|
||||||
28
akka-docs-dev/rst/java/http/introduction.rst
Normal file
28
akka-docs-dev/rst/java/http/introduction.rst
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
The Akka HTTP modules implement a full server- and client-side HTTP stack on top of *akka-actor* and *akka-stream*. It's
|
||||||
|
not a web-framework but rather a more general toolkit for providing and consuming HTTP-based services. While interaction
|
||||||
|
with a browser is of course also in scope it is not the primary focus of Akka HTTP.
|
||||||
|
|
||||||
|
Akka HTTP follows a rather open design and many times offers several different API levels for "doing the same thing".
|
||||||
|
You get to pick the API level of abstraction that is most suitable for your application.
|
||||||
|
This means that, if you have trouble achieving something using a high-level API, there's a good chance that you can get
|
||||||
|
it done with a low-level API, which offers more flexibility but might require you do write more application code.
|
||||||
|
|
||||||
|
Akka HTTP is structured into several modules:
|
||||||
|
|
||||||
|
akka-http-core
|
||||||
|
A complete, mostly low-level, server- and client-side implementation of HTTP (incl. WebSockets)
|
||||||
|
|
||||||
|
akka-http
|
||||||
|
Higher-level functionality, like (un)marshalling, (de)compression as well as a powerful DSL
|
||||||
|
for defining HTTP-based APIs on the server-side
|
||||||
|
|
||||||
|
akka-http-testkit
|
||||||
|
A test harness and set of utilities for verifying server-side service implementations
|
||||||
|
|
||||||
|
akka-http-jackson
|
||||||
|
Predefined glue-code for (de)serializing custom types from/to JSON with jackson_
|
||||||
|
|
||||||
|
.. _jackson: https://github.com/FasterXML/jackson
|
||||||
154
akka-docs-dev/rst/java/http/low-level-server-side-api.rst
Normal file
154
akka-docs-dev/rst/java/http/low-level-server-side-api.rst
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
.. _http-low-level-server-side-api-java:
|
||||||
|
|
||||||
|
Low-Level Server-Side API
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Apart from the :ref:`HTTP Client <http-client-side-java>` Akka HTTP also provides an embedded,
|
||||||
|
`Reactive-Streams`_-based, fully asynchronous HTTP/1.1 server implemented on top of :ref:`Akka Stream <streams-java>`.
|
||||||
|
|
||||||
|
It sports the following features:
|
||||||
|
|
||||||
|
- Full support for `HTTP persistent connections`_
|
||||||
|
- Full support for `HTTP pipelining`_
|
||||||
|
- Full support for asynchronous HTTP streaming including "chunked" transfer encoding accessible through an idiomatic API
|
||||||
|
- Optional SSL/TLS encryption
|
||||||
|
- Websocket support
|
||||||
|
|
||||||
|
.. _HTTP persistent connections: http://en.wikipedia.org/wiki/HTTP_persistent_connection
|
||||||
|
.. _HTTP pipelining: http://en.wikipedia.org/wiki/HTTP_pipelining
|
||||||
|
.. _Reactive-Streams: http://www.reactive-streams.org/
|
||||||
|
|
||||||
|
The server-side components of Akka HTTP are split into two layers:
|
||||||
|
|
||||||
|
1. The basic low-level server implementation in the ``akka-http-core`` module
|
||||||
|
2. Higher-level functionality in the ``akka-http`` module
|
||||||
|
|
||||||
|
The low-level server (1) is scoped with a clear focus on the essential functionality of an HTTP/1.1 server:
|
||||||
|
|
||||||
|
- Connection management
|
||||||
|
- Parsing and rendering of messages and headers
|
||||||
|
- Timeout management (for requests and connections)
|
||||||
|
- Response ordering (for transparent pipelining support)
|
||||||
|
|
||||||
|
All non-core features of typical HTTP servers (like request routing, file serving, compression, etc.) are left to
|
||||||
|
the higher layers, they are not implemented by the ``akka-http-core``-level server itself.
|
||||||
|
Apart from general focus this design keeps the server core small and light-weight as well as easy to understand and
|
||||||
|
maintain.
|
||||||
|
|
||||||
|
Depending on your needs you can either use the low-level API directly or rely on the high-level
|
||||||
|
:ref:`Routing DSL <http-high-level-server-side-api-java>` which can make the definition of more complex service logic much
|
||||||
|
easier.
|
||||||
|
|
||||||
|
|
||||||
|
Streams and HTTP
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The Akka HTTP server is implemented on top of :ref:`Akka Stream <streams-java>` and makes heavy use of it - in its
|
||||||
|
implementation as well as on all levels of its API.
|
||||||
|
|
||||||
|
On the connection level Akka HTTP offers basically the same kind of interface as :ref:`Akka Stream IO <stream-io-java>`:
|
||||||
|
A socket binding is represented as a stream of incoming connections. The application pulls connections from this stream
|
||||||
|
source and, for each of them, provides a ``Flow<HttpRequest, HttpResponse, ?>`` to "translate" requests into responses.
|
||||||
|
|
||||||
|
Apart from regarding a socket bound on the server-side as a ``Source<IncomingConnection>`` and each connection as a
|
||||||
|
``Source<HttpRequest>`` with a ``Sink<HttpResponse>`` the stream abstraction is also present inside a single HTTP
|
||||||
|
message: The entities of HTTP requests and responses are generally modeled as a ``Source<ByteString>``. See also
|
||||||
|
the :ref:`http-model-java` for more information on how HTTP messages are represented in Akka HTTP.
|
||||||
|
|
||||||
|
|
||||||
|
Starting and Stopping
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
On the most basic level an Akka HTTP server is bound by invoking the ``bind`` method of the `akka.http.javadsl.Http`_
|
||||||
|
extension:
|
||||||
|
|
||||||
|
.. includecode:: ../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||||
|
:include: binding-example
|
||||||
|
|
||||||
|
Arguments to the ``Http().bind`` method specify the interface and port to bind to and register interest in handling
|
||||||
|
incoming HTTP connections. Additionally, the method also allows for the definition of socket options as well as a larger
|
||||||
|
number of settings for configuring the server according to your needs.
|
||||||
|
|
||||||
|
The result of the ``bind`` method is a ``Source<Http.IncomingConnection>`` which must be drained by the application in
|
||||||
|
order to accept incoming connections.
|
||||||
|
The actual binding is not performed before this source is materialized as part of a processing pipeline. In
|
||||||
|
case the bind fails (e.g. because the port is already busy) the materialized stream will immediately be terminated with
|
||||||
|
a respective exception.
|
||||||
|
The binding is released (i.e. the underlying socket unbound) when the subscriber of the incoming
|
||||||
|
connection source has cancelled its subscription. Alternatively one can use the ``unbind()`` method of the
|
||||||
|
``Http.ServerBinding`` instance that is created as part of the connection source's materialization process.
|
||||||
|
The ``Http.ServerBinding`` also provides a way to get a hold of the actual local address of the bound socket, which is
|
||||||
|
useful for example when binding to port zero (and thus letting the OS pick an available port).
|
||||||
|
|
||||||
|
.. _akka.http.javadsl.Http: @github@/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala
|
||||||
|
|
||||||
|
|
||||||
|
Request-Response Cycle
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
When a new connection has been accepted it will be published as an ``Http.IncomingConnection`` which consists
|
||||||
|
of the remote address and methods to provide a ``Flow<HttpRequest, HttpResponse, ?>`` to handle requests coming in over
|
||||||
|
this connection.
|
||||||
|
|
||||||
|
Requests are handled by calling one of the ``handleWithXXX`` methods with a handler, which can either be
|
||||||
|
|
||||||
|
- a ``Flow<HttpRequest, HttpResponse, ?>`` for ``handleWith``,
|
||||||
|
- a function ``Function<HttpRequest, HttpResponse>`` for ``handleWithSyncHandler``,
|
||||||
|
- a function ``Function<HttpRequest, Future<HttpResponse>>`` for ``handleWithAsyncHandler``.
|
||||||
|
|
||||||
|
Here is a complete example:
|
||||||
|
|
||||||
|
.. includecode:: ../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||||
|
:include: full-server-example
|
||||||
|
|
||||||
|
In this example, a request is handled by transforming the request stream with a function ``Function<HttpRequest, HttpResponse>``
|
||||||
|
using ``handleWithSyncHandler`` (or equivalently, Akka Stream's ``map`` operator). Depending on the use case many
|
||||||
|
other ways of providing a request handler are conceivable using Akka Stream's combinators.
|
||||||
|
|
||||||
|
If the application provides a ``Flow`` it is also the responsibility of the application to generate exactly one response
|
||||||
|
for every request and that the ordering of responses matches the ordering of the associated requests (which is relevant
|
||||||
|
if HTTP pipelining is enabled where processing of multiple incoming requests may overlap). When relying on
|
||||||
|
``handleWithSyncHandler`` or ``handleWithAsyncHandler``, or the ``map`` or ``mapAsync`` stream operators, this
|
||||||
|
requirement will be automatically fulfilled.
|
||||||
|
|
||||||
|
|
||||||
|
Streaming Request/Response Entities
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Streaming of HTTP message entities is supported through subclasses of ``HttpEntity``. The application needs to be able
|
||||||
|
to deal with streamed entities when receiving a request as well as, in many cases, when constructing responses.
|
||||||
|
See :ref:`HttpEntity-java` for a description of the alternatives.
|
||||||
|
|
||||||
|
|
||||||
|
Closing a connection
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The HTTP connection will be closed when the handling ``Flow`` cancels its upstream subscription or the peer closes the
|
||||||
|
connection. An often times more convenient alternative is to explicitly add a ``Connection: close`` header to an
|
||||||
|
``HttpResponse``. This response will then be the last one on the connection and the server will actively close the
|
||||||
|
connection when it has been sent out.
|
||||||
|
|
||||||
|
|
||||||
|
.. _serverSideHTTPS-java:
|
||||||
|
|
||||||
|
Server-Side HTTPS Support
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Akka HTTP supports TLS encryption on the server-side as well as on the :ref:`client-side <clientSideHTTPS-java>`.
|
||||||
|
|
||||||
|
The central vehicle for configuring encryption is the ``HttpsContext``, which can be created using ``HttpsContext.create``
|
||||||
|
which is defined like this:
|
||||||
|
|
||||||
|
.. includecode:: /../../akka-http-core/src/main/java/akka/http/javadsl/HttpsContext.java
|
||||||
|
:include: http-context-creation
|
||||||
|
|
||||||
|
On the server-side the ``bind``, and ``bindAndHandleXXX`` methods of the `akka.http.javadsl.Http`_ extension define an
|
||||||
|
optional ``httpsContext`` parameter, which can receive the HTTPS configuration in the form of an ``HttpsContext``
|
||||||
|
instance.
|
||||||
|
If defined encryption is enabled on all accepted connections. Otherwise it is disabled (which is the default).
|
||||||
|
|
||||||
|
|
||||||
|
Stand-Alone HTTP Layer Usage
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
// TODO
|
||||||
11
akka-docs-dev/rst/java/http/routing-dsl/index.rst
Normal file
11
akka-docs-dev/rst/java/http/routing-dsl/index.rst
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
.. _http-high-level-server-side-api-java:
|
||||||
|
|
||||||
|
High-level Server-Side API
|
||||||
|
==========================
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
overview
|
||||||
4
akka-docs-dev/rst/java/http/routing-dsl/overview.rst
Normal file
4
akka-docs-dev/rst/java/http/routing-dsl/overview.rst
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
Routing DSL Overview
|
||||||
|
====================
|
||||||
|
|
||||||
|
...
|
||||||
|
|
@ -72,8 +72,8 @@ Here are some examples how to construct an ``HttpResponse``:
|
||||||
.. includecode:: ../../code/docs/http/scaladsl/ModelSpec.scala
|
.. includecode:: ../../code/docs/http/scaladsl/ModelSpec.scala
|
||||||
:include: construct-response
|
:include: construct-response
|
||||||
|
|
||||||
In addition to the simple ``HttpEntity`` constructors create an entity from a fixed ``String`` or ``ByteString`` shown
|
In addition to the simple ``HttpEntity`` constructors which create an entity from a fixed ``String`` or ``ByteString``
|
||||||
as here the Akka HTTP model defines a number of subclasses of ``HttpEntity`` which allow body data to be specified as a
|
as shown here the Akka HTTP model defines a number of subclasses of ``HttpEntity`` which allow body data to be specified as a
|
||||||
stream of bytes.
|
stream of bytes.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -93,9 +93,9 @@ HttpEntity.Strict
|
||||||
|
|
||||||
HttpEntity.Default
|
HttpEntity.Default
|
||||||
The general, unchunked HTTP/1.1 message entity.
|
The general, unchunked HTTP/1.1 message entity.
|
||||||
It has a known length and presents its data as a ``Source[ByteString]`` which can only materialized once.
|
It has a known length and presents its data as a ``Source[ByteString]`` which can be only materialized once.
|
||||||
It is an error if the provided source doesn't produce exactly as many bytes as specified.
|
It is an error if the provided source doesn't produce exactly as many bytes as specified.
|
||||||
On the wire, a ``Strict`` entity and a ``Default`` entity cannot be distinguished.
|
The distinction of ``Strict`` and ``Default`` is an API-only one. One the wire, both kinds of entities look the same.
|
||||||
|
|
||||||
|
|
||||||
HttpEntity.Chunked
|
HttpEntity.Chunked
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ It sports the following features:
|
||||||
- Full support for `HTTP pipelining`_
|
- Full support for `HTTP pipelining`_
|
||||||
- Full support for asynchronous HTTP streaming including "chunked" transfer encoding accessible through an idiomatic API
|
- Full support for asynchronous HTTP streaming including "chunked" transfer encoding accessible through an idiomatic API
|
||||||
- Optional SSL/TLS encryption
|
- Optional SSL/TLS encryption
|
||||||
|
- Websocket support
|
||||||
|
|
||||||
.. _HTTP persistent connections: http://en.wikipedia.org/wiki/HTTP_persistent_connection
|
.. _HTTP persistent connections: http://en.wikipedia.org/wiki/HTTP_persistent_connection
|
||||||
.. _HTTP pipelining: http://en.wikipedia.org/wiki/HTTP_pipelining
|
.. _HTTP pipelining: http://en.wikipedia.org/wiki/HTTP_pipelining
|
||||||
|
|
@ -26,7 +27,7 @@ The server-side components of Akka HTTP are split into two layers:
|
||||||
The low-level server (1) is scoped with a clear focus on the essential functionality of an HTTP/1.1 server:
|
The low-level server (1) is scoped with a clear focus on the essential functionality of an HTTP/1.1 server:
|
||||||
|
|
||||||
- Connection management
|
- Connection management
|
||||||
- Parsing messages and headers
|
- Parsing and rendering of messages and headers
|
||||||
- Timeout management (for requests and connections)
|
- Timeout management (for requests and connections)
|
||||||
- Response ordering (for transparent pipelining support)
|
- Response ordering (for transparent pipelining support)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,16 @@ public abstract class HttpsContext {
|
||||||
public abstract Option<ClientAuth> getClientAuth();
|
public abstract Option<ClientAuth> getClientAuth();
|
||||||
|
|
||||||
public abstract Option<SSLParameters> getSslParameters();
|
public abstract Option<SSLParameters> getSslParameters();
|
||||||
|
|
||||||
|
//#http-context-creation
|
||||||
public static HttpsContext create(SSLContext sslContext,
|
public static HttpsContext create(SSLContext sslContext,
|
||||||
Option<Collection<String>> enabledCipherSuites,
|
Option<Collection<String>> enabledCipherSuites,
|
||||||
Option<Collection<String>> enabledProtocols,
|
Option<Collection<String>> enabledProtocols,
|
||||||
Option<ClientAuth> clientAuth,
|
Option<ClientAuth> clientAuth,
|
||||||
Option<SSLParameters> sslParameters) {
|
Option<SSLParameters> sslParameters)
|
||||||
|
//#http-context-creation
|
||||||
|
{
|
||||||
return akka.http.scaladsl.HttpsContext.create(sslContext, enabledCipherSuites, enabledProtocols,
|
return akka.http.scaladsl.HttpsContext.create(sslContext, enabledCipherSuites, enabledProtocols,
|
||||||
clientAuth, sslParameters);
|
clientAuth, sslParameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue