You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@couchdb.apache.org by Ilya Khlopotov <ii...@apache.org> on 2020/04/27 14:55:10 UTC

API versioning

Hello,

The topic of API versioning was brought in the [Streaming API in CouchDB 4.0](https://lists.apache.org/thread.html/ra8d16937cca332207d772844d2789f932fbc4572443a354391663b9c%40%3Cdev.couchdb.apache.org%3E) thread. The tread proposes to add new API endpoints to introduce a response structure change. The alternative approach could be to implement proper support for different API versions. 

It would benefit CouchDB project if we would have support for API versioning. Adding new endpoint is easy but it is very hard to deprecate or change the old ones. With proper API versioning we can avoid the need to rewrite all client applications at the same time. 

rnewson mentioned a good blog post about API versioning (https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/). The main idea of the blog post is. There is no perfect solution it would be the best to support all options so the user can choose which one to use.

In that spirit I propose to implement four different ways of specifying the API version (per endpoint):

- Path based -  `/_v{version_number}/{db}/_all_docs`
- Query parameter based  - `/{db}/_all_docs?_v={version_number}`
- Accept / Content-Type headers in the form of `application/couchdb; _v={version_number},application/json`
- Custom header - X-Couch-API: v2

The server would include response version in two places:
- Custom header - `X-Couch-API: v2`
- `Content-type: application/couchdb; _v={version_number},application/json`

Implementation wise it would go as follows:
1) we teach chttpd how to extract version (we set version to `1` if it is not specified)
2) we change arity of chttpd_handlers:url_handler/2 to pass API version
3) we would update functions in chttpd_httpd_handlers.erl to match on API version
  ```
  url_handler(<<"_all_dbs">>, 1)        -> fun chttpd_misc:handle_all_dbs_req/1;
  url_handler(<<"_all_dbs">>, 2)        -> fun chttpd_misc_v2:handle_all_dbs_req/1;
  ...
  db_handler(<<"_design">>, 1)       -> fun chttpd_db:handle_design_req/2;
  db_handler(<<"_design">>, 2)       -> fun chttpd_db_v2:handle_design_req/2;
  ...
  design_handler(<<"_view">>, 1)    -> fun chttpd_view:handle_view_req/3;
  design_handler(<<"_view">>, 2)    -> fun chttpd_view_v2:handle_view_req/3;
  ```
4) Modify chttpd:send_response to set response version (pass additional argument)

I don't expect the implementation to exceed 20 lines of code (not counting changes in arity of functions in chttpd_httpd_handlers).

Best regards,
iilyak 

Re: API versioning

Posted by Ilya Khlopotov <ii...@apache.org>.
> I'd rather see something where we can say "replace these things with newer versions,
fall back to v1 for the defaults". 

I thought we would use something like:
```
url_handler(<<"_all_dbs">>, 2)        -> fun handle_all_dbs_req/1;
url_handler(<<"_all_dbs">>, _)        -> fun chttpd_misc:handle_all_dbs_req/1;
```


