This is a stduy notes for sttp. sttp is an open-source Scala Http client library that provides a clean and programmer-friendly API to make HTTP requests. It can use one of many wrapped backends, such as akka-http, async-http-client, http4s or OkHttp.

Quick Start

The default backend is Java’s HttpURLConnection. use import sttp.client.quick._ to import an implicit synchronous backend, the default backend. To see more requests and helper methods, use import sttp.client._ and check the methods in basicRequest.

Model Classes

sttp model is a stand-alone project which provides a basic HTTP model and constants. The basic classes include Header, Cookie, CookieWithMeta, MediaType, Method, StatusCode and Uri. Use companion objects to crete a model class instance.

A request can only be sent if the request method and URI are defined. Use uri prefix and a string template to define an instance of a Uri.

Define and Send a Request

Use the cookie, body, and post etc. methods of the sttp.client.basicRequest to define a request. Use the send method that takes an implicit SttpBackend instance to send a request.

sttp provides two requests: emptyRequest with no headers at all, and basicRequest that has Accept-Encoding: gzip, defalt.

Use basicRequest.auth.bear(token) to set authentication token.

Use Map[String, String] or Seq[(String, String)] as parameter of body() method to send form data. The content type will default to application/x-www-form-urlencoded; content length will also be set if not specified. Use BodySerializer[B] to define a custom body serializer.

All requests have type RequestT[U, T, S] where U shows whether the request method and URL are specified, T is the response type that has a default type of Either[String, String], S specifies the stream type. The basicRequest has a type of RequestT[Empty, Either[String, String], Nothing].

Response

Responses are represented as instances of the case class Response[T], where T is the type of the response body. When sending a request, the response will be returned in a wrapper. For example, for asynchronous backends, we can get a Future[Response[T]]. while for the default synchronous backend, the wrapper will be a no-op, Id, which is the same as no wrapper at all.

The code property returns the response code. The isSuccess and isServerError check for specific response code ranges.

the headers property gives all headers as a sequence. The contentType and contentLength helper methods are used to read some header values.

Response Body

The default response body has a type of Either[String, String], using the encoding specified in the Content-Type response header. The default response.body will be a:

  • Left(errorMessage) if the request is successful, but response code is not expected (non 2xx).
  • Right(body) if the request is successful and the response code is expected (2xx).

Use sttp.response method to specify the response type, such as sttp.response(asByteArray) to specify a response type fo Either[String, Array[Byte]]. Other values could be ignore, asString, and asParams etc.

akka-http Backend

Add the dependencies of "com.softwaremill.sttp.client" %% "akka-http-backend" % "2.0.0-RC5" and "com.typesafe.akka" %% "akka-stream" % "2.5.11" to your project to use the fully asyn backend that returns a response wrapped in a Future. Use implicit val sttpBackend = AkkaHttpBackend() or to use an existing actory system: implicit val sttpBackend = AkkaHttpBackend.usingActorSystem(actorSystem). Call sttpBackend.close() to free resources used by the backend.

JSON

Use "com.softwaremill.sttp.client" %% "circe" % "2.0.0-RC6" to add the circe dependency. Need to define an implicit circe encoder for the request payload and a decoder for the response. The code is as the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import sttp.client._
import sttp.client.circe._

implicit val backend = HttpURLConnectionBackend()

// Assume that there is an implicit circe encoder in scope
// for the request Payload, and a decoder for the MyResponse
val requestPayload: Payload = ???

val response: Response[Either[ResponseError[io.circe.Error], MyResponse]] =
  basicRequest
    .post(uri"...")
    .body(requestPayload)
    .response(asJson[MyResponse])
    .send()

To define the coder and decoder for any class, use @JsonCodec macro. For Scala 2.13, use -Ymacro-annotations Scalac option, not Macro Paradis plugin.