157 lines
No EOL
8.1 KiB
ReStructuredText
157 lines
No EOL
8.1 KiB
ReStructuredText
.. _http-core-server-scala:
|
|
|
|
Server API
|
|
==========
|
|
|
|
The Akka HTTP server is an embedded, stream-based, fully asynchronous, low-overhead
|
|
HTTP/1.1 server implemented on top of `Akka Streams`_. (todo: fix link)
|
|
|
|
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
|
|
reactive streams API
|
|
- Optional SSL/TLS encryption
|
|
|
|
.. _HTTP persistent connections: http://en.wikipedia.org/wiki/HTTP_persistent_connection
|
|
.. _HTTP pipelining: http://en.wikipedia.org/wiki/HTTP_pipelining
|
|
.. _Akka streams: http://akka.io/docs/
|
|
|
|
|
|
Design Philosophy
|
|
-----------------
|
|
|
|
Akka HTTP server is scoped with a clear focus on the essential functionality of an HTTP/1.1 server:
|
|
|
|
- Connection management
|
|
- Parsing 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 next-higher layer in the application stack, they are not implemented by the HTTP server itself.
|
|
Apart from general focus this design keeps the server small and light-weight as well as easy to understand and
|
|
maintain.
|
|
|
|
|
|
Basic Architecture
|
|
------------------
|
|
|
|
Akka HTTP server is implemented on top of Akka streams and makes heavy use of them - in its
|
|
implementation and also on all levels of its API.
|
|
|
|
On the connection level Akka HTTP supports basically the same interface as Akka streams IO: A socket binding is
|
|
represented as a stream of incoming connections. The application needs to provide a ``Flow[HttpRequest, HttpResponse]``
|
|
to "translate" requests into responses.
|
|
|
|
Streaming is also supported for single message entities itself. Particular kinds of ``HttpEntity``
|
|
subclasses provide support for fixed or streamed message entities.
|
|
|
|
|
|
Starting and Stopping
|
|
---------------------
|
|
|
|
An Akka HTTP server is bound by invoking the ``bind`` method of the `akka.http.Http`_ extension:
|
|
|
|
.. includecode:: ../code/docs/http/HttpServerExampleSpec.scala
|
|
:include: bind-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 you to define 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 ``Http.ServerBinding`` which is immediately returned. The ``ServerBinding.connections``
|
|
returns a ``Source[IncomingConnection]`` which is used to handle incoming connections. The actual binding is only done when this
|
|
source is materialized as part of a bigger processing pipeline. In case the bind fails (e.g. because the port is already
|
|
busy) the error will be reported by flagging an error on the ``IncomingConnection`` stream.
|
|
|
|
After materialization ``ServerBinding.localAddress`` returns the actual local address of the bound socket.
|
|
|
|
Connections are handled by materializing a pipeline which uses the ``Source[IncomingConnection]`` returned by
|
|
``ServerBinding.connections``. The binding is released and the underlying listening socket is closed when all
|
|
subscribers of the ``connections`` source have cancelled their subscription.
|
|
|
|
(todo: explain even lower level serverFlowToTransport API)
|
|
|
|
.. _akka.http.Http: @github@/akka-http-core/src/main/scala/akka/http/Http.scala
|
|
|
|
|
|
Request-Response Cycle
|
|
----------------------
|
|
|
|
When a new connection has been accepted it will be published by by the ``ServerBinding.connections`` source 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 ``IncomingConnection.handleWithX`` methods with a handler, which can either be
|
|
|
|
- a ``Flow[HttpRequest, HttpResponse]`` for ``handleWith``,
|
|
- a function ``HttpRequest => HttpResponse`` for ``handleWithSyncHandler``,
|
|
- or a function ``HttpRequest => Future[HttpResponse]`` for ``handleWithAsyncHandler``.
|
|
|
|
.. includecode:: ../code/docs/http/HttpServerExampleSpec.scala
|
|
:include: full-server-example
|
|
|
|
In this case, a request is handled by transforming the request stream with a function ``HttpRequest => HttpResponse``
|
|
using ``handleWithSyncHandler`` (or equivalently, Akka stream's ``map`` operator). Depending on the use case, arbitrary
|
|
other ways of connecting 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). Using ``handleWithSyncHandler``
|
|
or ``handleWithAsyncHandler`` or, instead, if using stream operators like ``map`` or ``mapFuture`` this requirement
|
|
will automatically be fulfilled.
|
|
|
|
Streaming request/response entities
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Streaming of HTTP message entities is supported through subclasses of ``HttpEntity``. You need to be able to deal
|
|
with streamed entities when receiving a request as well as when constructing responses. See :ref:`HttpEntity` for
|
|
a description of the alternatives.
|
|
|
|
(todo): Link to :ref:`http-routing-scala` for (un-)marshalling facilities.
|
|
|
|
|
|
Closing a connection
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The HTTP connection will be closed when the handling ``Flow`` cancel its upstream subscription or the peer closes the
|
|
connection.
|
|
|
|
You can also use the value of the ``Connection`` header of a response as described below to give a hint to the
|
|
implementation to close the connection after the completion of the response.
|
|
|
|
HTTP Headers
|
|
------------
|
|
|
|
When the Akka HTTP server receives an HTTP request it tries to parse all its headers into their respective
|
|
model classes. No matter whether this succeeds or not, the connection actor 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 common headers are treated specially in the model and in the implementation and should not occur in the ``headers``
|
|
field of an HTTP message:
|
|
|
|
- ``Content-Type``: Use the ``contentType`` field of the ``HttpEntity`` subclasses to set or determine the content-type
|
|
on an entity.
|
|
- ``Transfer-Encoding``: The ``Transfer-Encoding`` is represented by subclasses of ``HttpEntity``.
|
|
- ``Content-Length``: The ``Content-Length`` header is represented implicitly by the choice of an ``HttpEntity`` subclass:
|
|
A Strict entity determines the Content-Length by the length of the data provided. A Default entity has an explicit
|
|
``contentLength`` field which specifies the amount of data the streaming producer will produce. Chunked and CloseDelimited
|
|
entities don't need to define a length.
|
|
- ``Server``: The ``Server`` header is usually added automatically and it's value can be configured. An application can
|
|
decide to provide a custom ``Server`` header by including an explicit instance in the response.
|
|
- ``Date``: The ``Date`` header is added automatically and can be overridden by supplying it manually.
|
|
- ``Connection``: When sending out responses the connection actor watches for a ``Connection`` header set by the
|
|
application and acts accordingly, i.e. you can force the connection actor to close the connection after having sent
|
|
the response by including a ``Connection("close")`` header. To unconditionally force a connection keep-alive you can
|
|
explicitly set a ``Connection("Keep-Alive")`` header. If you don't set an explicit ``Connection`` header the
|
|
connection actor will keep the connection alive if the client supports this (i.e. it either sent a
|
|
``Connection: Keep-Alive`` header or advertised HTTP/1.1 capabilities without sending a ``Connection: close`` header).
|
|
|
|
SSL Support
|
|
-----------
|
|
|
|
(todo) |