On 2020/04/27 21:34:28, Paul Davis <pa...@gmail.com> wrote: 
> Overall this looks quite good to me. The only thing I'd say is that we
> should set our version much earlier so we can eventually rely on this
> for selecting an entirely independent implementation. Though that's
> not very pressing as once we have the concept embedded we can extend
> it as needed.
> 
> For this approach the only thing that concerns me is the way
> versioning is applied to individual URL handlers. I'd rather see
> something where we can say "replace these things with newer versions,
> fall back to v1 for the defaults". Though I couldn't figure out a very
> clean way to do that. The only thing I came up with was to have a
> chttpd_handlers_v2.erl service that's called and then
> chttpd_httpd_handlers_v2.erl that instead of defaulting to `no_match`
> would just forward to `chttpd_httpd_handlers:url_handler(Req)` or w/e
> it would be. But to be honest, I'm not super fond of that approach.
> 
> On Mon, Apr 27, 2020 at 2:41 PM Ilya Khlopotov <ii...@apache.org> wrote:
> >
> > I've implemented a PoC for versioned API https://github.com/apache/couchdb/pull/2832. The code is very ugly but it demonstrates how it could work.
> >
> > Best regards,
> > iilyak
> >
> > On 2020/04/27 14:55:10, Ilya Khlopotov <ii...@apache.org> wrote:
> > > Hello,
> > >
> > > The topic of API versioning was brought in the [Streaming API in CouchDB 4.0](https://lists.apache.org/thread.html/ra8d16937cca332207d772844d2789f932fbc4572443a354391663b9c%40%3Cdev.couchdb.apache.org%3E) thread. The tread proposes to add new API endpoints to introduce a response structure change. The alternative approach could be to implement proper support for different API versions.
> > >
> > > It would benefit CouchDB project if we would have support for API versioning. Adding new endpoint is easy but it is very hard to deprecate or change the old ones. With proper API versioning we can avoid the need to rewrite all client applications at the same time.
> > >
> > > rnewson mentioned a good blog post about API versioning (https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/). The main idea of the blog post is. There is no perfect solution it would be the best to support all options so the user can choose which one to use.
> > >
> > > In that spirit I propose to implement four different ways of specifying the API version (per endpoint):
> > >
> > > - Path based -  `/_v{version_number}/{db}/_all_docs`
> > > - Query parameter based  - `/{db}/_all_docs?_v={version_number}`
> > > - Accept / Content-Type headers in the form of `application/couchdb; _v={version_number},application/json`
> > > - Custom header - X-Couch-API: v2
> > >
> > > The server would include response version in two places:
> > > - Custom header - `X-Couch-API: v2`
> > > - `Content-type: application/couchdb; _v={version_number},application/json`
> > >
> > > Implementation wise it would go as follows:
> > > 1) we teach chttpd how to extract version (we set version to `1` if it is not specified)
> > > 2) we change arity of chttpd_handlers:url_handler/2 to pass API version
> > > 3) we would update functions in chttpd_httpd_handlers.erl to match on API version
> > >   ```
> > >   url_handler(<<"_all_dbs">>, 1)        -> fun chttpd_misc:handle_all_dbs_req/1;
> > >   url_handler(<<"_all_dbs">>, 2)        -> fun chttpd_misc_v2:handle_all_dbs_req/1;
> > >   ...
> > >   db_handler(<<"_design">>, 1)       -> fun chttpd_db:handle_design_req/2;
> > >   db_handler(<<"_design">>, 2)       -> fun chttpd_db_v2:handle_design_req/2;
> > >   ...
> > >   design_handler(<<"_view">>, 1)    -> fun chttpd_view:handle_view_req/3;
> > >   design_handler(<<"_view">>, 2)    -> fun chttpd_view_v2:handle_view_req/3;
> > >   ```
> > > 4) Modify chttpd:send_response to set response version (pass additional argument)
> > >
> > > I don't expect the implementation to exceed 20 lines of code (not counting changes in arity of functions in chttpd_httpd_handlers).
> > >
> > > Best regards,
> > > iilyak
> > >
> 

Re: API versioning

Posted by Ilya Khlopotov <ii...@apache.org>.
> application/couchdb needs registering, which is a faff, and isn't appropriate imo as we have many different formats of request and response, which a content-type ought to capture.

I could be wrong but  `application/couchdb; _v={version_number},application/json` should fall back to json if client don't understand `application/couchdb` (different alternatives separated by comma). 

> We could sink a lot of time into declaring content types for the all_docs response, the changes response, etc, or do something like like Accept: application/json; couch_version=2, 

If fallback to json works (and my reading of the spec tells me that it should) then we just prepend existent Content-Type with `application/couchdb; _v={version_number},`



