- The router is the component in charge of translating each incoming HTTP request to an Action. Each route consists of an HTTP method, and URI patterns, both associated with a call to an Action Generator.
- URI patterns
- static patch
- dynamic parts
- dynamic parts with custom regular expressions
- dynamic parts spanning several /
- A simple result contains a status code, a set of HTTP headers and a body to be sent to the client.
- The result content type is automatically inferred from the Scala value that you specify as the response body. Just use the as (new ContentType) method on a result to create a new similar result with a different Content-Type header.
- “text/plain” | “text/xml” | “text/html”
For text based HTTP response it is very important to handle the charset correctly. Play handles that for you and use utf-8 by default. The charset is used to both convert the text response to the corresponding bytes to send over the network socket, and to update the Content-Type header with the proper ;charset=xxx extension. The charset is handled automatically via the play.api.mvc.CodeC type class. Just import an implicit instance of play.api.mvc.CodeC in the current scope to change the charset that will be used by all operations.
The benefit of using HTML instead of “text/html” is that the charset will be automatically handled for you and the actual Content-Type header will be set to text/html;charset=utf-8.
- “text/plain” | “text/xml” | “text/html”
- You can add/update any HTTP header to result by withHeaders
- Cookies are just special form of HTTP header by withCookies
- If you want to remove cookies, you can use discardingCookies
- Redirecting the browser to a new URL is just another kind of simple result. However, these result type don’t take a response body. The default is to use a 303 SEE_OTHER response type, but you can set a more special status code if you need one.
- A play.api.mvc.Action is basically a (play.api.mvc.Request => play.api.mvc.Result) function that handles a request and generate a result to be sent to the client.
- It is useful to mark the request parameter as implicit so it can be implicitly used by other APIs.
- A Controller is nothing more than a singleton object that generates Action values.
- Action composition
- By implementing your own ActionBuilder, you can declare reusable action stacks, that can then be used to build actions.
- Implementing ActionBuilder’s invokeBlock method
- Actions can be mixed in to action builders using the composeAction method.
- Each action function may represent modular processing such as authentication, database lookups for objects, permission checks, or other operations that you wish to compose and reuse across actions.
- A HTTP Put or Post request contains a body. This body can use any format, specified in the Content-Type request header. In Play, a body parser transforms this request body into a Scala value.
- The request body for a HTTP request can be very large and a body parser can’t just wait and load the whole data set into memory before parsing it. A BodyParser[A] is basically an Iteratee[Array[Byte], A] meaning that it receives chunks of bytes (as long as the web browser uploads some data) and computes a value of type A as result.
- A text body parse could accumulate chunks of bytes into a String, and give the computed String as result, Iteratee[Array[Byte], String]
- A file body parser could store each chunk of bytes into a local file, and give a reference to the java.io.File as result, Iteratee[Array[Byte], File]
- A S3 body parser could push each chunk of bytes to Amazon S3 and give a S3 object id as result, Iteratee[Array[Byte], S3ObjectId]
- A body parser has access to the HTTP request headers before it starts parsing the request body, and has the opportunity to run some precondition checks. For example, a body parser can check some HTTP headers are properly set, or that the user trying to upload a large file has the permission to do so.
- Once the body parser finishes its job and gives back a value of type A, the corresponding Action function is executed and the computed body value is passed into the request.
A Front-end HTTP Server:
- Deploy play application as a stand-alone server is used by setting the application HTTP port to 80
- Using a font-end HTTP server, like Apache, Lighttpd, Nginx will rarely give you better performance that using Play server directly. However, HTTP servers are very good at handling HTTPs, conditional GET requests and static assets, and many services assume a front end HTTP server is part of your architecture.