=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
|
||||
=========
|
||||
|
||||
...
|
||||
.. 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
|
||||
:include: construct-response
|
||||
|
||||
In addition to the simple ``HttpEntity`` constructors create an entity from a fixed ``String`` or ``ByteString`` shown
|
||||
as here the Akka HTTP model defines a number of subclasses of ``HttpEntity`` which allow body data to be specified as a
|
||||
In addition to the simple ``HttpEntity`` constructors 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.
|
||||
|
||||
|
||||
|
|
@ -93,9 +93,9 @@ HttpEntity.Strict
|
|||
|
||||
HttpEntity.Default
|
||||
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.
|
||||
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
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ It sports the following features:
|
|||
- 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
|
||||
|
|
@ -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:
|
||||
|
||||
- Connection management
|
||||
- Parsing messages and headers
|
||||
- Parsing and rendering of messages and headers
|
||||
- Timeout management (for requests and connections)
|
||||
- Response ordering (for transparent pipelining support)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,16 @@ public abstract class HttpsContext {
|
|||
public abstract Option<ClientAuth> getClientAuth();
|
||||
|
||||
public abstract Option<SSLParameters> getSslParameters();
|
||||
|
||||
|
||||
//#http-context-creation
|
||||
public static HttpsContext create(SSLContext sslContext,
|
||||
Option<Collection<String>> enabledCipherSuites,
|
||||
Option<Collection<String>> enabledProtocols,
|
||||
Option<ClientAuth> clientAuth,
|
||||
Option<SSLParameters> sslParameters) {
|
||||
Option<SSLParameters> sslParameters)
|
||||
//#http-context-creation
|
||||
{
|
||||
return akka.http.scaladsl.HttpsContext.create(sslContext, enabledCipherSuites, enabledProtocols,
|
||||
clientAuth, sslParameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue