Skip to content

Commit

Permalink
Docs
Browse files Browse the repository at this point in the history
  • Loading branch information
adamw committed Jan 2, 2025
1 parent d749fe7 commit 49db99a
Show file tree
Hide file tree
Showing 15 changed files with 63 additions and 54 deletions.
2 changes: 1 addition & 1 deletion docs/backends/akka.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ The akka-http backend support both regular and streaming [websockets](../other/w

## Testing

Apart from testing using [the stub](../testing.md), you can create a backend using any `HttpRequest => Future[HttpResponse]` function, or an akka-http `Route`.
Apart from testing using [the stub](../testing/stub.md), you can create a backend using any `HttpRequest => Future[HttpResponse]` function, or an akka-http `Route`.

That way, you can "mock" a server that the backend will talk to, without starting any actual server or making any HTTP calls.

Expand Down
2 changes: 1 addition & 1 deletion docs/backends/pekko.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ The pekko-http backend support both regular and streaming [websockets](../other/

## Testing

Apart from testing using [the stub](../testing.md), you can create a backend using any `HttpRequest => Future[HttpResponse]` function, or an pekko-http `Route`.
Apart from testing using [the stub](../testing/stub.md), you can create a backend using any `HttpRequest => Future[HttpResponse]` function, or an pekko-http `Route`.

That way, you can "mock" a server that the backend will talk to, without starting any actual server or making any HTTP calls.

Expand Down
2 changes: 1 addition & 1 deletion docs/backends/zio.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ The `HttpClient` ZIO backend supports both regular and streaming [websockets](..
## Testing

A stub backend can be created through the `.stub` method on the companion object, and configured as described in the
[testing](../testing.md) section.
[testing](../testing/stub.md) section.

A layer with the stub `SttpBackend` can be then created by simply calling `ZLayer.succeed(sttpBackendStub)`.

Expand Down
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ Third party projects:
:maxdepth: 2
:caption: Testing
testing
testing/stub
testing/curl
.. toctree::
:maxdepth: 2
Expand Down
8 changes: 4 additions & 4 deletions docs/model/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ The model also contains aggregate/helper classes such as `Headers` and `QueryPar
Example with objects:

```scala mdoc:compile-only
import sttp.client4._
import sttp.model._
import sttp.client4.*
import sttp.model.*

object Example:
val request = basicRequest.header(Header.contentType(MediaType.ApplicationJson))
Expand All @@ -36,8 +36,8 @@ object Example:
Example with traits:

```scala mdoc:compile-only
import sttp.client4._
import sttp.model._
import sttp.client4.*
import sttp.model.*

object Example extends HeaderNames with MediaTypes with StatusCodes:
val request = basicRequest.header(ContentType, ApplicationJson.toString)
Expand Down
4 changes: 2 additions & 2 deletions docs/model/uri.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ The `Uri` class is immutable, and can be constructed by hand, but in many cases
Using the URI interpolator it's possible to conveniently create `Uri` instances, for example:

```scala mdoc:compile-only
import sttp.client4._
import sttp.model._
import sttp.client4.*
import sttp.model.*

val user = "Mary Smith"
val filter = "programming languages"
Expand Down
2 changes: 2 additions & 0 deletions docs/requests/authentication.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Authentication

## Supported schemes

sttp supports basic, bearer-token based authentication and digest authentication. Two first cases are handled by adding an `Authorization` header with the appropriate credentials.

Basic authentication, using which the username and password are encoded using Base64, can be added as follows:
Expand Down
27 changes: 8 additions & 19 deletions docs/requests/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,40 +31,29 @@ The URI can be created programmatically (by calling methods on the `Uri` class),

## Sending a request

A request definition can be created without knowing how it will be sent. But to send a request, a backend is needed. A default, synchronous backend based on Java's `HttpURLConnection` is provided in the `core` jar.
A request definition can be created without knowing how it will be sent. But to send a request, a backend is needed. A default, synchronous backend based on Java's `HttpClient` is provided in the `core` jar.

To invoke the `send(backend)` method on a request description, you'll need an instance of `SttpBackend`:
To invoke the `send(backend)` method on a request description, you'll need an instance of `Backend`:

```scala mdoc:compile-only
val backend = DefaultSyncBackend()
val response: Response[Either[String, String]] = request.send(backend)
```

The default backend uses the `Identity` effect to return responses, which is equivalent to a synchronous call (no effect at all). Other asynchronous backends use other effect types. See the section on [backends](../backends/summary.md) for more details.
The default backend invokes any effects synchronously. Other, asynchronous backends, use "wrapper" effect types, such as `Future` or `IO`. See the section on [backends](../backends/summary.md) for more details.

```{eval-rst}
.. note::
Only requests with the request method and uri can be sent. If trying to send a request without these components specified, a compile-time error will be reported. On how this is implemented, see the documentation on the :doc:`type of request definitions <type>`.
Only requests with the request method and uri can be sent. When trying to send a request without these components specified, a compile-time error will be reported. On how this is implemented, see the documentation on the :doc:`type of request definitions <type>`.
```

## Initial requests

sttp provides two initial requests:
sttp provides three initial requests:

* `basicRequest`, which is an empty request with the `Accept-Encoding: gzip, deflate` header added. That's the one that is most commonly used.
* `basicRequest`, which is an empty request with the `Accept-Encoding: gzip, deflate` header added. That's the one that is most commonly used. By default reads the response as a `Either[String, String]` (indicating HTTP 4xx/5xx failure or 2xx success).
* `emptyRequest`, a completely empty request, with no headers at all.
* `quickRequest`, which by default reads the response as a `String` in case of a success, and throws an exception / returns a failed effect in case of a 4xx/5xx HTTP error response.

Both of these requests will by default read the response body into a UTF-8 `String`. How the response body is handled is also part of the request definition. See the section on [response body specifications](../responses/body.md) for more details on how to customize that.

## Debugging requests

sttp comes with builtin request to curl converter. To convert request to curl invocation use `.toCurl` method.

For example:

```scala mdoc
basicRequest.get(uri"http://httpbin.org/ip").toCurl
```

Note that the `Accept-Encoding` header, which is added by default to all requests (`Accept-Encoding: gzip, deflate`), can make curl warn that _binary output can mess up your terminal_, when running generated command from the command line. It can be omitted by setting `omitAcceptEncoding = true` when calling `.toCurl` method.
How the response body is handled can be (and very often is) customized. See the section on [response body specifications](../responses/body.md) for more details.
2 changes: 2 additions & 0 deletions docs/requests/cookies.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Cookies

## Cookies on requests

Cookies sent in requests are key-value pairs contained in the `Cookie` header. They can be set on a request in a couple of ways. The first is using the `.cookie(name: String, value: String)` method. This will yield a new request definition which, when sent, will contain the given cookie.

Cookies are currently only available on the JVM.
Expand Down
15 changes: 15 additions & 0 deletions docs/requests/headers.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Headers

## Arbitrary headers

Arbitrary headers can be set on the request using the `.header` method:

```scala mdoc:compile-only
Expand Down Expand Up @@ -42,3 +44,16 @@ basicRequest.acceptEncoding("gzip, deflate")
```

See also documentation on setting [cookies](cookies.md) and [authentication](authentication.md).

## Header names

To avoid using string literals for header names, the `HeaderNames` object from sttp model can be used:

```scala mdoc:compile-only
import sttp.client4.*
import sttp.model.HeaderNames
import sttp.model.headers.CacheDirective
import scala.concurrent.duration.*

basicRequest.header(HeaderNames.CacheControl, CacheDirective.MaxAge(1.day).toString)
```
2 changes: 1 addition & 1 deletion docs/requests/multipart.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The content type of each part is by default the same as when setting simple bodi
The parts can be specified using either a `Seq[Multipart]` or by using multiple arguments:

```scala mdoc:compile-only
import sttp.client4._
import sttp.client4.*

basicRequest.multipartBody(Seq(multipart("p1", "v1"), multipart("p2", "v2")))
basicRequest.multipartBody(multipart("p1", "v1"), multipart("p2", "v2"))
Expand Down
14 changes: 6 additions & 8 deletions docs/requests/streaming.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

Some backends (see [backends summary](../backends/summary.md)) support streaming bodies, as described by the `Streams[S]` capability. If that's the case, you can set a stream of the supported type as a request body using the `streamBody` method, instead of the usual `body` method.

```{eval-rst}
.. note::
Here, streaming refers to (usually) non-blocking, asynchronous streams of data. To send data which is available as an ``InputStream``, or a file from local storage (which is available as a ``File`` or ``Path``), no special backend support is needed. See the documenttation on :doc:`setting the request body <body>`.
```{note}
Here, streaming refers to (usually) non-blocking, asynchronous streams of data. To send data which is available as an `InputStream`, or a file from local storage (which is available as a `File` or `Path`), no special backend support is needed. See the documenttation on [setting the request body](body.md).
```

An implementation of the `Streams[S]` capability must be passed to the `.streamBody` method, to determine the type of streams that are supported. These implementations are provided by the backend implementations, e.g. `AkkaStreams` or `Fs2Streams[F]`.
An implementation of the `Streams[S]` capability must be passed to the `.streamBody` method, to determine the type of streams that are supported. These implementations are provided by the backend implementations, e.g. `PekkoStreams` or `Fs2Streams[F]`.

For example, using the [akka-http backend](../backends/akka.md), a request with a streaming body can be defined as follows:
For example, using the [pekko-http backend](../backends/pekko.md), a request with a streaming body can be defined as follows:

```scala mdoc:compile-only
import sttp.client4.*
Expand All @@ -27,8 +25,8 @@ basicRequest
.streamBody(PekkoStreams)(source)
```

```{eval-rst}
.. note:: A request with the body set as a stream can only be sent using a backend supporting exactly the given type of streams.
```{note}
A request with the body set as a stream can only be sent using a backend supporting exactly the given type of streams.
```

It's also possible to specify that the [response body should be a stream](../responses/body.md).
17 changes: 4 additions & 13 deletions docs/requests/type.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
# The type of request definitions

All request definitions have type `RequestT[U, T, R]` (RequestT as in Request Template). If this looks a bit complex, don't worry, what the three type parameters stand for is the only thing you'll hopefully have to remember when using the API!
Most request definitions have the type `Request[T]`. The `T` specifies the type to which the response will be read. By default, this is `Either[String, String]`. But it can also be e.g. `Array[Byte]` or `Unit`, if the response should be ignored. Response body handling can be changed by calling the `.response` method. With backends which support streaming, this can also be a supported stream type. See [response body specifications](../responses/body.md) for more details.

Going one-by-one:
If you're using streaming [request](streaming.md)/[response](../responses/body.md) bodies, you'll get a `StreamRequest[T, R]`. The `R` type parameter specifies the requirements of this request. In case of streaming, this will be an implementation of `Streams[S]`, such as `Fs2Streams[F]` or `PekkoStreams`. You can only send such requests using backends, which also support this type of streaming (this is verified at compile-time)!

* `U[_]` specifies if the request method and URL are specified. Using the API, this can be either `type Empty[X] = None`, meaning that the request has neither a method nor an URI. Or, it can be `type Id[X] = X` (type-level identity), meaning that the request has both a method and an URI specified. Only requests with a specified URI & method can be sent.
* `T` specifies the type to which the response will be read. By default, this is `Either[String, String]`. But it can also be e.g. `Array[Byte]` or `Unit`, if the response should be ignored. Response body handling can be changed by calling the `.response` method. With backends which support streaming, this can also be a supported stream type. See [response body specifications](../responses/body.md) for more details.
* `R` specifies the requirements of this request. Most of the time this will be `Any`, meaning that this request does not have any special requirements, and can be sent using any backend. So most of the time you can just ignore that parameter. However, if you are using streaming [request](streaming.md)/[response](../responses/body.md) bodies or [websockets](../other/websockets.md), the type parameter will reflect the required capabilities. They can include `Effect[F]`, `Streams[S]` and `WebSockets`.
If you're describing a web socket request, you'll get a `WebSocketRequest[F[_], T]`. The `F[_]` type parameter describes the effect, using which the web socket is processed (by default, the request then also contains the entire logic to interact with the web socket, although this is not strictly required). For synchronous web sockets, `F[_]` will be `Identity` ("no wrapper", direct-style). For asynchronous web sockets, `F[_]` might be `Future` or `IO` (or any other effect type). As with streams, such requests can only be sent using backends which support web sockets, and the effect type used to process the web socket.

There are two type aliases for the request template that are used:

* `type Request[T, R] = RequestT[Identity, T, R]`. A sendable request.
* `type PartialRequest[T, R] = RequestT[Empty, T, R]`

As `basicRequest`, the starting request, by default reads the body into a `Either[String, String]`, its type is:

`basicRequest: PartialRequest[Either[String, String], Any]`
Finally, if you're processing the websocket using streaming, you'll work with a `WebSocketStreamRequest[T, S]`. As before, `S` will contain the required streaming capability. However, it will also contain the effect type, which is used to interact with the web socket. An example value for `S` might be `PekkoStreams & Effect[Future]`.
11 changes: 11 additions & 0 deletions docs/testing/curl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Converting requests to CURL commands

sttp comes with builtin request to curl converter. To convert request to curl invocation use `.toCurl` method.

For example:

```scala mdoc
basicRequest.get(uri"http://httpbin.org/ip").toCurl
```

Note that the `Accept-Encoding` header, which is added by default to all requests (`Accept-Encoding: gzip, deflate`), can make curl warn that _binary output can mess up your terminal_, when running generated command from the command line. It can be omitted by setting `omitAcceptEncoding = true` when calling `.toCurl` method.
6 changes: 3 additions & 3 deletions docs/testing.md → docs/testing/stub.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Testing
# The stub backend

If you need a stub backend for use in tests instead of a "real" backend (you probably don't want to make HTTP calls during unit tests), you can use the `SttpBackendStub` class. It allows specifying how the backend should respond to requests matching given predicates.

You can also create a stub backend using [akka-http routes](backends/akka.md).
You can also create a stub backend using [akka-http routes](../backends/akka.md).

## Creating a stub backend

Expand Down Expand Up @@ -287,7 +287,7 @@ the `WebSocket` trait is recommended.

Using `RecordingSttpBackend` it's possible to capture all interactions in which a backend has been involved.

The recording backend is a [backend wrapper](backends/wrappers/custom.md), and it can wrap any backend, but it's most
The recording backend is a [backend wrapper](../backends/wrappers/custom.md), and it can wrap any backend, but it's most
useful when combined with the backend stub.

Example usage:
Expand Down

0 comments on commit 49db99a

Please sign in to comment.