package http
The core module for lolhttp.
Server.listen(8888) { request => Ok("Hello world!") } Client.run(Get("http://localhost:8888/")) { response => response.readAs[String] }
Provides an HTTP Client and an HTTP Server. Both client and server are Service functions. A service function takes a Request and eventually returns a Response. Requests and responses are shared between the client and the server API, making it easy to assemble them. Both are seen as a set of HTTP headers, and a Content body.
The content fs2.Stream
is based on fs2
and can be lazily consumed if needed.
It can be encoded and decoded using the appropriate ContentEncoder and ContentDecoder.
SSL is supported on both sides.
- Source
- package.scala
- Alphabetic
- By Inheritance
- http
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
-
case class
ClasspathResource(path: String) extends Product with Serializable
A resource than can be read from the classpath.
A resource than can be read from the classpath.
Ok(ClasspathResource("/public/index.html"))
A common use case is to serve static resources (html, js, images files) from the classpath. ClasspathResource values can be directly encoded as Content and used to feed an HTTP response.
Trying to write a missing resource on an HTTP response will close the connection.
Also, this provide a basic security by requiring the path to be asbolutely defined. No directory navigation is allowed. For example
ClasspathResource("/public/../public/index.html")
will resolve to a missing resource. -
trait
Client extends Service
An HTTP client.
An HTTP client.
val eventuallyContent = client(Get("/hello")).flatMap { response => response.readAs[String] }
An HTTP client is a Service function. It handles HTTP requests and eventually returns HTTP responses.
A client maintains several TCP connections to the remote server. These connections are used to send requests and are blocked until the corresponding response has been received. If no connection is available when a new request comes, it waits for one connection to become available.
It is important that the user code completly consumes the response content stream, so the connection is freed for the next request. That's why it is better to use the
run
operation if possible since this one automatically drains the request upon return.If the request to execute does not specify an Host header, it will be automatically added and set to the value of the client
host
. -
case class
Content(stream: Stream[IO, Byte], headers: Map[HttpString, HttpString] = Map.empty) extends Product with Serializable
An HTTP message content body.
An HTTP message content body.
It is used to represent the content body for both HTTP requests & responses. It is composed of a lazy stream of byte that can be consumed if needed, and a set of content-related HTTP headers (such as
Content-Length
,Content-Type
, etc.).The provided stream is not pure and can only be consumed once.
- stream
an
fs2.Stream
ofByte
.- headers
a set of content-related HTTP headers.
-
trait
ContentDecoder[+A] extends AnyRef
An HTTP content decoder.
An HTTP content decoder.
val textContent: Content = ??? val textDecoder: ContentDecoder[String] = ContentDecoder.text(maxSize = 1024, defaultCodec = Codec.UTF8) val text: String = textDecoder(textContent).unsafeRun()
A content decoder is able to parse an HTTP content into a scala value of type
A
. It will look at the content HTTP headers if needed, and consume the content stream bytes to eventually output a scala value. -
trait
ContentEncoder[-A] extends AnyRef
A HTTP content encoder.
A HTTP content encoder.
val text = "Hello, world" val textEncoder: ContentEncoder[String] = ContentEncoder.text(codec = Codec.UTF8) val textContent: Content = textEncoder(text)
A content decoder is able to encode a scala value into an HTTP content . It will produce both a stream of bytes and the set of required HTTP headers like
Content-Length
orContent-Type
. -
case class
Error(code: Int, msg: String) extends RuntimeException with Product with Serializable
Expected errors.
Expected errors.
See the companion object for all defined errors.
- code
the error code.
- msg
the error message.
-
class
HttpMethod extends AnyRef
An HTTP method such as GET or POST.
-
case class
HttpString(str: String) extends Ordered[HttpString] with Product with Serializable
An case insensitive string.
An case insensitive string.
val contentType: HttpString = h"text/plain"
HTTP strings are case insensitive. The
h
string interpolation allows to create HttpString easily.- str
the underlying string.
-
implicit
class
LiteralHttpString extends AnyRef
The
h
interpolation creates HttpString values.The
h
interpolation creates HttpString values. You can use it as a matcher too.val header = h"LOCATION" header match { case h"Location" => println("this is the Location header") case _ => println("wrong header") }
-
case class
Panic(msg: String) extends RuntimeException with Product with Serializable
Panics are errors that should not occur or should not be handled.
Panics are errors that should not occur or should not be handled.
- msg
the error message.
-
type
PartialService = PartialFunction[Request, IO[Response]]
A partial service is not defined for all Request.
-
case class
Request(method: HttpMethod, url: String = "/", scheme: String = "http", content: Content = Content.empty, headers: Map[HttpString, HttpString] = Map.empty, protocol: String = HTTP, from: Option[InetAddress] = None) extends Product with Serializable
An HTTP request.
An HTTP request.
Represent all the data available in the HTTP request headers, and the request content that can be consumed lazily if needed.
- method
the HTTP method such as GET or POST.
- url
the resource URL.
- scheme
the scheme such as
http
orhttps
.- content
the request content.
- headers
the HTTP headers.
- protocol
the protocol version.
-
case class
Response(status: Int, content: Content = Content.empty, headers: Map[HttpString, HttpString] = Map.empty) extends Product with Serializable
An HTTP response.
An HTTP response.
Represent all the data available in the HTTP response headers, and the response content that can be consumed lazily if needed.
- status
the HTTP response code such as
200
or404
.- content
the response content.
- headers
the HTTP headers.
-
trait
Server extends Service
An HTTP server.
An HTTP server.
val eventuallyContent = server(Get("/hello")).flatMap { response => response.readAs[String] }
An HTTP server is a service function. It handles HTTP requests and eventually returns HTTP responses.
The server listen for HTTP connections on the socketAddress TCP socket. If ssl is defined, it supports TLS connections. Calling the stop operation asks for a graceful shutdown.
-
type
Service = (Request) ⇒ IO[Response]
A service is a function from Request to eventually a Response.
-
implicit
class
UrlMatcher extends AnyRef
The
url
interpolation is mainly useful in pattern matching to match and extract dynamic parameters in URL templates.The
url
interpolation is mainly useful in pattern matching to match and extract dynamic parameters in URL templates. You can use it to build URL string too, but in this case it acts as the standards
interpolation.val userProfile = url"/users/$userId" userProfile match { case url"/users/$userId" => println("user id" -> userId) case url"/images/$image..." => println("image path" -> image) case url"/search?keyword=$keyword&sort=$sort" => println("keyword" -> keyword) case _ => println("wrong url") }
The matcher allow to extract dynamic parts from both the URL path and queryString. For the path only a fragment or a fragment part can be extracted (no
/
will be matched):url"/users/$id/items" = "/users/12/items" // will match with id="12" url"/users/id-$id/items" = "/users/id-12/items" // will match with id="12"
If you want to capture several fragments, you can use the
...
syntax:url"/files/$file..." = "/files/images/lol.png" // will match with file="images/lol.png"
You can also match and extract from the queryString. The parameter order is not important and parameters not specified in the pattern will be ignored:
url"/?page=$page&sort=$sort" = "/?sort=asc&page=3&offset=2" // will match with page="3", sort="asc" url"/?section=home" = "/?section=home&update=now" // will match url"/?section=home&update=$date" = "/?section=contact&update=now" // won't match
Value Members
-
lazy val
BadRequest: Response
A 400 Bad request Response.
-
lazy val
Created: Response
A 201 Created Response.
-
val
DELETE: HttpMethod
DELETE HTTP method.
-
def
Delete(url: String): Request
Constructs a DELETE Request.
-
val
GET: HttpMethod
GET HTTP method.
-
def
Get(url: String): Request
Constructs a GET Request.
-
val
HEAD: HttpMethod
HEAD HTTP method.
-
val
HTTP: String
Protocol version for HTTP/1.1
-
val
HTTP2: String
Protocol version for HTTP/2
-
def
Head(url: String): Request
Constructs a HEAD Request.
-
lazy val
InternalServerError: Response
A 500 Internal server error Response.
-
lazy val
NotFound: Response
A 404 Not found Response.
-
lazy val
Ok: Response
A 200 Ok Response.
-
val
POST: HttpMethod
POST HTTP method.
-
val
PUT: HttpMethod
PUT HTTP method.
-
def
Post[A](url: String, content: A)(implicit encoder: ContentEncoder[A]): Request
Constructs a POST Request.
-
def
Put[A](url: String, content: A)(implicit encoder: ContentEncoder[A]): Request
Constructs a PUT Request.
-
def
Redirect(url: String, code: Int = 307): Response
Create 30x HTTP redirects.
Create 30x HTTP redirects.
- url
will be used as
Location
header value.- code
the actual status code to use (default to 307).
- returns
a 30x Response.
-
def
UpgradeRequired(protocol: HttpString): Response
Create a 426 Upgrade required Response.
Create a 426 Upgrade required Response.
- protocol
the new protocol the server want to switch to.
-
implicit
def
pureResponse(response: Response): IO[Response]
Automatically convert a Response into a pure
IO[Response]
if needed. -
implicit
def
sseDecoder[A](implicit eventDecoder: EventDecoder[A]): ContentDecoder[Stream[IO, Event[A]]]
Support for Server Sent Events decoding.
-
implicit
def
sseEncoder[A](implicit eventEncoder: EventEncoder[A]): ContentEncoder[Stream[IO, Event[A]]]
Support for Server Sent Events encoding.
-
object
ClasspathResource extends Serializable
Define the implicit encoder for ClasspathResource.
-
object
Client
Build HTTP clients.
Build HTTP clients.
val client = Client("github.com") val fetchGithubHomePage: IO[String] = for { homePage <- client.run(Get("/"))(_.readAs[String]) _ <- client.stop() } yield (homePage) println(fetchGithubHomePage.unsafeRunSync)
Once created an HTTP client maintains several TCP connections to the remote server, and can be reused to run several requests. It is better to create a dedicated client this way if you plan to send many requests to the same server.
However there are some situations where you have a single request to run, or you have a batch of requests to send over an unknown set of servers. In this case you can use the run operation that automatically create a temporary HTTP client to run the request and trash it after the exchange completion.
val homePage = Client.run(Get("http://github.com/"))(_.readAs[String])
Note that in this case, for each request, a new client (including the whole IO infrastructure) will to be created, and a new TCP connection will be opened to the server.
-
object
Content extends Serializable
Build HTTP message content body.
Build HTTP message content body.
val textContent: Content = Content.of("Hello world!")
Given an existing ContentDecoder for a type
A
, this object allows to create HTTP content fromA
values. Meaning, it will encode the value into a stream of bytes, and a set of appropriate HTTP headers. -
object
ContentDecoder
Library of built-in content decoders.
Library of built-in content decoders.
This provides content decoder functions for the common scala types, and implicit decoder configured with a set of sensible default.
The implicitly provided decoders are chosen by the compiler and cannot be explicitly configured. In particular they are automatically configured with a MaxSize limit that specify the maximum amount of bytes they are authorized to read in memory.
It means that for example, this code:
val str: String = request.readAs[String]
will truncate the content body if it is bigger than the MaxSize property. The default for MaxSize is
1MB
, and can be configured globally via thelol.http.ContentDecoder.maxSizeInMemory
system property.If you want to configure the content decoder to allow it to read more data despite the maximum set in MaxSize, you can just pass the content decoder yourself instead of relying on implicit resolution:
val str: String = request.readAs(text(maxSize = 10 * 1024 * 1024))
-
object
ContentEncoder
Library of built-in content encoders.
Library of built-in content encoders.
This provides content encoder functions for the common scala types, and implicit encoder configured with a set of sensible default.
The implicitly provided encoders are chosen by the compiler and cannot be explicitly configured.
For example, this code:
val response = Ok("Hello, world!")
will generate an HTTP response body by encoding the provided string using the UTF-8 charset.
If you want to configure the content encoder, you can just pass it yourself instead of relying on implicit resolution:
val response = Ok("Hello, world!")(text(codec = Codec("us-ascii")))
-
object
Error extends Serializable
All expected errors.
-
object
Headers
A collection of HTTP header names.
-
object
HttpMethod
HTTP method matcher.
HTTP method matcher.
request.method match { case GET => println("This is a get") case _ => println("Oops") }
Allow to match HTTP methods.
-
object
HttpString extends Serializable
HttpString builders.
-
object
Panic extends Serializable
Allows to panic.
-
object
SSL
lol SSL.
-
object
Server
Build and start HTTP servers.
Build and start HTTP servers.
Server.listen(8888) { request => Ok("Hello world!") }
Starting an HTTP server require a service function. The service function will be run on the provided
scala.concurrent.ExecutionContext
. This function should be non-blocking, but you can also decide to go with a blocking service if you provide an appropriate ExecutionContext (just note that if the ExecutionContext is fully blocked, the HTTP server is fully blocked).The service function will be called by the server as soon as new HTTP request header has been received. The server also set up a lazy stream for the body. User code can pull from this stream and consume it if needed. Otherwise it will be drained after exchange completion (ie. when the response has been fully sent).
The response value returned by the service function will be transfered back to the client.
-
object
ServerSentEvents
Support for Server Sent Events content.
Support for Server Sent Events content. It allows a server to stream events to a client. Events are string (utf-8) encoded, and a proper
EventEncoder
orEventDecoded
must be available for your event payload type. -
object
at
Request extractor.
Request extractor.
val app: PartialService = { case GET at "/" => Ok("Home") case _ => NotFound }
Matches Request values by splitting them in a (HTTP method, URL) pair.