Request

A Request describes a pattern within an HTTP request that a Route attempts to match. It can also create an HTTP request that the Request will match. This so-called reverse routing allows creating clients that will call an endpoint.

A Request always matches an HTTP method and a Path. It may match other components of a request as well. It may also extract elements from the path, query parameters, and other parts of the request. These are passed to the Route handler.

The Request Type

You can usually avoid writing Request types explicitly, but in case you have to write them down a Request is defined as

Request[P <: Tuple, Q <: Tuple, I <: Tuple, O <: Tuple]

where

Creating Requests

Requests are created by calling the method on the Request object that corresponds to the HTTP method of interest. For example, Request.get for a GET request, Request.post for a POST request, and so on. Thesse methods all accept a Path, as described in the next section, which is the only required part of a Request in addition to the HTTP method.

Here is an example that matches a GET request to the path /user/<int>, where <int> is an integer.

Request.get(Path / "user" / Param.int)

Working with paths is quite complex, so this has it's own documentation.

You can optionally match and extract values from the headers and entity of a HTTP request. If you want to extract match or extract values from the headers, you must call these methods before you call methods that deal with the entity. This design makes it a bit easier to deal with the types inside Request.

Headers

You can extract the value of any particular header in the HTTP request, and make that value available to the request handler. Alternatively you can ensure that the header exists and has a particular value, but not make that value availabe to the handler.

There are two variants of the extractHeader method, which will get the value of a header and make it available to the handler. In the first variant you specify just the type of the header, which is usually found in the org.https4s.headers package.

Here is an example the extracts the value associated with the Content-Type header.

import org.http4s.headers.*

Request.get(Path / "user" / Param.int)
  .extractHeader[`Content-Type`]

If we want to extract more than one header we call andExtractHeader for each additional header after the first.

Request.get(Path / "user" / Param.int)
  .extractHeader[`Content-Type`]
  .andExtractHeader[Referer]

This variant of extractHeader requires us to specify a value for the header when we do reverse routing. We can avoid this by providing a header when we call extractHeader.

In this example we construct a JSON Content-Type header and pass that value to extractHeader. Now jsonContentType will be used when constructing an HTTP request matching this request.

import org.http4s.MediaType

val jsonContentType = `Content-Type`(MediaType.application.json)

Request.get(Path / "user" / Param.int)
  .extractHeader(jsonContentType)

We often want to ensure that a header matches a particular value, but don't want to otherwise do anything with the value. In other words, we don't want to the header's value passed to the handler once we have verified it exists. For these cases we can use ensureHeader.

Request.get(Path / "user" / Param.int)
  .ensureHeader(jsonContentType)

As with extractHeader, we use andEnsureHeader to ensure two or more headers.

Finally, not that although we've used Content-Type headers in the examples you don't normally have to deal with them. If you specify a Entity that will check the headers are correct. We've used them in this examples as they are probably the headers that are most familiar to most web developers.

Entities

Calling the withEntity method on a Request allows you to specify an Entity, which is responsible for extracting data from an HTTP request. The Entity is responsible for checking the HTTP Content-Type header, and, if it matches, decoding the HTTP entity into a Scala value.

Here's an example of a Request that extracts HTML content as a String value.

Request.get(Path.root).withEntity(Entity.html)

There are several predefined Entity values on the companion object, but you can easily create your own if needed.

Paths→