SoftInstigate / restheart

Rapid API Development with MongoDB
https://restheart.org
GNU Affero General Public License v3.0
805 stars 171 forks source link

Usage of max-age header in combination with eTag #358

Closed hannomalie closed 5 years ago

hannomalie commented 5 years ago

Hey guys, I have a small question :)

Do you have any idea how one could implement the usage of a max-age header in combination with the eTag mechanism in restheart?

Background is, that we have customers that use middleware which does treat Not Modified responses without a max-age value as not cacheable. Do you have any experience regarding such a scenario?

Thx! Hannes

ujibang commented 5 years ago

I understand that you need to add the Cache-Control header to Not Modified responses (correct me if I'm wrong).

You can use a Transformer to add the Cache-Control header.

A starting point is:

@RegisterPlugin(name = "addCacheControl",
        description = "Adds Cache Contro to responses when status==SC_NOT_MODIFIED")
public class AddCacheControlToNotModified implements Transformer {

    @Override
    public void transform(
            HttpServerExchange exchange,
            RequestContext context,
            BsonValue contentToTransform,
            BsonValue args) {
        if (context.getDbOperationResult() == null) {
        } else {
            if (context.getResponseStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
                exchange.getResponseHeaders().add(Headers.CACHE_CONTROL, 
                        "max-age=10");
            }
        }
    }
}

Of course then you need to add addCacheControl to the collection metadata rts as described in https://restheart.org/docs/transformers/

{ "rts": [
 {"name":"addCacheControl", 
 "phase":"RESPONSE", 
 "scope":"THIS", 
 "args":null}
]}
hannomalie commented 5 years ago

Hi, yes I think you understood it correctly. Unfortunately, using collection metadata is not an option in our scenario. If there's no other way, we have to be creative :) Thanks for the very fast reply, much appreciated.

mkjsix commented 5 years ago

@hannespernpeintner a common alternative is to put a reverse proxy on top of RESTHeart. For example, it's easy to configure NGINX as a proxy_pass for RESTHeart and add all the necessary HTTP headers in the final response.