Skip to content

Commit

Permalink
Release 0.18.0-M1
Browse files Browse the repository at this point in the history
  • Loading branch information
adamw committed Mar 31, 2021
1 parent a0eb926 commit 0868018
Show file tree
Hide file tree
Showing 29 changed files with 555 additions and 447 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ tapir documentation is available at [tapir.softwaremill.com](http://tapir.softwa
Add the following dependency:

```sbt
"com.softwaremill.sttp.tapir" %% "tapir-core" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-core" % "0.18.0-M1"
```

You'll need partial unification enabled in the compiler (alternatively, you'll need to manually provide type arguments in some cases):
Expand Down
48 changes: 48 additions & 0 deletions generated-doc/out/client/http4s.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Using as an http4s client

Add the dependency:

```scala
"com.softwaremill.sttp.tapir" %% "tapir-http4s-client" % "0.18.0-M1"
```

To interpret an endpoint definition as an `org.http4s.Request[F]`, import:

```scala
import sttp.tapir.client.http4s.Http4sClientInterpreter
```

This objects contains two methods:
- `toRequestUnsafe(Endpoint, Option[String])`: given the optional base URI, returns a function
which generates a request and a response parser from endpoint inputs. Response parser throws
an exception if decoding of the result fails.
```scala
I => (org.http4s.Request[F], org.http4s.Response[F] => F[Either[E, O]])
```
- `toRequest(Endpoint, Option[String])`: given the optional base URI, returns a function
which generates a request and a response parser from endpoint inputs. Response parser
returns an instance of `DecodeResult` which contains the decoded response body or error details.
```scala
I => (org.http4s.Request[F], org.http4s.Response[F] => F[DecodeResult[Either[E, O]]])
```

Note that the returned functions have one-argument: the input values of end endpoint. This might be a
single type, a tuple, or a case class, depending on the endpoint description.

After providing the input parameters, the following values are returned:
- An instance of `org.http4s.Request[F]` with the input value
encoded as appropriate request parameters: path, query, headers and body.
The request can be further customised and sent using an http4s client, or run against `org.http4s.HttpRoutes[F]`.
- A response parser to be applied to the response received after executing the request.
The result will then contain the decoded error or success values
(note that this can be the body enriched with data from headers/status code).

