Hi, I''m struggling with the backward compatibility of a RESTful interface. I can''t find any documentation on the standard way to solving this. I know that as long as you only extend the RESTful interface there is no backward compatibility issue, but I don''t believe that is a very realistic situation (I refactor a lot). Say you want to change an attribute''s name, how would you solve this? For the solution I''ve got the following assumptions: - The interface version should not be placed in the URL (i.e. www.mydomain.com/v2/books). The URL defines the resource, the interface version is not part of the resource in my opinion. - The interface version should not be placed in the parameters (i.e. www.mydomain.com/books?version=2). This is an option, but it would pollute my urls. - Only the first interface version can be defaulted, because changing the default will break existing client implementations using the previous default. So this default is not really usefull in the long run, since only version 1 can use it. But at least this would allow people to leave out the interface version description, if they don''t have to be backward compatible. I believe that an ideal solution to this would be to place the version in the HTTP headers. Only there is no standard defined for it as far as I can see. But it would be like the following: POST www.mydomain.com/books HTTP/1.1 Interface-Version: 2 Content-Type: application/xml Accept: application/xml <book>....</book> For the controller we could then apply a before_filter which rewrites the param hash to the latest interface version (after determining the used interface version from the header). The latest interface definition is then used in the controller actions. I think this can be quite clean. Does anybody have know of a standard solution for this problem? Regards, Bas --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
[edit_by_author] The third assumption is incorrect. You must default the last version, otherwise the non webservice clients (browsers etc.) would get into trouble. But this does create another issue that every webservice client must use the version number from the start, also for version 1. [/edit_by_author] On Feb 7, 5:23 pm, Bas van Westing <basvanwest...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Hi, > > I''m struggling with the backward compatibility of a RESTful interface. > I can''t find any documentation on the standard way to solving this. I > know that as long as you only extend the RESTful interface there is no > backward compatibility issue, but I don''t believe that is a very > realistic situation (I refactor a lot). Say you want to change an > attribute''s name, how would you solve this? > > For the solution I''ve got the following assumptions: > - The interface version should not be placed in the URL (i.e.www.mydomain.com/v2/books). The URL defines the resource, the > interface version is not part of the resource in my opinion. > - The interface version should not be placed in the parameters (i.e.www.mydomain.com/books?version=2). This is an option, but it would > pollute my urls. > - Only the first interface version can be defaulted, because changing > the default will break existing client implementations using the > previous default. So this default is not really usefull in the long > run, since only version 1 can use it. But at least this would allow > people to leave out the interface version description, if they don''t > have to be backward compatible. > > I believe that an ideal solution to this would be to place the version > in the HTTP headers. Only there is no standard defined for it as far > as I can see. But it would be like the following: > > POSTwww.mydomain.com/booksHTTP/1.1 > Interface-Version: 2 > Content-Type: application/xml > Accept: application/xml > > <book>....</book> > > For the controller we could then apply a before_filter which rewrites > the param hash to the latest interface version (after determining the > used interface version from the header). The latest interface > definition is then used in the controller actions. > > I think this can be quite clean. > Does anybody have know of a standard solution for this problem? > > Regards, Bas--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
I don''t think you should bother with version numbers, it''s RPC-like. Why do you want to keep an old version of the service alive? I would just force the clients to an update, or provide a new service for the updated resources. But if you want to use a version number, both examples are equal. All the information that the server needs to fulfill the request should be in the path. It doesn''t matter much if it''s /v2/books or books?v=2. I would just fork the project and have it running on diffrent domains, or rewrite the URL on the incoming webserver to point to different applications. Maintaining different versions off an API is going to be hell. On Feb 7, 2008 5:48 PM, Bas van Westing <basvanwesting-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > [edit_by_author] > The third assumption is incorrect. You must default the last version, > otherwise the non webservice clients (browsers etc.) would get into > trouble. But this does create another issue that every webservice > client must use the version number from the start, also for version 1. > [/edit_by_author] > > On Feb 7, 5:23 pm, Bas van Westing <basvanwest...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > Hi, > > > > I''m struggling with the backward compatibility of a RESTful interface. > > I can''t find any documentation on the standard way to solving this. I > > know that as long as you only extend the RESTful interface there is no > > backward compatibility issue, but I don''t believe that is a very > > realistic situation (I refactor a lot). Say you want to change an > > attribute''s name, how would you solve this? > > > > For the solution I''ve got the following assumptions: > > - The interface version should not be placed in the URL ( > i.e.www.mydomain.com/v2/books). The URL defines the resource, the > > interface version is not part of the resource in my opinion. > > - The interface version should not be placed in the parameters ( > i.e.www.mydomain.com/books?version=2). This is an option, but it would > > pollute my urls. > > - Only the first interface version can be defaulted, because changing > > the default will break existing client implementations using the > > previous default. So this default is not really usefull in the long > > run, since only version 1 can use it. But at least this would allow > > people to leave out the interface version description, if they don''t > > have to be backward compatible. > > > > I believe that an ideal solution to this would be to place the version > > in the HTTP headers. Only there is no standard defined for it as far > > as I can see. But it would be like the following: > > > > POSTwww.mydomain.com/booksHTTP/1.1 > > Interface-Version: 2 > > Content-Type: application/xml > > Accept: application/xml > > > > <book>....</book> > > > > For the controller we could then apply a before_filter which rewrites > > the param hash to the latest interface version (after determining the > > used interface version from the header). The latest interface > > definition is then used in the controller actions. > > > > I think this can be quite clean. > > Does anybody have know of a standard solution for this problem? > > > > Regards, Bas > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hi Matthijs, I''m afraid I cannot just force my paying customers to change their interfaces. I don''t think you ever can... in real life (only the planning and synchronized execution alone would give severe headaches). Anyway I did some more reading and I think the HTTP Header option is not so bad. There are X-Headers which basically are free form. So the header would look like the following: POST /books HTTP/1.1 User-Agent: ApacheBench/2.0.40-dev Authorization: Basic YmFzOnRlc3QHost: www.mydomain.com X-Interface-Version: 2 Content-Type: application/xml Accept: application/xml The before_filter is really not so hard to implement. And making the interface upgrades cascaded (in case of a version delta > 1) will only require me to add a single mapping for each new interface version, only defining the mapping with the previous version. Keeping in mind that interface versions are only increased is case of a non- incremental extension, I won''t expect to ever go beyond more than 3 interface versions in practice. So I think your statement that "Maintaining different versions off an API is going to be hell." is not necessarily the case. As I see things now, the backward compatibility issue with RESTful interfaces is solvable nicely in Ruby on Rails (or in general). The only remaining question is: Am I doing something really non- standard and is there a better solution? Regards, Bas van Westing On Feb 7, 6:55 pm, "Matthijs Langenberg" <mlangenb...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I don''t think you should bother with version numbers, it''s RPC-like. Why do > you want to keep an old version of the service alive? I would just force the > clients to an update, or provide a new service for the updated resources. But > if you want to use a version number, both examples are equal. All the > information that the server needs to fulfill the request should be in the > path. It doesn''t matter much if it''s /v2/books or books?v=2. > > I would just fork the project and have it running on diffrent domains, or > rewrite the URL on the incoming webserver to point to different > applications. > Maintaining different versions off an API is going to be hell. > > On Feb 7, 2008 5:48 PM, Bas van Westing <basvanwest...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > [edit_by_author] > > The third assumption is incorrect. You must default the last version, > > otherwise the non webservice clients (browsers etc.) would get into > > trouble. But this does create another issue that every webservice > > client must use the version number from the start, also for version 1. > > [/edit_by_author] > > > On Feb 7, 5:23 pm, Bas van Westing <basvanwest...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Hi, > > > > I''m struggling with the backward compatibility of a RESTful interface. > > > I can''t find any documentation on the standard way to solving this. I > > > know that as long as you only extend the RESTful interface there is no > > > backward compatibility issue, but I don''t believe that is a very > > > realistic situation (I refactor a lot). Say you want to change an > > > attribute''s name, how would you solve this? > > > > For the solution I''ve got the following assumptions: > > > - The interface version should not be placed in the URL ( > > i.e.www.mydomain.com/v2/books). The URL defines the resource, the > > > interface version is not part of the resource in my opinion. > > > - The interface version should not be placed in the parameters ( > > i.e.www.mydomain.com/books?version=2). This is an option, but it would > > > pollute my urls. > > > - Only the first interface version can be defaulted, because changing > > > the default will break existing client implementations using the > > > previous default. So this default is not really usefull in the long > > > run, since only version 1 can use it. But at least this would allow > > > people to leave out the interface version description, if they don''t > > > have to be backward compatible. > > > > I believe that an ideal solution to this would be to place the version > > > in the HTTP headers. Only there is no standard defined for it as far > > > as I can see. But it would be like the following: > > > > POSTwww.mydomain.com/booksHTTP/1.1 > > > Interface-Version: 2 > > > Content-Type: application/xml > > > Accept: application/xml > > > > <book>....</book> > > > > For the controller we could then apply a before_filter which rewrites > > > the param hash to the latest interface version (after determining the > > > used interface version from the header). The latest interface > > > definition is then used in the controller actions. > > > > I think this can be quite clean. > > > Does anybody have know of a standard solution for this problem? > > > > Regards, Bas--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---