views:

99

answers:

4

Let's say I have a RESTful, hypertext-driven service that models an ice cream store. To help manage my store better, I want to be able to display a daily report listing quantity and dollar value of each kind of ice cream sold.

It seems like this reporting capability could be exposed as a resource called DailyReport. A DailyReport can be generated quickly, and there doesn't seem to be any advantage to actually storing reports on the server. I only want a DailyReport for some days, other days I don't care about getting a DailyReport. Furthermore, storing DailyReports on the server would complicate client implementations, which would need remember to delete reports they no longer need.

A DailyReport is transient; its representation can be retrieved only once. One way to implement this would be to offer a link "/daily-reports", a POST to which will return a response containing a DailyReport representation listing the information for that day's sales.

Edit: Let's also say that I really do want to do a POST request. A DailyReport has many different options for creating a view such as sorting ice cream types alphabetically, by dollar value - or including an hourly breakdown - or optionally including the temperature for that day - or filtering out certain ice cream types (as a list). Rather than using query parameters with a GET, I'd rather POST a DailyReport representation with the appropriate options (using a well-defined custom media type to document each option). The representation I get back would display my options along with the report itself.

Is this the correct way to think about the problem, or should some other approach be used instead? If correct, what special considerations might be important when implementing the DailyReport resource? (For example, it probably wouldn't be appropriate to set the Location header when returning after a POST request).

+2  A: 

There's no need to use a POST for this, since requesting the report doesn't change the state of the server. I would use a resource like this:

GET /daily-report/

200 OK
Pragma: no-cache
<daily-report for="2009-04-20" generated-at="2009-4-20T12:13:14Z">
    <!-- contents of the report here -->
</daily-report>


Responding to your edit: if you are POSTing a description of the report to a URL, and retrieving a temporary data set as a result, that's not REST at all. It's RPC, in the same vein as SOAP. RPC is not an inherently bad thing, but please, please don't call it RESTful.

John Millikin
Good point. What if there were several parameters that could be applied to the DailyReport - for example sort ice cream types alphabetically or by dollar figure - and what if I didn't want to use query parameters to do this? Or what if I wanted to enable the date range to be set to something other than the last 24 hours, i.e., a more general purpose Report resource? Let's say I don't want to include these options as query parameters, but rather as a full-fledged representation sent as a POST payload? That's closer to what I'm thinking about.
Rich Apodaca
Why don't you want to use query parameters? That's what they exist for. Custom report ranges can be provided using query parameters as well. If the parameters are so complex that they can't be represented in the query string, then it might be worth uploading them to the server and making the daily report a sub-resource.
John Millikin
+4  A: 

If you want to make daily reports for past days available, you could implement it as a GET to /daily_reports/2009/08/20. I agree with John Millikin that a POST is unnecessary here - there's no need for something like this to be a user-creatable resource.

The advantage of making the report for each day available as its own URI is cacheability.

EDIT: A good solution might be to merge the two answers, making daily_report/ a no-cache representation of the current day's data and daily_reports/yyyy/mm/dd a cacheable representation of a full day's data.

Greg Campbell
+1  A: 

I think Greg's approach is the correct one. To expound upon it, I don't think you should provide a /daily-report resource that changes daily, because running the report on Tuesday at 11:59 would yield different results than running it Wednesday at 00:01, which can be A) confusing for clients expecting the resource to be the same, and B) doesn't allow clients to retrieve a previous day's data after the day has passed. You should provide a unique resource identifier for each daily report that's available, that way clients can access the information they need at any time.

Rob Hruska
It is quite common to have a /TodaysWeather type of resource. A client should not be surprised when a resource changes between GETs.
Darrel Miller
I agree with Darrel's comment, just add the proper expires header. It is perfectly valid to GET a resource that represents something current to the time it was retrieved. If you want to make it clearer to the API consumer you may want to have separate URI formats:/daily-report/archive/daily-reports/2009/02/12I'm sure someone will jump in and mention REST doesn't care about URI design, however they are important to designing a usable API.
Stephen Petschulat
+2  A: 

Sometimes it is desirable to keep a record of requests for reports, in those cases it is not unreasonable to POST to a collection resource. It is also useful for long running reports where you want handle the execution asynchronously. How long the server holds onto those report requests is up to you.

I would do something like

POST /DailyReportRequests

which would return a representation of the request, including options, and when the report is completed, a link to the report results.

Another alternative which is good when you have a set of pre-canned reports is to create a DailyReports resource that contains a list of preconfigured report links. The OpenSearchDescription spec allows you to do something similar to this using the Query tag.

Darrel Miller