On 2020/04/27 22:44:03, Robert Samuel Newson <rn...@apache.org> wrote: 
> As a general direction, I like it, but the specific example of accept/content doesn't sit right with me.
> 
> application/couchdb needs registering, which is a faff, and isn't appropriate imo as we have many different formats of request and response, which a content-type ought to capture. From the post I linked, it's the ".v2+json" bit that matters. We could sink a lot of time into declaring content types for the all_docs response, the changes response, etc, or do something like like Accept: application/json; couch_version=2, or simply omit this option and just have the path option, the query parameter option and the custom header option.
> 
> B.
> 
> > On 27 Apr 2020, at 22:34, Paul Davis <pa...@gmail.com> wrote:
> > 
> > Overall this looks quite good to me. The only thing I'd say is that we
> > should set our version much earlier so we can eventually rely on this
> > for selecting an entirely independent implementation. Though that's
> > not very pressing as once we have the concept embedded we can extend
> > it as needed.
> > 
> > For this approach the only thing that concerns me is the way
> > versioning is applied to individual URL handlers. I'd rather see
> > something where we can say "replace these things with newer versions,
> > fall back to v1 for the defaults". Though I couldn't figure out a very
> > clean way to do that. The only thing I came up with was to have a
> > chttpd_handlers_v2.erl service that's called and then
> > chttpd_httpd_handlers_v2.erl that instead of defaulting to `no_match`
> > would just forward to `chttpd_httpd_handlers:url_handler(Req)` or w/e
> > it would be. But to be honest, I'm not super fond of that approach.
> > 
> > On Mon, Apr 27, 2020 at 2:41 PM Ilya Khlopotov <ii...@apache.org> wrote:
> >> 
> >> I've implemented a PoC for versioned API https://github.com/apache/couchdb/pull/2832. The code is very ugly but it demonstrates how it could work.
> >> 
> >> Best regards,
> >> iilyak
> >> 
> >> On 2020/04/27 14:55:10, Ilya Khlopotov <ii...@apache.org> wrote:
> >>> Hello,
> >>> 
> >>> The topic of API versioning was brought in the [Streaming API in CouchDB 4.0](https://lists.apache.org/thread.html/ra8d16937cca332207d772844d2789f932fbc4572443a354391663b9c%40%3Cdev.couchdb.apache.org%3E) thread. The tread proposes to add new API endpoints to introduce a response structure change. The alternative approach could be to implement proper support for different API versions.
> >>> 
> >>> It would benefit CouchDB project if we would have support for API versioning. Adding new endpoint is easy but it is very hard to deprecate or change the old ones. With proper API versioning we can avoid the need to rewrite all client applications at the same time.
> >>> 
> >>> rnewson mentioned a good blog post about API versioning (https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/). The main idea of the blog post is. There is no perfect solution it would be the best to support all options so the user can choose which one to use.
> >>> 
> >>> In that spirit I propose to implement four different ways of specifying the API version (per endpoint):
> >>> 
> >>> - Path based -  `/_v{version_number}/{db}/_all_docs`
> >>> - Query parameter based  - `/{db}/_all_docs?_v={version_number}`
> >>> - Accept / Content-Type headers in the form of `application/couchdb; _v={version_number},application/json`
> >>> - Custom header - X-Couch-API: v2
> >>> 
> >>> The server would include response version in two places:
> >>> - Custom header - `X-Couch-API: v2`
> >>> - `Content-type: application/couchdb; _v={version_number},application/json`
> >>> 
> >>> Implementation wise it would go as follows:
> >>> 1) we teach chttpd how to extract version (we set version to `1` if it is not specified)
> >>> 2) we change arity of chttpd_handlers:url_handler/2 to pass API version
> >>> 3) we would update functions in chttpd_httpd_handlers.erl to match on API version
> >>>  ```
> >>>  url_handler(<<"_all_dbs">>, 1)        -> fun chttpd_misc:handle_all_dbs_req/1;
> >>>  url_handler(<<"_all_dbs">>, 2)        -> fun chttpd_misc_v2:handle_all_dbs_req/1;
> >>>  ...
> >>>  db_handler(<<"_design">>, 1)       -> fun chttpd_db:handle_design_req/2;
> >>>  db_handler(<<"_design">>, 2)       -> fun chttpd_db_v2:handle_design_req/2;
> >>>  ...
> >>>  design_handler(<<"_view">>, 1)    -> fun chttpd_view:handle_view_req/3;
> >>>  design_handler(<<"_view">>, 2)    -> fun chttpd_view_v2:handle_view_req/3;
> >>>  ```
> >>> 4) Modify chttpd:send_response to set response version (pass additional argument)
> >>> 
> >>> I don't expect the implementation to exceed 20 lines of code (not counting changes in arity of functions in chttpd_httpd_handlers).
> >>> 
> >>> Best regards,
> >>> iilyak
> >>> 
> 
> 

Re: API versioning

