What is the best RESTful method to return the total number of elements in an object?

I am developing a REST API service for the large social networking site I’m participating in. So far, it works fine. I can issue GET , POST , PUT and DELETE requests to the URLs of objects and affect my data. However, this data is uploaded (limited to 30 results at a time).

However, what is the best RESTful way to get the total number of participants through my API?

I am currently issuing requests for a URL structure, for example:

  • / api / members - returns a list of participants (30 at a time, as described above)
  • / api / members / 1 - One member effect, depending on the request method used

My question is: how could I use a similar URL structure to get the total number of participants in my application? Obviously, querying only the id field (similar to the Facebooks API) and counting results will be ineffective if only half of the results are returned only.

+79
rest restful-url
Sep 15 '10 at 8:41
source share
10 answers

While the response to / API / users is uploaded and returns only 30 records, nothing prevents you from including the total number of records and other relevant information in the response, such as page size, page number / offset, etc.

The StackOverflow API is a good example of the same project. Here's the documentation for the Users method - https://api.stackexchange.com/docs/users

+50
Sep 15 '10 at 8:48
source share

I prefer to use HTTP headers for this kind of contextual information.

For the total number of elements, I use the X-total-count header.
For links to the next, previous page, etc. I am using http link header:
http://www.w3.org/wiki/LinkHeader

Github does the same: https://developer.github.com/v3/#pagination

In my opinion, it is cleaner because it can also be used when returning content that does not support hyperlinks (for example, binary files, images).

+36
Sep 05 '15 at 20:45
source share

Alternative if you do not need the actual elements

Franci Penov's answer is by far the best way for you to always return items along with all the additional metadata about the entities you requested. How it should be done.

but sometimes returning all the data does not make sense, because they may not need them at all. Perhaps all you need is metadata about the requested resource. Like the total number or number of pages or something else. In this case, you can always request a URL request so that your service does not return elements, but simply metadata:

 /api/members?metaonly=true /api/members?includeitems=0 

or something similar...

+19
Jan 05 '15 at 10:19
source share

You can return the invoice as a custom HTTP header in response to a HEAD request. That way, if the client only needs a tally, you do not need to return the actual list, and there is no need for an additional URL.

(Or, if you are in a controlled environment from endpoint to endpoint, you can use your own HTTP verb, such as COUNT.)

+17
Sep 15 '10 at 8:57
source share

Recently, I have been doing some extensive research on this and other issues related to the REST search call, and thought it was constructive to add some of my findings here. I am expanding the question a bit to include thoughts on paging, as well as counting, as they are related to each other.

Headings

Swap metadata is included in the response as response headers. The big advantage of this approach is that the response payload itself is just a request that requested the actual data request. Easier response handling for customers who are not interested in paging information.

There are many (standard and customizable) headers used in the wild to return information related to the paging call, including the total.

X-total-count

 X-Total-Count: 234 

This is used in some API that I found in the wild. There are also NPM packages to add support for this header, for example. Loopback Some articles also recommend setting this heading.

It is often used in conjunction with the Link header, which is a pretty good search call solution but does not contain general account information.

Link

 Link: </TheBook/chapter2>; rel="previous"; title*=UTF-8'de'letztes%20Kapitel, </TheBook/chapter4>; rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel 

I believe that by reading a lot on this topic, the general consensus is to use the Link header to provide paging links to clients using rel=next , rel=previous , etc. The problem is that he lacks information about the number of shared records, so many APIs combine this with the X-Total-Count header.

Alternatively, some APIs, such as JsonApi , use the Link format, but add the information in the response envelope instead of the header. This simplifies access to metadata (and creates a place to add general information about the account) by increasing the complexity of access to actual data (by adding an envelope).

Content range

 Content-Range: items 0-49/234 