See the [runnable example](https://github.com/softwaremill/tapir/blob/master/examples/src/main/scala/sttp/tapir/examples/Http4sClientExample.scala)
for example usage.

## Limitations

- Multipart requests are not supported yet.
- WebSockets are not supported yet.
- Streaming capabilities:
- only `Fs2Streams` are supported at the moment.
2 changes: 1 addition & 1 deletion generated-doc/out/client/play.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Add the dependency:

```scala
"com.softwaremill.sttp.tapir" %% "tapir-play-client" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-play-client" % "0.18.0-M1"
```

To make requests using an endpoint definition using the [play client](https://github.com/playframework/play-ws), import:
Expand Down
2 changes: 1 addition & 1 deletion generated-doc/out/client/sttp.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Add the dependency:

```scala
"com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % "0.18.0-M1"
```

To make requests using an endpoint definition using the [sttp client](https://github.com/softwaremill/sttp), import:
Expand Down
4 changes: 2 additions & 2 deletions generated-doc/out/docs/asyncapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
To use, add the following dependencies:

```scala
"com.softwaremill.sttp.tapir" %% "tapir-asyncapi-docs" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-asyncapi-circe-yaml" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-asyncapi-docs" % "0.18.0-M1"
"com.softwaremill.sttp.tapir" %% "tapir-asyncapi-circe-yaml" % "0.18.0-M1"
```

Tapir contains a case class-based model of the asyncapi data structures in the `asyncapi/asyncapi-model` subproject (the
Expand Down
22 changes: 11 additions & 11 deletions generated-doc/out/docs/openapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
To use, add the following dependencies:

```scala
"com.softwaremill.sttp.tapir" %% "tapir-openapi-docs" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-openapi-circe-yaml" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-openapi-docs" % "0.18.0-M1"
"com.softwaremill.sttp.tapir" %% "tapir-openapi-circe-yaml" % "0.18.0-M1"
```

Tapir contains a case class-based model of the openapi data structures in the `openapi/openapi-model` subproject (the
Expand Down Expand Up @@ -81,29 +81,29 @@ akka-http/http4s routes for exposing documentation using [Swagger UI](https://sw

```scala
// Akka HTTP
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-akka-http" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-redoc-akka-http" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-akka-http" % "0.18.0-M1"
"com.softwaremill.sttp.tapir" %% "tapir-redoc-akka-http" % "0.18.0-M1"

// Finatra
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-finatra" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-finatra" % "0.18.0-M1"

// HTTP4S
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-http4s" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-redoc-http4s" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-http4s" % "0.18.0-M1"
"com.softwaremill.sttp.tapir" %% "tapir-redoc-http4s" % "0.18.0-M1"

// Play
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-play" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-redoc-play" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-play" % "0.18.0-M1"
"com.softwaremill.sttp.tapir" %% "tapir-redoc-play" % "0.18.0-M1"

// Vert.x
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-vertx" % "0.17.19"
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-vertx" % "0.18.0-M1"
```

Note: `tapir-swagger-ui-akka-http` transitively pulls some Akka modules in version 2.6. If you want to force
your own Akka version (for example 2.5), use sbt exclusion. Mind the Scala version in artifact name:

```scala
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-akka-http" % "0.17.19" exclude("com.typesafe.akka", "akka-stream_2.12")
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-akka-http" % "0.18.0-M1" exclude("com.typesafe.akka", "akka-stream_2.12")
```

Usage example for akka-http:
Expand Down
43 changes: 15 additions & 28 deletions generated-doc/out/endpoint/codecs.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,24 @@
# Codecs

## Mappings

The `Mapping[L, H]` trait defines a bi-directional mapping between values of type `L` and values of type `H`.

Low-level values of type `L` can be **decoded** to a higher-level value of type `H`. The decoding can fail; this is
represented by a result of type `DecodeResult.Failure`. Failures might occur due to format errors, wrong arity, exceptions,
or validation errors. Validators can be added through the `validate` method.

High-level values of type `H` can be **encoded** as a low-level value of type `L`.

Mappings can be chained using one of the `map` functions.

## Codecs

A `Codec[L, H, CF]` is a `Mapping[L, H]`, with additional meta-data: a schema and the format of the
low-level value (more on that below).
A `Codec[L, H, CF]` is a bi-directional mapping between low-level values of type `L` and high-level values of type `H`.
Low level values are formatted as `CF`. A codec also contains the schema of the high-level value, which is used for
validation and documentation.

There are built-in codecs for most common types such as `String`, `Int` etc. Codecs are usually defined as implicit
values and resolved implicitly when they are referenced. However, they can also be provided explicitly as needed.

For example, a `query[Int]("quantity")` specifies an input parameter which corresponds to the `quantity` query
parameter and will be mapped as an `Int`. There's an implicit `Codec[List[String], Int, TextPlain]` value that is
referenced by the `query` method (which is defined in the `sttp.tapir` package).
parameter and will be mapped as an `Int`. A query input requires a codec, where the low-level value is a `List[String]`
(representing potentially 0, one, or multiple parameters with the given name in the URL). Hence, an implicit
`Codec[List[String], Int, TextPlain]` value will be looked up when using the `query` method (which is defined in the
`sttp.tapir` package).

In this example, the low-level value is a `List[String]`, as a given query parameter can be absent, have a single or
many values. The high-level value is an `Int`. The codec will verify that there's a single query parameter with the
given name, and parse it as an int. If any of this fails, a failure will be reported.
In this example, the codec will verify that there's a single query parameter with the given name, and parse it as an
integer. If any of this fails, a failure will be reported.

In a server setting, if the value cannot be parsed as an int, a decoding failure is reported, and the endpoint
won't match the request, or a `400 Bad Request` response is returned (depending on configuration).

As each codec is also a `Mapping`, codecs can be used to map endpoint inputs and outputs. In such cases, the
additional meta-data (schema & format) isn't taken into account.

## Optional and multiple parameters

Some inputs/outputs allow optional, or multiple parameters:
Expand All @@ -56,16 +41,18 @@ Schema consists of:

* the schema type, which is one of the values defined in `SchemaType`, such as `SString`, `SBinary`, `SArray`
or `SProduct`/`SCoproduct` (for ADTs). This is the shape of the encoded value - as it is sent over the network
* meta-data: value optionality, description and low-level format name
* meta-data: value optionality, description, example, default value and low-level format name
* validation rules

For primitive types, the schema values are built-in, and defined in the `Schema` companion object.

The schema is left unchanged when mapping a codec, or an input/output, as the underlying representation of the value
doesn't change. However, schemas can be changed for individual inputs/outputs using the `.schema(Schema)` method.

When codecs are derived for complex types, e.g. for json mapping, schemas are looked up through implicit
`Schema[T]` values. See [custom types](customtypes.md) for more details.
Schemas are typically referenced indirectly through codecs, and are specified when the codec is created.

As part of deriving a codec, to support a custom or complex type (e.g. for json mapping), schemas can be looked up
implicitly and derived as well. See [custom types](customtypes.md) for more details.

## Codec format

Expand All @@ -79,7 +66,7 @@ specifies how to serialize a case class to plain text, and a different `Codec[St
how to serialize a case class to json. Both can be implicitly available without implicit resolution conflicts.

Different codec formats can be used in different contexts. When defining a path, query or header parameter, only a codec
with the `TextPlain` media type can be used. However, for bodies, any media types is allowed. For example, the
with the `TextPlain` media type can be used. However, for bodies, any media type is allowed. For example, the
input/output described by `jsonBody[T]` requires a json codec.

## Next
Expand Down
49 changes: 49 additions & 0 deletions generated-doc/out/endpoint/contenttype.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Content type

The endpoint's output content type is bound to the body outputs, that are specified for the endpoint (if any). The
[codec](codecs.md) of a body output contains a `CodecFormat`, which in turns contains the `MediaType` instance.

## Codec formats and server interpreters

Codec formats define the *default* media type, which will be set as the `Content-Type` header. However, any
user-provided value will override this default:

* dynamic content type, using `.out(header(HeaderNames.ContentType))`
* fixed content type, using e.g. `out(header(Header.contentType(MediaType.ApplicationJson)))`

## Multiple content types

Multiple, alternative content types can be specified using `oneOf`, similarly as when specifying [status code](statuscodes.md)
mappings.

On the server side, the appropriate mapping will be chosen using content negotiation, via the `Accept` header, using
the [configurable](../server/options.md) `ContentTypeInterceptor`. Note that both the base media type, and the charset
for text types are taken into account.

On the client side, the appropriate mapping will be chosen basing on the `Content-Type` header value.

For example:

```scala
import sttp.tapir._
import sttp.tapir.Codec.{JsonCodec, XmlCodec}
import sttp.model.StatusCode

case class Entity(name: String)
implicit val jsonCodecForOrganization: JsonCodec[Entity] = ???
implicit val xmlCodecForOrganization: XmlCodec[Entity] = ???

endpoint.out(
oneOf(
oneOfMapping(StatusCode.Ok, anyJsonBody[Entity]),
oneOfMapping(StatusCode.Ok, xmlBody[Entity]),
)
)
```

For details on how to create codes manually or derive them automatically, see [custom types](customtypes.md) and the
subsequent section on json.

## Next

Read on about [json support](json.md).
Loading

0 comments on commit 0868018

Please sign in to comment.