Posted by Paul Davis <pa...@gmail.com>.
I didn’t read that hard. If memory serves its supposed to be something like
application/json;couchdb._v2 which shouldn’t require registration.
Regardless, being wrong three ways instead of four is fine by me (HIBP
wrong to be clear).

On Mon, Apr 27, 2020 at 5:44 PM Robert Samuel Newson <rn...@apache.org>
wrote:

> As a general direction, I like it, but the specific example of
> accept/content doesn't sit right with me.
>
> application/couchdb needs registering, which is a faff, and isn't
> appropriate imo as we have many different formats of request and response,
> which a content-type ought to capture. From the post I linked, it's the
> ".v2+json" bit that matters. We could sink a lot of time into declaring
> content types for the all_docs response, the changes response, etc, or do
> something like like Accept: application/json; couch_version=2, or simply
> omit this option and just have the path option, the query parameter option
> and the custom header option.
>
> B.
>
> > On 27 Apr 2020, at 22:34, Paul Davis <pa...@gmail.com>
> wrote:
> >
> > Overall this looks quite good to me. The only thing I'd say is that we
> > should set our version much earlier so we can eventually rely on this
> > for selecting an entirely independent implementation. Though that's
> > not very pressing as once we have the concept embedded we can extend
> > it as needed.
> >
> > For this approach the only thing that concerns me is the way
> > versioning is applied to individual URL handlers. I'd rather see
> > something where we can say "replace these things with newer versions,
> > fall back to v1 for the defaults". Though I couldn't figure out a very
> > clean way to do that. The only thing I came up with was to have a
> > chttpd_handlers_v2.erl service that's called and then
> > chttpd_httpd_handlers_v2.erl that instead of defaulting to `no_match`
> > would just forward to `chttpd_httpd_handlers:url_handler(Req)` or w/e
> > it would be. But to be honest, I'm not super fond of that approach.
> >
> > On Mon, Apr 27, 2020 at 2:41 PM Ilya Khlopotov <ii...@apache.org>
> wrote:
> >>
> >> I've implemented a PoC for versioned API
> https://github.com/apache/couchdb/pull/2832. The code is very ugly but it
> demonstrates how it could work.
> >>
> >> Best regards,
> >> iilyak
> >>
> >> On 2020/04/27 14:55:10, Ilya Khlopotov <ii...@apache.org> wrote:
> >>> Hello,
> >>>
> >>> The topic of API versioning was brought in the [Streaming API in
> CouchDB 4.0](
> https://lists.apache.org/thread.html/ra8d16937cca332207d772844d2789f932fbc4572443a354391663b9c%40%3Cdev.couchdb.apache.org%3E)
> thread. The tread proposes to add new API endpoints to introduce a response
> structure change. The alternative approach could be to implement proper
> support for different API versions.
> >>>
> >>> It would benefit CouchDB project if we would have support for API
> versioning. Adding new endpoint is easy but it is very hard to deprecate or
> change the old ones. With proper API versioning we can avoid the need to
> rewrite all client applications at the same time.
> >>>
> >>> rnewson mentioned a good blog post about API versioning (
> https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/). The
> main idea of the blog post is. There is no perfect solution it would be the
> best to support all options so the user can choose which one to use.
> >>>
> >>> In that spirit I propose to implement four different ways of
> specifying the API version (per endpoint):
> >>>
> >>> - Path based -  `/_v{version_number}/{db}/_all_docs`
> >>> - Query parameter based  - `/{db}/_all_docs?_v={version_number}`
> >>> - Accept / Content-Type headers in the form of `application/couchdb;
> _v={version_number},application/json`
> >>> - Custom header - X-Couch-API: v2
> >>>
> >>> The server would include response version in two places:
> >>> - Custom header - `X-Couch-API: v2`
> >>> - `Content-type: application/couchdb;
> _v={version_number},application/json`
> >>>
> >>> Implementation wise it would go as follows:
> >>> 1) we teach chttpd how to extract version (we set version to `1` if it
> is not specified)
> >>> 2) we change arity of chttpd_handlers:url_handler/2 to pass API version
> >>> 3) we would update functions in chttpd_httpd_handlers.erl to match on
> API version
> >>>  ```
> >>>  url_handler(<<"_all_dbs">>, 1)        -> fun
> chttpd_misc:handle_all_dbs_req/1;
> >>>  url_handler(<<"_all_dbs">>, 2)        -> fun
> chttpd_misc_v2:handle_all_dbs_req/1;
> >>>  ...
> >>>  db_handler(<<"_design">>, 1)       -> fun
> chttpd_db:handle_design_req/2;
> >>>  db_handler(<<"_design">>, 2)       -> fun
> chttpd_db_v2:handle_design_req/2;
> >>>  ...
> >>>  design_handler(<<"_view">>, 1)    -> fun
> chttpd_view:handle_view_req/3;
> >>>  design_handler(<<"_view">>, 2)    -> fun
> chttpd_view_v2:handle_view_req/3;
> >>>  ```
> >>> 4) Modify chttpd:send_response to set response version (pass
> additional argument)
> >>>
> >>> I don't expect the implementation to exceed 20 lines of code (not
> counting changes in arity of functions in chttpd_httpd_handlers).
> >>>
> >>> Best regards,
> >>> iilyak
> >>>
>
>

