Live data from Hacker News

Rdio: No REST for the wicked

developer.rdio.com

11–20 of 29 posts

Re: Rdio: No REST for the wicked

#11
post #9

When I started working on the Rdio API I struggled to work out how to effectively expose our API through a more classically REST model, but ultimately there was too much functionality that would be significantly more ugly when forced into a document-oriented REST model than exposed through an RPC model. Hi Ian, if it's not too much trouble could you give an example of functionality that didn't work well with REST?

Off the top of my head a couple of things that didn't map well were: * search * deleting songs from a playlist (safely) * multidimentional stats queries (eg: http://developer.rdio.com/docs/read/rest/Methods#getHeavyRot... ) Perhaps we could have modelled these in a REST-like manner, but it seemed simpler to make the functionality available through an RPC protocol - simpler for us to implement and simpler for develope…

When I design RESTful APIs, I tyypically wind up with a collection resource for each of my resource types. (This is a common pattern, I think.) Searching and your getHeavyRotation are examples of "GET the collection resource, but filter the resources to include in the list". For this I use the path to identify the collection and query parameters to specify the filtering.

Query parameters are appropriate here because they're not being used to specify which collection resource to retrieve. They're being used to alter the representation of the collection. This is just like using start and count query parameters to allow paging through a large collection.

For your search, you would use a single query parameter, and for getHeavyRotation you would use one parameter for each field you can filter on. They'd be optional of course, and if none are specified you get the whole collection.

Regarding deleting songs "safely", I'm not sure what you mean but I'm guessing you want some confirmation or recovery. I assume each song has a playlist attribute; instead of allowing a DELETE method on the song I would have a trashbin playlist, and allow the song resource to be updated with the playlist attribute changed to the trashbin uri. That allows the songs to be recovered if they are moved by mistake. To really clear it out, you could allow DELETE on /{trashbin uri}/{song id}. Eg: the song resource can only be deleted via the trashbin.

Re: Rdio: No REST for the wicked

#12
I'm working on an RPC API that works with XML over HTTP. I'll be calling it an XML API. If it did JSON I'd call it a JSON API. Some customers seem to want to call it a REST API, but it would pain me to call it that when it isn't.

Re: Rdio: No REST for the wicked

#13
post #9

Earlier quoted context omitted.

Off the top of my head a couple of things that didn't map well were: * search * deleting songs from a playlist (safely) * multidimentional stats queries (eg: http://developer.rdio.com/docs/read/rest/Methods#getHeavyRot... ) Perhaps we could have modelled these in a REST-like manner, but it seemed simpler to make the functionality available through an RPC protocol - simpler for us to implement and simpler for develope…

When I design RESTful APIs, I tyypically wind up with a collection resource for each of my resource types. (This is a common pattern, I think.) Searching and your getHeavyRotation are examples of "GET the collection resource, but filter the resources to include in the list". For this I use the path to identify the collection and query parameters to specify the filtering. Query parameters are appropriate here because…

Given then, how would you map a search that returns multiple types?

As far as deleting songs "safely", what Ian means is that for any given playlist (of which a user has an unlimited number) any given song can be in it any number of times. So when you delete a song, we generally ask for song_id and index to make sure that a) the playlist hasn't mutated (much), and b) we are dropping the right song. The DELETE on /{trashbin uri}/{song id} doesn't provide 2 of the 3 required bits of information, and DELETE /playlist/{playlist id}/{song id}/{index} isn't very RESTful (imo).

Re: Rdio: No REST for the wicked

#14
post #13

Earlier quoted context omitted.

When I design RESTful APIs, I tyypically wind up with a collection resource for each of my resource types. (This is a common pattern, I think.) Searching and your getHeavyRotation are examples of "GET the collection resource, but filter the resources to include in the list". For this I use the path to identify the collection and query parameters to specify the filtering. Query parameters are appropriate here because…

Given then, how would you map a search that returns multiple types? As far as deleting songs "safely", what Ian means is that for any given playlist (of which a user has an unlimited number) any given song can be in it any number of times. So when you delete a song, we generally ask for song_id and index to make sure that a) the playlist hasn't mutated (much), and b) we are dropping the right song. The DELETE on /{tr…

A search with multiple return types is a good question when the results are JSON, but if the result is something like Atom, it's not really an issue at all because each entity in the resulting feed can contain its own type descriptors. Unfortunately it's since been replaced by a new CMS after I left several years ago, but the search for newsweek.com used to work like this.

Re: Rdio: No REST for the wicked

#15
post #13

Earlier quoted context omitted.

When I design RESTful APIs, I tyypically wind up with a collection resource for each of my resource types. (This is a common pattern, I think.) Searching and your getHeavyRotation are examples of "GET the collection resource, but filter the resources to include in the list". For this I use the path to identify the collection and query parameters to specify the filtering. Query parameters are appropriate here because…

Given then, how would you map a search that returns multiple types? As far as deleting songs "safely", what Ian means is that for any given playlist (of which a user has an unlimited number) any given song can be in it any number of times. So when you delete a song, we generally ask for song_id and index to make sure that a) the playlist hasn't mutated (much), and b) we are dropping the right song. The DELETE on /{tr…

