pekko/akka-docs/modules/http.rst

200 lines
No EOL
7.4 KiB
ReStructuredText
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

.. _http-module:
HTTP
====
.. sidebar:: Contents
.. contents:: :local:
Play2-mini
----------
The Akka team recommends the `Play2-mini <https://github.com/typesafehub/play2-mini>`_ framework when building RESTful
service applications that integrates with Akka. It provides a REST API on top of `Play2 <https://github.com/playframework/Play20/>`_.
Getting started
---------------
First you must make your application aware of play-mini.
In SBT you just have to add the following to your _libraryDependencies_::
libraryDependencies += "com.typesafe" %% "play-mini" % "2.0-RC3-SNAPSHOT"
Sample Application
------------------
To illustrate how easy it is to wire a RESTful service with Akka we will use a sample application.
The aim of the application is to show how to use play-mini and Akka in combination. Do not put too much
attention on the actual business logic itself, which is a extremely simple bank application, as building a bank
application is a little more complex than what's shown in the sample...
The application should support the following URL commands:
- GET /ping - returns a Pong message with the time of the server (used to see if the application is up and running)
- GET /account/statement/{accountId} - returns the account statement
- POST /account/deposit - deposits money to an account (and creates a new one if it's not already existing)
- POST /account/withdraw - withdraws money from an account
Error messages will be returned in case of any misuse of the application, e.g. withdrawing more money than an
account has etc.
Getting started
---------------
To build a play-mini application you first have to make your object extend com.typesafe.play.mini.Application:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: playMiniDefinition
The next step is to implement the mandatory method ``route``:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: route
:exclude: routeLogic
It is inside the ``route`` method that all the magic happens.
In the sections below we will show how to set up play-mini to handle both GET and POST HTTP calls.
Simple GET
----------
We start off by creating the simplest method we can - a "ping" method:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: simpleGET
As you can see in the section above play-mini uses Scala's wonderful pattern matching.
In the snippet we instruct play-mini to reply to all HTTP GET calls with the URI "/ping".
The ``Action`` returned comes from Play! and you can find more information about it `here <https://github.com/playframework/Play20/wiki/ScalaActions>`_.
.. _Advanced-GET:
Advanced GET
------------
Let's try something more advanced, retrieving parameters from the URI and also make an asynchronous call to an actor:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: regexGET
The regular expression looks like this:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: regexURI
In the snippets above we extract a URI parameter with the help of a simple regular expression and then we pass this
parameter on to the underlying actor system. As you can see ``AsyncResult`` is being used. This means that the call to
the actor will be performed asynchronously, i.e. no blocking.
The asynchronous call to the actor is being done with a ``ask``, e.g.::
(accountActor ask Status(accountId))
The actor that receives the message returns the result by using a standard *sender !*
as can be seen here:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: senderBang
When the result is returned to the calling code we use some mapping code in Play to convert a Akka future to a Play future.
This is shown in this code:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: innerRegexGET
In this snippet we check the result to decide what type of response we want to send to the calling client.
Using HTTP POST
---------------
Okay, in the sections above we have shown you how to use play-mini for HTTP GET calls. Let's move on to when the user
posts values to the application.
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: asyncDepositPOST
As you can see the structure is almost the same as for the :ref:`Advanced-GET`. The difference is that we make the
``request`` parameter ``implicit`` and also that the following line of code is used to extract parameters from the POST.
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: formAsyncDepositPOST
The code snippet used to map the call to parameters looks like this:
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
:include: form
Apart from the mapping of parameters the call to the actor looks is done the same as in :ref:`Advanced-GET`.
The Complete Code Sample
------------------------
Below is the complete application in all its beauty.
Global.scala (<yourApp>/src/main/scala/Global.scala):
.. includecode:: code/Global.scala
PlayMiniApplication.scala (<yourApp>/src/main/scala/akka/docs/http/PlayMiniApplication.scala):
.. includecode:: code/akka/docs/http/PlayMiniApplication.scala
Build.scala (<yourApp>/project/Build.scala):
.. code-block:: scala
import sbt._
import Keys._
object PlayMiniApplicationBuild extends Build {
lazy val root = Project(id = "play-mini-application", base = file("."), settings = Project.defaultSettings).settings(
libraryDependencies += "com.typesafe" %% "play-mini" % "2.0-RC3-SNAPSHOT",
mainClass in (Compile, run) := Some("play.core.server.NettyServer"))
}
Running the Application
-----------------------
Firstly, start up the application by opening a command terminal and type::
> sbt
> run
Now you should see something similar to this in your terminal window::
[info] Running play.core.server.NettyServer
Play server process ID is 2523
[info] play - Application started (Prod)
[info] play - Listening for HTTP on port 9000...
In this example we will use the awesome `cURL <http://en.wikipedia.org/wiki/CURL>`_ command to interact with the application.
Fire up a command terminal and try the application out::
First we check the status of a couple of accounts:
> curl http://localhost:9000/account/statement/TheDudesAccount
Unknown account: TheDudesAccount
> curl http://localhost:9000/account/statement/MrLebowskisAccount
Unknown account: MrLebowskisAccount
Now deposit some money to the accounts:
> curl -d "accountId=TheDudesAccount&amount=1000" http://localhost:9000/account/deposit
Updated account total: 1000
> curl -d "accountId=MrLebowskisAccount&amount=500" http://localhost:9000/account/deposit
Updated account total: 500
Next thing is to check the status of the account:
> curl http://localhost:9000/account/statement/TheDudesAccount
Account total: 1000
> curl http://localhost:9000/account/statement/MrLebowskisAccount
Account total: 500
Fair enough, let's try to withdraw some cash shall we:
> curl -d "accountId=TheDudesAccount&amount=999" http://localhost:9000/account/withdraw
Updated account total: 1
> curl -d "accountId=MrLebowskisAccount&amount=999" http://localhost:9000/account/withdraw
Unknown account or insufficient funds. Get your act together.
> curl -d "accountId=MrLebowskisAccount&amount=500" http://localhost:9000/account/withdraw
Updated account total: 0
Yeah, it works!
Now we leave it to the astute reader of this document to take advantage of the power of play-mini and Akka.