Re: API versioning

Posted by Robert Samuel Newson <rn...@apache.org>.
As a general direction, I like it, but the specific example of accept/content doesn't sit right with me.

application/couchdb needs registering, which is a faff, and isn't appropriate imo as we have many different formats of request and response, which a content-type ought to capture. From the post I linked, it's the ".v2+json" bit that matters. We could sink a lot of time into declaring content types for the all_docs response, the changes response, etc, or do something like like Accept: application/json; couch_version=2, or simply omit this option and just have the path option, the query parameter option and the custom header option.

B.

> On 27 Apr 2020, at 22:34, Paul Davis <pa...@gmail.com> wrote:
> 
> Overall this looks quite good to me. The only thing I'd say is that we
> should set our version much earlier so we can eventually rely on this
> for selecting an entirely independent implementation. Though that's
> not very pressing as once we have the concept embedded we can extend
> it as needed.
> 
> For this approach the only thing that concerns me is the way
> versioning is applied to individual URL handlers. I'd rather see
> something where we can say "replace these things with newer versions,
> fall back to v1 for the defaults". Though I couldn't figure out a very
> clean way to do that. The only thing I came up with was to have a
> chttpd_handlers_v2.erl service that's called and then
> chttpd_httpd_handlers_v2.erl that instead of defaulting to `no_match`
> would just forward to `chttpd_httpd_handlers:url_handler(Req)` or w/e
> it would be. But to be honest, I'm not super fond of that approach.
> 
> On Mon, Apr 27, 2020 at 2:41 PM Ilya Khlopotov <ii...@apache.org> wrote:
>> 
>> I've implemented a PoC for versioned API https://github.com/apache/couchdb/pull/2832. The code is very ugly but it demonstrates how it could work.
>> 
>> Best regards,
>> iilyak
>> 
>> On 2020/04/27 14:55:10, Ilya Khlopotov <ii...@apache.org> wrote:
>>> Hello,
>>> 
>>> The topic of API versioning was brought in the [Streaming API in CouchDB 4.0](https://lists.apache.org/thread.html/ra8d16937cca332207d772844d2789f932fbc4572443a354391663b9c%40%3Cdev.couchdb.apache.org%3E) thread. The tread proposes to add new API endpoints to introduce a response structure change. The alternative approach could be to implement proper support for different API versions.
>>> 
>>> It would benefit CouchDB project if we would have support for API versioning. Adding new endpoint is easy but it is very hard to deprecate or change the old ones. With proper API versioning we can avoid the need to rewrite all client applications at the same time.
>>> 
>>> rnewson mentioned a good blog post about API versioning (https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/). The main idea of the blog post is. There is no perfect solution it would be the best to support all options so the user can choose which one to use.
>>> 
>>> In that spirit I propose to implement four different ways of specifying the API version (per endpoint):
>>> 
>>> - Path based -  `/_v{version_number}/{db}/_all_docs`
>>> - Query parameter based  - `/{db}/_all_docs?_v={version_number}`
>>> - Accept / Content-Type headers in the form of `application/couchdb; _v={version_number},application/json`
>>> - Custom header - X-Couch-API: v2
>>> 
>>> The server would include response version in two places:
>>> - Custom header - `X-Couch-API: v2`
>>> - `Content-type: application/couchdb; _v={version_number},application/json`
>>> 
>>> Implementation wise it would go as follows:
>>> 1) we teach chttpd how to extract version (we set version to `1` if it is not specified)
>>> 2) we change arity of chttpd_handlers:url_handler/2 to pass API version
>>> 3) we would update functions in chttpd_httpd_handlers.erl to match on API version
>>>  ```
>>>  url_handler(<<"_all_dbs">>, 1)        -> fun chttpd_misc:handle_all_dbs_req/1;
>>>  url_handler(<<"_all_dbs">>, 2)        -> fun chttpd_misc_v2:handle_all_dbs_req/1;
>>>  ...
>>>  db_handler(<<"_design">>, 1)       -> fun chttpd_db:handle_design_req/2;
>>>  db_handler(<<"_design">>, 2)       -> fun chttpd_db_v2:handle_design_req/2;
>>>  ...
>>>  design_handler(<<"_view">>, 1)    -> fun chttpd_view:handle_view_req/3;
>>>  design_handler(<<"_view">>, 2)    -> fun chttpd_view_v2:handle_view_req/3;
>>>  ```
>>> 4) Modify chttpd:send_response to set response version (pass additional argument)
>>> 
>>> I don't expect the implementation to exceed 20 lines of code (not counting changes in arity of functions in chttpd_httpd_handlers).
>>> 
>>> Best regards,
>>> iilyak
>>> 


