/userStories?asA=emailScammer&iWantTo=mineEmailAddresses&soThat=iCanBroadcastMoreSpam
I'm not sure I was kidding.
Followup: I used query parameters; HTML is a successful implementation of a media-type which supports hypermedia controls. It's an ideal reference implementation for illustrating RESTful principles.
But it is not without its limitations. URI Templates offer a lot of flexibility; web forms -- not so much. You expose query parameters, or you force the client to traverse a graph to find the control that they want.
Digging around for URI design guidelines, I found this summary by K. Alan Bates
Hierarchical data is supposed to be represented on the path and with path parameters. Non-hierarchical data is supposed to be represented in the query. The fragment is more complicated, because its semantics depend specifically upon the media type of the representation being requested.
Moving the parameters of the story from the query string would be preferred, because it correctly represents that this the known identification of a resource, rather than a specification for a resource that may not have any matches. Furthermore, doing so better conforms to the convention that path segments represent hierarchy. For instance, it's reasonable to suppose that the URI for the story card ought to look like:
/userStories/asA=emailScammer&iWantTo=mineEmailAddresses&soThat=iCanBroadcastMoreSpam/card
The design guidelines in the RESTful Web Services Cookbook suggest an improvement on the previous design...
Use the comma (Richardson & Ruby, in Chapter 5 of RESTful Web Services were a bit more specific,
) and semicolon (;
) to indicate nonhierarchical elements in the path portion of the URI.
I recommend using commas when the order of the scoping information is important, and semicolons when the order doesn't matter.I'm not actually sure if the template of the user story should be considered ordered or not. There are a lot of references to the Cohn template, a few that point out that maybe the business value should get pride of place.
Me? I'm going to represent that the ordering of these elements matters, because that allows me to use the delimiter that looks like the punctuation on the story card itself
/userStories/asA=emailScammer,iWantTo=mineEmailAddresses,soThat=iCanBroadcastMoreSpam/card
Better, but I don't like equals, and none of the other sub-delims improve the outcome. Today, I learned that RFC 3986 offers me an out -- the production rules for path segments explicitly include colon!
/userStories/asA:emailScammer,iWantTo:mineEmailAddresses,soThat:iCanBroadcastMoreSpam/card
In all, an educational exercise. Didn't learn whether or not I was kidding.
After asking around, another approach is to use POST for searches if you do not need permanent URLs. For example:
ReplyDeletePOST /userStories/card?sort=asA
asA=emailScammer
iWantTo=mineEmailAddresses
soThat=iCanBroadcastMoreSpam
The thinking is to create an object on the server side for results, and return a reference to it. This lets you page through that object without it being updated with new data -- the problem of recomputing search results each call causing, say, page 2 to skip or duplicate results that matched/unmatched between calls.
The client does need to remember to DELETE the search results object when done, to free up resources on the server.
Wrong plot. This isn't the identifier for a query! This is a bookmark: you use it as the starting point for your acceptance test.
ReplyDelete