diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/HttpServerExampleSpec.java b/akka-docs-dev/rst/java/code/docs/http/javadsl/HttpServerExampleSpec.java new file mode 100644 index 0000000000..e0bc5a2edc --- /dev/null +++ b/akka-docs-dev/rst/java/code/docs/http/javadsl/HttpServerExampleSpec.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2009-2015 Typesafe Inc. + */ + +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> serverSource = + Http.get(system).bind("localhost", 8080, materializer); + + Future serverBindingFuture = + serverSource.to(Sink.foreach( + new Procedure() { + @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> serverSource = + Http.get(system).bind("localhost", 8080, materializer); + + final Function requestHandler = + new Function() { + 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(), + "Hello world!"); + else if (request.getUri().path().equals("/ping")) + return HttpResponse.create().withEntity("PONG!"); + else + return NOT_FOUND; + } + else return NOT_FOUND; + } + }; + + Future serverBindingFuture = + serverSource.to(Sink.foreach( + new Procedure() { + @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 + } +} diff --git a/akka-docs-dev/rst/java/code/docs/http/javadsl/ModelSpec.java b/akka-docs-dev/rst/java/code/docs/http/javadsl/ModelSpec.java new file mode 100644 index 0000000000..c7b4e28817 --- /dev/null +++ b/akka-docs-dev/rst/java/code/docs/http/javadsl/ModelSpec.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009-2015 Typesafe Inc. + */ + +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 getCredentialsOfRequest(HttpRequest request) { + Option 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 +} diff --git a/akka-docs-dev/rst/java/http/client-side/connection-level.rst b/akka-docs-dev/rst/java/http/client-side/connection-level.rst new file mode 100644 index 0000000000..8c68877973 --- /dev/null +++ b/akka-docs-dev/rst/java/http/client-side/connection-level.rst @@ -0,0 +1,4 @@ +.. _ConnectionLevelApi-java: + +Connection-Level Client-Side API +================================ diff --git a/akka-docs-dev/rst/java/http/client-side/host-level.rst b/akka-docs-dev/rst/java/http/client-side/host-level.rst new file mode 100644 index 0000000000..0484303b98 --- /dev/null +++ b/akka-docs-dev/rst/java/http/client-side/host-level.rst @@ -0,0 +1,4 @@ +.. _HostLevelApi-java: + +Host-Level Client-Side API +========================== diff --git a/akka-docs-dev/rst/java/http/client-side/https-support.rst b/akka-docs-dev/rst/java/http/client-side/https-support.rst new file mode 100644 index 0000000000..f97420cba2 --- /dev/null +++ b/akka-docs-dev/rst/java/http/client-side/https-support.rst @@ -0,0 +1,4 @@ +.. _clientSideHTTPS-java: + +Client-Side HTTPS Support +========================= diff --git a/akka-docs-dev/rst/java/http/client-side/index.rst b/akka-docs-dev/rst/java/http/client-side/index.rst new file mode 100644 index 0000000000..9e0a7261d5 --- /dev/null +++ b/akka-docs-dev/rst/java/http/client-side/index.rst @@ -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 \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/client-side/request-level.rst b/akka-docs-dev/rst/java/http/client-side/request-level.rst new file mode 100644 index 0000000000..75eb9b4e62 --- /dev/null +++ b/akka-docs-dev/rst/java/http/client-side/request-level.rst @@ -0,0 +1,6 @@ +.. _RequestLevelApi-java: + +Request-Level Client-Side API +============================= + +... \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/client-side/websocket-support.rst b/akka-docs-dev/rst/java/http/client-side/websocket-support.rst new file mode 100644 index 0000000000..69cdb560eb --- /dev/null +++ b/akka-docs-dev/rst/java/http/client-side/websocket-support.rst @@ -0,0 +1,4 @@ +Client-Side WebSocket Support +============================= + +TODO \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/configuration.rst b/akka-docs-dev/rst/java/http/configuration.rst new file mode 100644 index 0000000000..00c02e25a3 --- /dev/null +++ b/akka-docs-dev/rst/java/http/configuration.rst @@ -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 \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/http-model.rst b/akka-docs-dev/rst/java/http/http-model.rst new file mode 100644 index 0000000000..983831d24f --- /dev/null +++ b/akka-docs-dev/rst/java/http/http-model.rst @@ -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`` 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. diff --git a/akka-docs-dev/rst/java/http/index.rst b/akka-docs-dev/rst/java/http/index.rst index 99a1336ce9..ccaa676527 100644 --- a/akka-docs-dev/rst/java/http/index.rst +++ b/akka-docs-dev/rst/java/http/index.rst @@ -3,4 +3,12 @@ Akka HTTP ========= -... \ No newline at end of file +.. toctree:: + :maxdepth: 2 + + introduction + configuration + http-model + low-level-server-side-api + routing-dsl/index + client-side/index \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/introduction.rst b/akka-docs-dev/rst/java/http/introduction.rst new file mode 100644 index 0000000000..fe641ea0a6 --- /dev/null +++ b/akka-docs-dev/rst/java/http/introduction.rst @@ -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 diff --git a/akka-docs-dev/rst/java/http/low-level-server-side-api.rst b/akka-docs-dev/rst/java/http/low-level-server-side-api.rst new file mode 100644 index 0000000000..e0f9a43190 --- /dev/null +++ b/akka-docs-dev/rst/java/http/low-level-server-side-api.rst @@ -0,0 +1,154 @@ +.. _http-low-level-server-side-api-java: + +Low-Level Server-Side API +========================= + +Apart from the :ref:`HTTP Client ` Akka HTTP also provides an embedded, +`Reactive-Streams`_-based, fully asynchronous HTTP/1.1 server implemented on top of :ref:`Akka Stream `. + +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 ` 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 ` 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 `: +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`` to "translate" requests into responses. + +Apart from regarding a socket bound on the server-side as a ``Source`` and each connection as a +``Source`` with a ``Sink`` the stream abstraction is also present inside a single HTTP +message: The entities of HTTP requests and responses are generally modeled as a ``Source``. 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`` 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`` 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`` for ``handleWith``, + - a function ``Function`` for ``handleWithSyncHandler``, + - a function ``Function>`` 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`` +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 `. + +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 \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/routing-dsl/index.rst b/akka-docs-dev/rst/java/http/routing-dsl/index.rst new file mode 100644 index 0000000000..85758fd319 --- /dev/null +++ b/akka-docs-dev/rst/java/http/routing-dsl/index.rst @@ -0,0 +1,11 @@ +.. _http-high-level-server-side-api-java: + +High-level Server-Side API +========================== + +... + +.. toctree:: + :maxdepth: 1 + + overview \ No newline at end of file diff --git a/akka-docs-dev/rst/java/http/routing-dsl/overview.rst b/akka-docs-dev/rst/java/http/routing-dsl/overview.rst new file mode 100644 index 0000000000..477c5fb3ec --- /dev/null +++ b/akka-docs-dev/rst/java/http/routing-dsl/overview.rst @@ -0,0 +1,4 @@ +Routing DSL Overview +==================== + +... \ No newline at end of file diff --git a/akka-docs-dev/rst/scala/http/common/http-model.rst b/akka-docs-dev/rst/scala/http/common/http-model.rst index 8fc9fca17f..578f57f39c 100644 --- a/akka-docs-dev/rst/scala/http/common/http-model.rst +++ b/akka-docs-dev/rst/scala/http/common/http-model.rst @@ -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 diff --git a/akka-docs-dev/rst/scala/http/low-level-server-side-api.rst b/akka-docs-dev/rst/scala/http/low-level-server-side-api.rst index 380839ad14..0fcc13055f 100644 --- a/akka-docs-dev/rst/scala/http/low-level-server-side-api.rst +++ b/akka-docs-dev/rst/scala/http/low-level-server-side-api.rst @@ -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) diff --git a/akka-http-core/src/main/java/akka/http/javadsl/HttpsContext.java b/akka-http-core/src/main/java/akka/http/javadsl/HttpsContext.java index b3820305a3..28c429d712 100644 --- a/akka-http-core/src/main/java/akka/http/javadsl/HttpsContext.java +++ b/akka-http-core/src/main/java/akka/http/javadsl/HttpsContext.java @@ -23,13 +23,16 @@ public abstract class HttpsContext { public abstract Option getClientAuth(); public abstract Option getSslParameters(); - + + //#http-context-creation public static HttpsContext create(SSLContext sslContext, Option> enabledCipherSuites, Option> enabledProtocols, Option clientAuth, - Option sslParameters) { + Option sslParameters) + //#http-context-creation + { return akka.http.scaladsl.HttpsContext.create(sslContext, enabledCipherSuites, enabledProtocols, clientAuth, sslParameters); } -} \ No newline at end of file +}