Re: API versioning

Posted by Paul Davis <pa...@gmail.com>.
Overall this looks quite good to me. The only thing I'd say is that we
should set our version much earlier so we can eventually rely on this
for selecting an entirely independent implementation. Though that's
not very pressing as once we have the concept embedded we can extend
it as needed.

For this approach the only thing that concerns me is the way
versioning is applied to individual URL handlers. I'd rather see
something where we can say "replace these things with newer versions,
fall back to v1 for the defaults". Though I couldn't figure out a very
clean way to do that. The only thing I came up with was to have a
chttpd_handlers_v2.erl service that's called and then
chttpd_httpd_handlers_v2.erl that instead of defaulting to `no_match`
would just forward to `chttpd_httpd_handlers:url_handler(Req)` or w/e
it would be. But to be honest, I'm not super fond of that approach.

On Mon, Apr 27, 2020 at 2:41 PM Ilya Khlopotov <ii...@apache.org> wrote:
>
> I've implemented a PoC for versioned API https://github.com/apache/couchdb/pull/2832. The code is very ugly but it demonstrates how it could work.
>
> Best regards,
> iilyak
>
> On 2020/04/27 14:55:10, Ilya Khlopotov <ii...@apache.org> wrote:
> > Hello,
> >
> > The topic of API versioning was brought in the [Streaming API in CouchDB 4.0](https://lists.apache.org/thread.html/ra8d16937cca332207d772844d2789f932fbc4572443a354391663b9c%40%3Cdev.couchdb.apache.org%3E) thread. The tread proposes to add new API endpoints to introduce a response structure change. The alternative approach could be to implement proper support for different API versions.
> >
> > It would benefit CouchDB project if we would have support for API versioning. Adding new endpoint is easy but it is very hard to deprecate or change the old ones. With proper API versioning we can avoid the need to rewrite all client applications at the same time.
> >
> > rnewson mentioned a good blog post about API versioning (https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/). The main idea of the blog post is. There is no perfect solution it would be the best to support all options so the user can choose which one to use.
> >
> > In that spirit I propose to implement four different ways of specifying the API version (per endpoint):
> >
> > - Path based -  `/_v{version_number}/{db}/_all_docs`
> > - Query parameter based  - `/{db}/_all_docs?_v={version_number}`
> > - Accept / Content-Type headers in the form of `application/couchdb; _v={version_number},application/json`
> > - Custom header - X-Couch-API: v2
> >
> > The server would include response version in two places:
> > - Custom header - `X-Couch-API: v2`
> > - `Content-type: application/couchdb; _v={version_number},application/json`
> >
> > Implementation wise it would go as follows:
> > 1) we teach chttpd how to extract version (we set version to `1` if it is not specified)
> > 2) we change arity of chttpd_handlers:url_handler/2 to pass API version
> > 3) we would update functions in chttpd_httpd_handlers.erl to match on API version
> >   ```
> >   url_handler(<<"_all_dbs">>, 1)        -> fun chttpd_misc:handle_all_dbs_req/1;
> >   url_handler(<<"_all_dbs">>, 2)        -> fun chttpd_misc_v2:handle_all_dbs_req/1;
> >   ...
> >   db_handler(<<"_design">>, 1)       -> fun chttpd_db:handle_design_req/2;
> >   db_handler(<<"_design">>, 2)       -> fun chttpd_db_v2:handle_design_req/2;
> >   ...
> >   design_handler(<<"_view">>, 1)    -> fun chttpd_view:handle_view_req/3;
> >   design_handler(<<"_view">>, 2)    -> fun chttpd_view_v2:handle_view_req/3;
> >   ```
> > 4) Modify chttpd:send_response to set response version (pass additional argument)
> >
> > I don't expect the implementation to exceed 20 lines of code (not counting changes in arity of functions in chttpd_httpd_handlers).
> >
> > Best regards,
> > iilyak
> >

