How should I implement a COUNT verb in my RESTful web service?

15,193

Solution 1

The main purpose of rest is to define a set of resources that you interact with using well defined verbs. You must thus avoid to define your own verbs. The number of resources should be considered as a different resource, with its own uri that you can simply GET. For example:

GET resources?crit1=val1&crit2=val2

returns the list of resources and

GET resources/count?crit1=val1&crit2=val2

Another option is to use the conneg: e.g. Accept: text/uri-list returns the resources list and Accept: text/plain returns only the count

Solution 2

You can use HEAD without breaking the HTTP specification and you can indicate the count by using an HTTP Range header in the response:

HEAD /resource/?search=lorem

Response from the service, assuming that you return the first 20 results by default:

...
Content-Range: resources 0-20/12345
...

This way you transfer the amount of resources to the client within the header of the response message without the need to return a message body.

Update:
The solution suggested Yannick Loiseau will work fine. Just wanted to provide one other alternative approach which can be used to achieve what you need without the need to define a new resource of verb.

You can use GET and add the count into the body of the message. Then, if you API allows clients to request a range of results, you can use that in order to limit the size of message body to a minimum (since you only want the count). One way to do that would be to request an empty range (from 0 to 0), for example:

GET /resource/?search=lorem&range=0,0

The service could then respond as follows, indicating that there are 1234 matching resources in the result set:

<?xml version="1.0" encoding="UTF-8" ?>
<resources range="0-0/1234" />

Solution 3

Ignoring the HTTP specification and returning the object count in the response body of a HEAD request.

IMHO, this is a very bad idea. It may not work simply because you might have intermediaries that don't ignore the HTTP spec.

Defining a new HTTP method, COUNT, that returns the object count in the response body.

There is no problem with this approach. HTTP is extendable and you can define your own verbs. Some firewalls prohibit this, but they are usually also prohibit POST and DELETE and X-HTTP-Method-Override header is widely supported.

Another option, to add a query param to your url, something like: ?countOnly=true

Share:
15,193
claymation
Author by

claymation

Updated on June 03, 2022

Comments

  • claymation
    claymation almost 2 years

    I've written a RESTful web service that supports the standard CRUD operations, and that can return a set of objects matching certain criteria (a SEARCH verb), but I'd like to add a higher-order COUNT verb, so clients can count the resources matching search criteria without having to fetch all of them.

    A few options that occur to me:

    • Ignoring the HTTP specification and returning the object count in the response body of a HEAD request.

    • Duplicating the SEARCH verb's logic, but making a HEAD request instead of a GET request. The server then would encode the object count in a response header.

    • Defining a new HTTP method, COUNT, that returns the object count in the response body.

    I'd prefer the API of the first approach, but I have to strike that option because it's non-compliant. The second approach seems most semantically correct, but the API isn't very convenient: clients will have to deal with response headers, when most of the time they want to be able to do something easy like response.count. So I'm leaning toward the third approach, but I'm concerned about the potential problems involved with defining a new HTTP method.

    What would you do?

  • Yannick Loiseau
    Yannick Loiseau about 13 years
    the Content-Range header represent the amount of the representation that is sent, in bytes. I don't think it's applicable here (w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16)
  • MicE
    MicE about 13 years
    Actually I think that it is, but I may be misunderstanding the RFC (correct if I am, please). The part of the RFC which you are referring to doesn't provide an example, but it refers you to another section which mentions other range units (w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.12). The RFC defines only bytes as units, however it does not forbid usage of other ranges.
  • Yannick Loiseau
    Yannick Loiseau about 13 years
    Your right that you can define other units (in this case resources), and then request by range, or use the response header to know the count. However, this means that only specific application can use this information, while using other resources any http client (browser, crawler, ...) can get the info.
  • claymation
    claymation about 13 years
    I like the idea of exposing a separate resource for object count, but I don't know where to put it. Assume I have a dictionary resource, and it exposes words as keys (GET dictionary/{word}), then where would I put the count resource? If I did GET dictionary/count, I could no longer have the word "count" in my collection.
  • MicE
    MicE about 13 years
    Yes, that's right - it would be a custom defined unit, so only customized clients would understand it. But isn't that the same as when defining a new count resource? If you want http clients to actually understand it, you still need to customize them in some way (teaching them to use the count resource or the range header). In both cases, standard http clients will still have full access to resource data so we are not limiting them in that way. Still, I believe that using a new resource is the more standards-compliant way in this case (since we don't need to rely on custom defined units).
  • Yannick Loiseau
    Yannick Loiseau about 13 years
    the count resource doesn't have to be a subresource of your dictionary, as long as you provide a link to it, which you should do anyway since the hypermedia is the engine of your application
  • Yannick Loiseau
    Yannick Loiseau about 13 years
    You cant teach client to use (discover) it with hypermedia, which is impossible (or far harder) with a custom unit or header. However, I like this range approche to provide a more "semantic" interface to paginate results for example (with the more classical query params as fallback)
  • FishBasketGordo
    FishBasketGordo about 10 years
    Are there any guidelines about how to implement something like getting the count of items in a dictionary resource? You can't just do GET dictionary/count, as @claymation points out above, so what's a simple, clean way to do it?
  • James Billingham
    James Billingham almost 10 years
    No reason you couldn't use a custom header. E.g. Content-Count or Resource-Count.