apicache icon indicating copy to clipboard operation
apicache copied to clipboard

Any way to ignore certain url params?

Open irman33 opened this issue 5 years ago • 6 comments

I'm trying to cache a api/route that's being called by Datatables, which is just a jQuery ajax request. The ajax request adds an _=234234234 (timestamp) param to bypass browser caching.

That's creating separate caches for each call.

Turning off the jQuery caching, I can get it to stop appending the param, but then the browser caching kicks in.

Any way to keep the jQuery caching but ignore the query param?

irman33 avatar Mar 20 '19 23:03 irman33

+1 for this, we need to avoid cache miss for the request with ?ts=[timestamp] as well.

My suggestion would be to expose overridable calculateCacheKey: fn(req, res) callback where default implementation would be return req.url (this is how it works now)

This would be able to replace appendKey functionality which can only increase specificity now, but is useless when you want to decrease it.

restyler avatar Jul 30 '19 06:07 restyler

For now I've solved this with middleware which is launched prior to apicache (regex might be used in case you need it, I use basic startsWith for better performance)

// MIDDLEWARE TO AVOID CACHE PURGES 
app.use(function(req, res, next) {
   // instead of ?v=[random timestamp] we set ?v=[start of today]
    let event = new Date();
    event.setHours(0,0,0,0);
    var ts = event.getTime();

    let rewriteMap = [
        ['/server/url1?v=', '/server/url1?v=' + ts],
        ['/server/url2?v', '/server/url2?v=' + ts]
    ];

    for (rewrite of rewriteMap) {
        if (req.url.startsWith(rewrite[0])) {
            //console.log(req.url);
            req.url = rewrite[1];
            req.originalUrl = rewrite[1]; // hack to fix apicache using originalUrl
            //console.log('avoided cache purge: ' + req.url);
            break;
        }
    }
    next();
});

restyler avatar Aug 01 '19 11:08 restyler

+1

I agree it would be nice to have a way to define our own cache key and avoid cache misuse/abuse.

As per my understanding, for example, a user can prevent apicache by intentionally requesting URLs like:

/my-api/load /my-api/load?x /my-api/load?x2 /my-api/load?x3 ...

All these requests will be treated by apicache as unique requests and will be executed independently.

Ideally, I'd appreciate a getKey method along with appendKey where I would simply whitelist my own params.

(A seemingly unrelated request - but heavily connected to this - is a way to be able to turn off the 'x-bypass-apicache' header).

Thanks @restyler I had the same idea (using a middleware) however I was quite unsure which parameters of the request should I modify not to break anything else.

adams-family avatar Mar 07 '21 13:03 adams-family

@adams-family @restyler @irman33 This should be available as the toggle within the signature apicache.middleware(duration: string, toggle: function). That function will control the caching and serving of the response within a route.

Example:

const app = express()

// cache toggle (if used) must return truthy to cache
const onlyMittens = request => request.params.name.toLowerCase() === 'mittens'

// using the middleware toggle
const cacheOnlyMIttens = apicache.middleware('1 week', onlyMittens)

app.get('/kittens/:name', cacheOnlyMittens, (req, res) => {
  res.send(`Hello ${req.params.name}!`)
})

// GET /kittens/fluffy --> Hello fluffy! (not cached)
// GET /kittens/mittens --> Hello mittens! (cached)

// GET /kittens/fluffy --> Hello fluffy! (still not cached)
// GET /kittens/mittens --> Hello mittens! (served from cache)

Hope that helps! If someone can confirm this works as expected, please close the issue after confirmation! :)

kwhitley avatar Mar 08 '21 15:03 kwhitley

Hi @kwhitley - thanks for your suggestion. I think my use-case is slightly different:

I want all these URLs to be cached:

GET /kittens/cat1 GET /kittens/cat2 GET /kittens/cat3 GET /kittens/cat4 ...

However, I want all these variants to result in the same "cache hit":

GET /kittens/cat1 GET /kittens/cat1?time=11111 GET /kittens/cat1?time=2222 GET /kittens/cat1?xxxx GET /kittens/cat1?xxxx_ GET /kittens/cat1?xxxx__

In other words, I don't want a possible attacher to bypass the cache by adding bogus characters (such as xxxx__, ...) to my requests. All requests above should IMO return the same cache entry.

adams-family avatar Mar 15 '21 17:03 adams-family

I have the same need as @adams-family, preventing cache bypassing. Ideally I'd want to be able to specify which query parameters (if any) should be used to generate the cache key.

chasetec avatar Apr 18 '21 19:04 chasetec