Re: API versioning

Posted by Ilya Khlopotov <ii...@apache.org>.
I've implemented a PoC for versioned API https://github.com/apache/couchdb/pull/2832. The code is very ugly but it demonstrates how it could work.

Best regards,
iilyak

On 2020/04/27 14:55:10, Ilya Khlopotov <ii...@apache.org> wrote: 
> Hello,
> 
> The topic of API versioning was brought in the [Streaming API in CouchDB 4.0](https://lists.apache.org/thread.html/ra8d16937cca332207d772844d2789f932fbc4572443a354391663b9c%40%3Cdev.couchdb.apache.org%3E) thread. The tread proposes to add new API endpoints to introduce a response structure change. The alternative approach could be to implement proper support for different API versions. 
> 
> It would benefit CouchDB project if we would have support for API versioning. Adding new endpoint is easy but it is very hard to deprecate or change the old ones. With proper API versioning we can avoid the need to rewrite all client applications at the same time. 
> 
> rnewson mentioned a good blog post about API versioning (https://www.troyhunt.com/your-api-versioning-is-wrong-which-is/). The main idea of the blog post is. There is no perfect solution it would be the best to support all options so the user can choose which one to use.
> 
> In that spirit I propose to implement four different ways of specifying the API version (per endpoint):
> 
> - Path based -  `/_v{version_number}/{db}/_all_docs`
> - Query parameter based  - `/{db}/_all_docs?_v={version_number}`
> - Accept / Content-Type headers in the form of `application/couchdb; _v={version_number},application/json`
> - Custom header - X-Couch-API: v2
> 
> The server would include response version in two places:
> - Custom header - `X-Couch-API: v2`
> - `Content-type: application/couchdb; _v={version_number},application/json`
> 
> Implementation wise it would go as follows:
> 1) we teach chttpd how to extract version (we set version to `1` if it is not specified)
> 2) we change arity of chttpd_handlers:url_handler/2 to pass API version
> 3) we would update functions in chttpd_httpd_handlers.erl to match on API version
>   ```
>   url_handler(<<"_all_dbs">>, 1)        -> fun chttpd_misc:handle_all_dbs_req/1;
>   url_handler(<<"_all_dbs">>, 2)        -> fun chttpd_misc_v2:handle_all_dbs_req/1;
>   ...
>   db_handler(<<"_design">>, 1)       -> fun chttpd_db:handle_design_req/2;
>   db_handler(<<"_design">>, 2)       -> fun chttpd_db_v2:handle_design_req/2;
>   ...
>   design_handler(<<"_view">>, 1)    -> fun chttpd_view:handle_view_req/3;
>   design_handler(<<"_view">>, 2)    -> fun chttpd_view_v2:handle_view_req/3;
>   ```
> 4) Modify chttpd:send_response to set response version (pass additional argument)
> 
> I don't expect the implementation to exceed 20 lines of code (not counting changes in arity of functions in chttpd_httpd_handlers).
> 
> Best regards,
> iilyak 
>