Is it valid to modify a REST API representation based on a If-Modified-Since header?
Asked Answered
S

1

9

I want to implement a "get changed values" capability in my API. For example, say I have the following REST API call:

GET /ws/school/7/student

This gets all the students in school #7. Unfortunately, this may be a lot. So, I want to modify the API to return only the student records that have been modified since a certain time. (The use case is that a nightly process runs from another system to pull all the students from my system to theirs.)

I see http://blog.mugunthkumar.com/articles/restful-api-server-doing-it-the-right-way-part-2/ recommends using the if-modified-since header and returning a representation as follows:

  • Search all the students updated since the time requested in the if-modified-since header
  • If there are any, return those students with a 200 OK
  • If there are no students returned from that query, return a 304 Not Modified

I understand what he wants to do, but this seems the wrong way to go about it. The definition of the If-Modified-Since header (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24) says:

The If-Modified-Since request-header field is used with a method to make it conditional: if the requested variant has not been modified since the time specified in this field, an entity will not be returned from the server; instead, a 304 (not modified) response will be returned without any message-body.

This seems wrong to me. We would not be returning the representation or a 304 as indicated by the RFC, but some hybrid. It seems like client side code (or worse, a web cache between server and client) might misinterpret the meaning and replace the local cached value, when it should really just be updating it.

So, two questions:

  • Is this a correct use of the header?
  • If not (and I suspect not), what is the best practice? Query string parameter?
Seed answered 14/10, 2014 at 14:24 Comment(0)
D
7

This is not the correct use of the header. The If-Modified-Since header is one which an HTTP client (browser or code) may optionally supply to the server when requesting a resource. If supplied the meaning is "I want resource X, but only if it's changed since time T." Its purpose is to allow client-side caching of resources.

The semantics of your proposed usage are "I want updates for collection X that happened since time T." It's a request for a subset of X. It does not seem like your motivation is to enable caching. Your client-side cached representation seemingly contains all of X, even though the typical request will only return you a small set of changes to X; that is, the response is not what you are directly caching, so the caching needs to happen in custom user logic client-side.

A query string parameter is a much more appropriate solution. Below {seq} would be something like a sequence number or timestamp.

GET /ws/schools/7/students/updates?since={seq}

Server-side I imagine you have a sequence of updates since the beginning of your system and a request of the above form would grab the first N updates that had a sequence value greater than {seq}. In this way, if a client ever got very far behind and needed to catch up, the results would be paged.

Dimity answered 14/10, 2014 at 15:30 Comment(1)
Thank you for confirming, bass-man. That was exactly my thinking as well.Seed

© 2022 - 2024 — McMap. All rights reserved.