endpoint versioning
- Dominant language
- Rust
- Stars
- 5.1k
- Forks
- 329
- PR merge metrics
- No merged PRs in 30d
Description
Fastify has a fun way of [versioning endpoint](https://www.fastify.io/docs/latest/Routes/#version) using `Accept-Version` headers. The way it's declared looks like this:
```js
fastify.route({
method: 'GET',
url: '/',
version: '1.2.0',
handler: function (request, reply) {
reply.send({ hello: 'world' })
}
})
```
I was thinking this could be an interesting mechanism for Tide as well. What if we could switch logic based on API version headers like this:
```rust
let mut app = tide::new();
app.at("/user")
.get(|_| async move { Ok("user v2.3.0") })
.version("1.2.0").get(|_| async move { Ok("user v1.2.0") })
.version("2.3.0").get(|_| async move { Ok("user v2.3.0") });
```
The `version` param would switch based on the `Accept-Version` header and the `Accept: version="..."` header. We'd need to figure out the specifics of how to integrate, but I think this could provide an exciting mechanism for *versioned* endpoints. Which are something that are incredibly important for applications.
## Alternatives
The [APIs as infrastructure](https://stripe.com/blog/api-versioning) post by Stripe describes an interesting practice they use to provide upgrades to their APIs. This seems like a lot of work to maintain, but it's interesting to think how we could support it. One way we could perhaps do this is if we continued to lean into [`str::find`-like](https://doc.rust-lang.org/std/primitive.str.html#method.find) APIs: APIs that can take different types of arguments, including closures. Defining the API part of Stripe's upgrade logic could then in Tide be defined as:
```rust
user tide::version::Date;
let mut app = tide::new();
let latest = |_| async move { Ok("user v2.3.0") };
let change_body = |res| async move { res.set_body("user v1.2.0"); res };
app.at("/user")
.get(latest)
.version(Date::new("2020-01-30").get(|_| async move {
let res = latest().await?;
Ok(change_body(res).await?)
})
.version(Date::new("2020-03-30").get(latest);
```
This is a super rough sketch of what it could look like, but the overall point I'm trying to convey is that there's a way the design above could be made forward compatible with some really elaborate versioning schemes. Thanks!
Contributor guide
Assessment
This issue has not been assessed yet.