cremes.devlist-ee4meeAH724@public.gmane.org
2006-Nov-22 16:17 UTC
RESTful web service design question
I''m working on a Rails app that needs to expose a RESTful web service. I''m curious to know some of the best practices as it relates to RESTful API design. Let''s say I have a set of related objects on the server side. I''ll use the venerable subscribers, subscriptions and magazines example to lay it out. class Subscriber < AR has_many :subscriptions has_many :magazines, :through => :subscriptions end class Subscription < AR belongs_to :subscriber belongs_to :magazine end class Magazine < AR has_many :subscriptions has_many :subscribers, :through => :subscriptions end Does it make sense for this relationship to get exposed through the REST API? Put another way, does it make sense to support a GET operation where the URL looks like this? http://example.com/subscribers/3/subscriptions/19/magazines/12.xml Or, should the API force smaller steps such that a web service client needs to do multiple GETs like: http://example.com/subscribers/3.xml # returns a list of subscriptions for subscriber.id == 3 http://example.com/subscriptions/19.xml # returns a list of magazines for subscriptions.id == 19 (already "constrained" by the previous call to subscribers) http://example.com/magazines/12.xml # id == 12 came from the prior call to #subscriptions I know the API is stateless so any "state" maintained between calls has to be represented in the URL, but it just seems wrong to me that the object relationships get exposed in the URL with the long, single call. It seems cleaner to force the web service client to break it into separate ones for each resource. The API also needs to support POST and PUT operations on the same set of related objects. Oh, and let''s assume there is some (at minimum) Basic HTTP Authentication going on here which is picked up by the Rails app to restrict the possible domain of retrievable db records. Thoughts? cr --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
stevemolitor-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2006-Nov-22 16:26 UTC
Re: RESTful web service design question
> Or, should the API force smaller steps such that a web service client needs to do multiple GETs like: > http://example.com/subscribers/3.xml # returns a list of subscriptions for subscriber.id == 3 > > http://example.com/subscriptions/19.xml # returns a list of magazines for subscriptions.id == 19 (already "constrained" by the previous call to subscribers) > > http://example.com/magazines/12.xml # id == 12 came from the prior call to #subscriptions > > I know the API is stateless so any "state" maintained between calls has to be represented in the URL, but it just seems wrong to me that the object relationships get exposed in the URL with the long, single call. It seems cleaner to force the web service client to break it into separate ones for each resource.I''m a REST newbie as well. I''m looking forward to seeing other''s responses to this question. However I don''t see anything inherently un-RESTful about your second approch, as long as the first request returns machine navigatable links to the sub-items. That way it''s still stateless. For example, http://example.com/subscribers/3.xml might return something like this: <subscriber id="3"> <name>bob</name> <subscriptions> <subscription id="14" xlink:href="http://www.magazines.com/subscriptions/14"/> <subscription id="19" xlink:href="http://www.magazines.com/subscriptions/19"/> </subscriptions> </subscriber> And so on. Steve --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
On 11/22/06, cremes.devlist-ee4meeAH724@public.gmane.org <cremes.devlist-ee4meeAH724@public.gmane.org> wrote:> > I''m working on a Rails app that needs to expose a RESTful web service. I''m curious to know some of the best practices as it relates to RESTful API design. > > Let''s say I have a set of related objects on the server side. I''ll use the venerable subscribers, subscriptions and magazines example to lay it out. > > class Subscriber < AR > has_many :subscriptions > has_many :magazines, :through => :subscriptions > end > > class Subscription < AR > belongs_to :subscriber > belongs_to :magazine > end > > class Magazine < AR > has_many :subscriptions > has_many :subscribers, :through => :subscriptions > end > > Does it make sense for this relationship to get exposed through the REST API? Put another way, does it make sense to support a GET operation where the URL looks like this? > http://example.com/subscribers/3/subscriptions/19/magazines/12.xml > > Or, should the API force smaller steps such that a web service client needs to do multiple GETs like: > http://example.com/subscribers/3.xml # returns a list of subscriptions for subscriber.id == 3 > > http://example.com/subscriptions/19.xml # returns a list of magazines for subscriptions.id == 19 (already "constrained" by the previous call to subscribers) > > http://example.com/magazines/12.xml # id == 12 came from the prior call to #subscriptions > > I know the API is stateless so any "state" maintained between calls has to be represented in the URL, but it just seems wrong to me that the object relationships get exposed in the URL with the long, single call. It seems cleaner to force the web service client to break it into separate ones for each resource. > > The API also needs to support POST and PUT operations on the same set of related objects.The way I would do this is not go beyond the 2nd level of resource nesting in the URI for GETs, so these would be acceptable: GET /subscribers/12 GET /magazines/2 GET /subscribers/12/subscriptions GET /magazines/2/subscriptions POST, PUT, and DELETE subscriptions as follows, though: POST /subscriptions/32 PUT /subscriptions/32 DELETE /subscriptions/32 There is no ''state'' carried across in these examples, by the way. For instance, nothing should prevent someone from doing a GET on Joe''s subscription to "Blah", without first doing a GET on Joe, so GET /subscriptions/32 should also be legal. -- Bosko Milekic <bosko.milekic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> http://www.crowdedweb.com/ --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
cremes.devlist-ee4meeAH724@public.gmane.org
2006-Nov-22 18:07 UTC
Re: RESTful web service design question
On Wednesday, November 22, 2006, at 10:55AM, "Bosko Milekic" <bosko.milekic-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> >On 11/22/06, cremes.devlist-ee4meeAH724@public.gmane.org <cremes.devlist-ee4meeAH724@public.gmane.org> wrote: >> >> I''m working on a Rails app that needs to expose a RESTful web service. I''m curious to know some of the best practices as it relates to RESTful API design. >> >> Let''s say I have a set of related objects on the server side. I''ll use the venerable subscribers, subscriptions and magazines example to lay it out. >>[snip] >> >> Does it make sense for this relationship to get exposed through the REST API? Put another way, does it make sense to support a GET operation where the URL looks like this? >> http://example.com/subscribers/3/subscriptions/19/magazines/12.xml >> >> Or, should the API force smaller steps such that a web service client needs to do multiple GETs like: >> http://example.com/subscribers/3.xml # returns a list of subscriptions for subscriber.id == 3 >> >> http://example.com/subscriptions/19.xml # returns a list of magazines for subscriptions.id == 19 (already "constrained" by the previous call to subscribers) >> >> http://example.com/magazines/12.xml # id == 12 came from the prior call to #subscriptions >> >>[snip] > >The way I would do this is not go beyond the 2nd level of resource >nesting in the URI for GETs, so these would be acceptable: > >GET /subscribers/12 >GET /magazines/2 >GET /subscribers/12/subscriptions >GET /magazines/2/subscriptions > >POST, PUT, and DELETE subscriptions as follows, though: > >POST /subscriptions/32 >PUT /subscriptions/32 >DELETE /subscriptions/32Okay, that looks all right. I certainly like it a lot better than stringing them all out which would require a pretty complex nested resource map in routes.rb. It would suck trying to debug one nested 3 or 4 deep. Thanks for your response. Now I know I''m not too far off from reality with my design. cr --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---