Promotion of a blog article called Range heading, I choose you (for pagination)! . The author makes a big argument for using Range and Content-Range headers for pagination. When we carefully read the RFCs in these headers, we find that expanding their values ​​outside the byte ranges was actually expected by the RFCs and is explicitly allowed. When used in the context of items instead of bytes Range header actually gives us a way to both request a specific range of elements and indicate to which range of the final result the response elements belong. This heading also provides a great way to show the total. And this is a true standard that basically displays one-to-one paging. It is also used in the wild .

The envelope

Many APIs, including those from our favorite Q&A website, use an envelope, a wrapper around the data, which are used to add meta-information about the data. In addition, OData and JsonApi standards use a response envelope.

The big drawback of this (imho) is that processing the response data becomes more complicated, since the actual data needs to be found somewhere in the envelope. There are also many different formats for this envelope, and you should use the correct one. This suggests that the response responses from OData and JsonApi are very different from each other, mixing OData in metadata at several points in the response.

Single endpoint

I think this has been covered quite fully in other answers. I did not investigate this because I agree with the comments that this is confusing since you now have several types of endpoints. I think it is beautiful if each endpoint is a (set) of resources (s).

Further thoughts

We not only need to provide search call meta-information related to the response, but also allow the client to request specific pages / ranges. It is also interesting to look at this aspect in order to get an agreed solution. Headers can also be used here (the Range header seems very appropriate) or other mechanisms such as query parameters. Some people advocate processing pages of results as separate resources, which may make sense in some use cases (e.g. /books/231/pages/52 ). In the end, I chose a wild range of commonly used query parameters, such as pagesize , page[size] and limit etc, in addition to supporting the Range header (and as a query parameter as well).

+14
May 14, '17 at 20:56
source share

I would recommend adding headers for them, for example:

 HTTP/1.1 200 Pagination-Count: 100 Pagination-Page: 5 Pagination-Limit: 20 Content-Type: application/json [ { "id": 10, "name": "shirt", "color": "red", "price": "$23" }, { "id": 11, "name": "shirt", "color": "blue", "price": "$25" } ] 

See details

https://github.com/adnan-kamili/rest-api-response-format

For swagger file:

https://github.com/adnan-kamili/swagger-response-template

+9
Aug 2 '16 at 13:42 on
source share

What about the new endpoint> / api / members / count, which simply calls Member.Count () and returns the result

+2
Sep 15 '10 at 8:45
source share

It seems easiest to add

 GET /api/members/count 

and return the total number of members

+2
Sep 15 2018-10-10T00:
source share

Sometimes frameworks (for example, $ resource / AngularJS) require an array as the result of a query, and you cannot have an answer like {count:10,items:[...]} , in which case I store "count" in responseHeaders .

P. S. In fact, you can do this with $ resource / AngularJS, but some settings are needed for this.

+2
Dec 15 '13 at 22:40
source share

When requesting paginated data, you know (using the value of the page size parameter or the default page size value) the page size, so you know whether you received all the data in response or not. When the response has less data than the page size, you get the whole data. When the full page returns, you need to ask again about another page.

I prefer to have a separate endpoint for count (or the same endpoint with the countOnly parameter). Since you can prepare the end user for a long / laborious process, showing a properly prepared progress panel.

If you want to return data in each response, the pageSize value should be specified, as well as the offset offset. Honestly, the best way is to repeat query filters. But the answer has become very complicated. Therefore, I prefer a dedicated endpoint to return the counter.

 <data> <originalRequest> <filter/> <filter/> </originalReqeust> <totalRecordCount/> <pageSize/> <offset/> <list> <item/> <item/> </list> </data> 

Couleage my, I prefer the countOnly parameter for an existing endpoint. Thus, when specifying, the response contains only metadata.

end point? = Filter value

 <data> <count/> <list> <item/> ... </list> </data> 

filter endpoint = value &? CountOnly = true

 <data> <count/> <!-- empty list --> <list/> </data> 
-2
Jul 18 '14 at 9:19
source share



All Articles