-
Notifications
You must be signed in to change notification settings - Fork 427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add docs for delimited path parameters #4079
Changes from 1 commit
3d1ef6f
62378c6
078664b
b251615
6126840
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -88,6 +88,89 @@ Different codec formats can be used in different contexts. When defining a path, | |||||
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. | ||||||
|
||||||
## Handling Delimited Path Parameters | ||||||
|
||||||
Tapir allows you to handle complex path parameters, such as lists of custom types separated by delimiters (e.g., commas). | ||||||
This can be achieved using Codec.delimited, which facilitates the serialization and deserialization of delimited lists | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
within path segments. | ||||||
|
||||||
### Use Case | ||||||
Suppose you want to define an endpoint that accepts a list of names as a comma-separated path parameter. Each name should | ||||||
adhere to a specific pattern (e.g., only uppercase letters). | ||||||
|
||||||
### Implementation Steps: | ||||||
|
||||||
### 1. Define the Custom Type and Validator | ||||||
Start by defining your custom type and the associated validator to enforce the desired pattern. | ||||||
|
||||||
```scala | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this can probably be compilation-checked? you can do this by adding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I ran that locally and got a success but needed to have all the code and imports together. I left |
||||||
import sttp.tapir._ | ||||||
import sttp.tapir.generic.auto._ | ||||||
import sttp.tapir.Codec | ||||||
import sttp.tapir.Validator | ||||||
|
||||||
case class Name(value: String) | ||||||
|
||||||
// Validator to ensure names consist of uppercase letters only | ||||||
val nameValidator: Validator[String] = Validator.pattern("^[A-Z]+$") | ||||||
``` | ||||||
|
||||||
### 2. Create Codecs for the Custom Type and Delimited List | ||||||
Utilize `Codec.parsedString` for individual `Name` instances and `Codec.delimited` for handling the list. | ||||||
|
||||||
```scala | ||||||
// Codec for single Name | ||||||
given Codec[String, Name, TextPlain] = Codec.parsedString(Name.apply) | ||||||
.validate(nameValidator.contramap(_.value)) | ||||||
|
||||||
// Codec for a list of Names, delimited by commas | ||||||
given Codec[String, Delimited[",", Name], TextPlain] = Codec.delimited | ||||||
``` | ||||||
|
||||||
### 3. Define the Endpoint with Delimited Path Parameter | ||||||
Incorporate the delimited codec into your endpoint definition to handle the list of names in the path. | ||||||
|
||||||
```scala | ||||||
val getUserEndpoint = | ||||||
endpoint.get | ||||||
.in("user" / path[List[Name]]("id")) | ||||||
.out(stringBody) | ||||||
``` | ||||||
|
||||||
### 4. Generated OpenAPI Schema | ||||||
When you generate the OpenAPI documentation for this endpoint, the schema for the `id` path parameter will | ||||||
correctly reflect it as an array with the specified pattern for each item. | ||||||
|
||||||
```yaml | ||||||
paths: | ||||||
/user/{id}: | ||||||
get: | ||||||
operationId: getUserId | ||||||
parameters: | ||||||
- name: id | ||||||
in: path | ||||||
required: true | ||||||
schema: | ||||||
type: array | ||||||
items: | ||||||
type: string | ||||||
pattern: ^[A-Z]+$ | ||||||
``` | ||||||
|
||||||
### Explanation | ||||||
- `Codec.parsedString`: Transforms a `String` into a custom type (`Name`) and vice versa. It also applies validation to | ||||||
ensure each `Name` adheres to the specified pattern. | ||||||
- `Codec.delimited`: Handles the serialization and deserialization of a delimited list (e.g., comma-separated) of the | ||||||
custom type. By specifying `Delimited[",", Name]`, Tapir knows how to split and join the list based on the delimiter. | ||||||
- Endpoint Definition: The `path[List[Name]]("id")` indicates that the id path parameter should be treated as a list of | ||||||
`Name` objects, utilizing the previously defined codecs. | ||||||
|
||||||
### Validation | ||||||
Validators play a crucial role in ensuring that each element within the delimited list meets the required criteria. In | ||||||
this example, `nameValidator` ensures that each `Name` consists solely of uppercase letters. Tapir applies this validation | ||||||
to each element in the list, providing robust input validation. | ||||||
|
||||||
|
||||||
## Next | ||||||
|
||||||
Read on about [custom types](customtypes.md). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the proposal! I think I'd suggest moving it to a top-level page linked in the
How To
section. The "codec" section over here is more of a reference, and this describes a specific use-caseThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the
How To
section references links to.scala
files. To follow that same pattern I'm thinking I'll convert this toDelimitedPathParameterExample.scala
and add code comments. Unless I'm missing something and I can just attach a.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh no, I meant a regular .md page. There are links to examples in the
Examples
section, but you should be able to add a link here: https://github.com/softwaremill/tapir/blob/master/doc/index.md?plain=1#L158 to the new pageThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't too sure where it should be housed so I made a dir for how-tos and placed it in there. Let me know if I should change that or rename it.