DELETE /playlist/{playlist id}/{song id}/{index} isn't very RESTful (imo)

Your opinion is a fact, imo. Songs can't be deleted from playlists using REST, full stop. Songs-in-playlists are values, not identities, so they can't be resources. I see it as analogue to words in a text file. A REST client would have to construct the updated playlist value and PUT the whole thing to the playlist resource. So "delete song from playlist" is a function that could only exist in the client.

Search on the other hand is just search. I don't think REST vs RPC has much to say about it. The only issue would be location: URL vs method.

Re: Rdio: No REST for the wicked

#16
post #13

Earlier quoted context omitted.

Given then, how would you map a search that returns multiple types? As far as deleting songs "safely", what Ian means is that for any given playlist (of which a user has an unlimited number) any given song can be in it any number of times. So when you delete a song, we generally ask for song_id and index to make sure that a) the playlist hasn't mutated (much), and b) we are dropping the right song. The DELETE on /{tr…

DELETE /playlist/{playlist id}/{song id}/{index} isn't very RESTful (imo) Your opinion is a fact, imo. Songs can't be deleted from playlists using REST, full stop. Songs-in-playlists are values, not identities, so they can't be resources. I see it as analogue to words in a text file. A REST client would have to construct the updated playlist value and PUT the whole thing to the playlist resource. So "delete song from…

> Your opinion is a fact, imo

This doesn't parse very well to me.

As far as your main point, I disagree. The /playlist/:playlist_id/:song_id/:index thing doesn't seem very good, no. But, if you kept an id that mapped songs to playlists, you could easily do DELETE /playlists/:playlist_id/:song_playlist_id and be done with it.

REST doesn't say you have to update the entire resource just because a member of that resource needs to be deleted.

Re: Rdio: No REST for the wicked

#17
post #13

Earlier quoted context omitted.

Given then, how would you map a search that returns multiple types? As far as deleting songs "safely", what Ian means is that for any given playlist (of which a user has an unlimited number) any given song can be in it any number of times. So when you delete a song, we generally ask for song_id and index to make sure that a) the playlist hasn't mutated (much), and b) we are dropping the right song. The DELETE on /{tr…

A search with multiple return types is a good question when the results are JSON, but if the result is something like Atom, it's not really an issue at all because each entity in the resulting feed can contain its own type descriptors. Unfortunately it's since been replaced by a new CMS after I left several years ago, but the search for newsweek.com used to work like this.

I'm confused, why would JSON vs. Atom make a difference in this case? What does Atom get you that you can't also do with JSON?

Re: Rdio: No REST for the wicked

#18
post #13

Earlier quoted context omitted.

Given then, how would you map a search that returns multiple types? As far as deleting songs "safely", what Ian means is that for any given playlist (of which a user has an unlimited number) any given song can be in it any number of times. So when you delete a song, we generally ask for song_id and index to make sure that a) the playlist hasn't mutated (much), and b) we are dropping the right song. The DELETE on /{tr…

DELETE /playlist/{playlist id}/{song id}/{index} isn't very RESTful (imo) Your opinion is a fact, imo. Songs can't be deleted from playlists using REST, full stop. Songs-in-playlists are values, not identities, so they can't be resources. I see it as analogue to words in a text file. A REST client would have to construct the updated playlist value and PUT the whole thing to the playlist resource. So "delete song from…

Agreed that it is possible, but it sucks to implement for the developer, which is Ian's original point. Its absolutely possible to do it, but we felt it was suboptimal, and opted to do something else.

Re: Rdio: No REST for the wicked

#19

Earlier quoted context omitted.

A search with multiple return types is a good question when the results are JSON, but if the result is something like Atom, it's not really an issue at all because each entity in the resulting feed can contain its own type descriptors. Unfortunately it's since been replaced by a new CMS after I left several years ago, but the search for newsweek.com used to work like this.

I'm confused, why would JSON vs. Atom make a difference in this case? What does Atom get you that you can't also do with JSON?

Atom has a well-defined way for expressing the content type of items in a feed. You can do this with JSON but you have to come up with your own system.

Re: Rdio: No REST for the wicked

#20
post #18

Earlier quoted context omitted.

DELETE /playlist/{playlist id}/{song id}/{index} isn't very RESTful (imo) Your opinion is a fact, imo. Songs can't be deleted from playlists using REST, full stop. Songs-in-playlists are values, not identities, so they can't be resources. I see it as analogue to words in a text file. A REST client would have to construct the updated playlist value and PUT the whole thing to the playlist resource. So "delete song from…

Agreed that it is possible, but it sucks to implement for the developer, which is Ian's original point. Its absolutely possible to do it, but we felt it was suboptimal, and opted to do something else.

Urm, I thought I was agreeing that it's not possible. But I think we're in agreement.

In short: you want to offer functions on the server that REST would push on to the client (or would require making architectural changes).

REST definitely requires a larger upfront investment vs RPC. Part of what I'm curious about is how much larger in real world cases, and this is a good example. So I appreciate you taking the time to respond.

Post reply on HN