.. _http-model-scala: 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/scaladsl/ModelSpec.scala :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 live in the ``HttpMethods`` object. - Defined ``HttpCharset`` instances live in the ``HttpCharsets`` object. - Defined ``HttpEncoding`` instances live in the ``HttpEncodings`` object. - Defined ``HttpProtocol`` instances live in the ``HttpProtocols`` object. - Defined ``MediaType`` instances live in the ``MediaTypes`` object. - Defined ``StatusCode`` instances live in the ``StatusCodes`` object. HttpRequest ----------- ``HttpRequest`` and ``HttpResponse`` are the basic case 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/scaladsl/ModelSpec.scala :include: construct-request All parameters of ``HttpRequest.apply`` have default values set, so ``headers`` for example don't need to be specified if there are none. Many of the parameters types (like ``HttpEntity`` and ``Uri``) define implicit conversions for common use cases to simplify the creation of request and response instances. HttpResponse ------------ An ``HttpResponse`` consists of - a status code - a seq of headers - an entity (body data) - a protocol 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 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. .. _HttpEntity: 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: HttpEntity.Strict 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``. 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 be only materialized once. It is an error if the provided source doesn't produce exactly as many bytes as specified. The distinction of ``Strict`` and ``Default`` is an API-only one. One the wire, both kinds of entities look the same. HttpEntity.Chunked 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[HttpEntity.ChunkStreamPart]``. A ``ChunkStreamPart`` is either a non-empty ``Chunk`` or a ``LastChunk`` containing optional trailer headers. The stream consists of zero or more ``Chunked`` parts and can be terminated by an optional ``LastChunk`` part. HttpEntity.CloseDelimited An unchunked entity of unknown length that is implicitly delimited by closing the connection (``Connection: close``). The content data are 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 ``HttpEntity.Chunked`` instead! HttpEntity.IndefiniteLength A streaming entity of unspecified length for use in a ``Multipart.BodyPart``. __ http://tools.ietf.org/html/rfc7230#section-4.1 Entity types ``Strict``, ``Default``, and ``Chunked`` are a subtype of ``HttpEntity.Regular`` which allows to use them for requests and responses. In contrast, ``HttpEntity.CloseDelimited`` can only be used for responses. Streaming entity types (i.e. all but ``Strict``) 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 ``HttpEntity`` companion object contains several helper constructors to create entities from common types easily. You can pattern match over the subtypes of ``HttpEntity`` 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, the general method ``HttpEntity.dataBytes`` is provided which returns a ``Source[ByteString, Any]`` that allows access to the data of an entity regardless of its concrete subtype. .. note:: When to use which subtype? - Use ``Strict`` if the amount of data is "small" and already available in memory (e.g. as a ``String`` or ``ByteString``) - Use ``Default`` if the data is generated by a streaming data source and the size of the data is known - Use ``Chunked`` for an entity of unknown length - Use ``CloseDelimited`` for a response as a legacy alternative to ``Chunked`` if the client doesn't support chunked transfer encoding. Otherwise use ``Chunked``! - In a ``Multipart.Bodypart`` use ``IndefiniteLength`` for content of unknown length. .. caution:: When you receive a non-strict message from a connection then additional data are only read from the network when you request them 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! Special processing for HEAD requests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `RFC 7230`_ defines very clear rules for the entity length of HTTP messages. Especially this rule requires special treatment in Akka HTTP: Any response to a HEAD request and any response with a 1xx (Informational), 204 (No Content), or 304 (Not Modified) status code is always terminated by the first empty line after the header fields, regardless of the header fields present in the message, and thus cannot contain a message body. Responses to HEAD requests introduce the complexity that `Content-Length` or `Transfer-Encoding` headers can be present but the entity is empty. This is modeled by allowing `HttpEntity.Default` and `HttpEntity.Chunked` to be used for HEAD responses with an empty data stream. Also, when a HEAD response has an `HttpEntity.CloseDelimited` entity the Akka HTTP implementation will *not* close the connection after the response has been sent. This allows the sending of HEAD responses without `Content-Length` header across persistent HTTP connections. .. _RFC 7230: http://tools.ietf.org/html/rfc7230#section-3.3.3 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/scaladsl/ModelSpec.scala :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 via the ``HttpEntity.Chunked`` entity. As such chunked messages that do not have another deeper nested transfer encoding will not have a ``Transfer-Encoding`` header in their ``headers`` sequence. 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`. 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. .. note:: Various parsing and rendering settings are available to tweak in the configuration under ``akka.http.client[.parsing]``, ``akka.http.server[.parsing]`` and ``akka.http.host-connection-pool[.client.parsing]``. Please note that while each of these sections expose the same parsing options, they will only be used for their respective APIs. For example, changing a setting inside ``akka.http.client.parsing`` **does not** change the same value in ``akka.http.host-connection-pool.client.parsing``, as they are different APIs. You can check which settings to tweak for which method exposed on the Http object by inspecting their ScalaDoc. In general though it's as simple as "pool" backed services use the ``host-connection-pool`` section, other clients which expose ``Flow`` use the ``client`` section, and the server side uses the ``server`` configuration section.