cache-handler icon indicating copy to clipboard operation
cache-handler copied to clipboard

Serve stale content from cache if origin responds with 5xx

Open rrva opened this issue 4 years ago • 23 comments

As requested in this forum thread, I want to be able to use caddy as a reverse caching proxy which makes an service more resilient to outages of the origin server, so that if the origin goes down or responds with errors, caddy serves old content.

Specifically:

  1. I only want http 200 responses to be cached
  2. If an origin server responds with http 5xx, I want to serve stale content from the cache.

Also attaching a corresponding nginx.conf which achieves what I want for reference.

nginx.conf.gz

rrva avatar Dec 28 '19 08:12 rrva

I define stale content as content for which the cache-control max-age has already expired, but it is to be kept in the cache anyway and served as a fallback if the origin is unresponsive/responds with errors

rrva avatar Dec 28 '19 13:12 rrva

@mholt I think this issue should be moved to https://github.com/caddyserver/cache-handler

francislavoie avatar Apr 20 '20 08:04 francislavoie

@francislavoie Agreed -- and this feature should be pretty easy to implement. Caddy has a ResponseRecorder which can help the cache decide whether to respond or not.

mholt avatar Apr 24 '20 16:04 mholt

@rrva are you still interested in this and/or willing to test an implementation?

gc-ss avatar Mar 28 '22 17:03 gc-ss

@gc-ss Sorry, no interest has faded for the moment (not using caddy in this capacity right now).

rrva avatar Mar 29 '22 21:03 rrva

Maybe we can take into count stale-if-error from Cache-Status - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control

frederichoule avatar Mar 23 '23 15:03 frederichoule

Should this issue be moved to https://github.com/darkweak/souin ?

frederichoule avatar Mar 23 '23 15:03 frederichoule

In the Souin codebase we support the stale-if-error directive

darkweak avatar Apr 01 '23 05:04 darkweak

@darkweak do you think it might be possible to make it configurable and not depending on upstream response cache-control?

I would like to enable fallback to server STALE page in case my upstream goes down.

fliespl avatar Jan 13 '24 20:01 fliespl

@fliespl you may use the mode bypass_response to bypass the response RFC checks. Or you could use the header_down caddy file directive to remove the cache-control response header.

darkweak avatar Jan 16 '24 20:01 darkweak

@darkweak thanks - do you have any example of that? I have tried a few things without success...

fliespl avatar Jan 16 '24 20:01 fliespl

I'm not sure but it could be something like this (cc @francislavoie about header_down reverse_proxy):

route {
  cache
  reverse_proxy 127.0.0.1:81 {
    header_down -Cache-Control
  }
}

Or using the mode cache directive:

route {
  cache {
    mode bypass_response
  }
  reverse_proxy 127.0.0.1:81
}

darkweak avatar Jan 16 '24 21:01 darkweak

@darkweak actually, I was not able to use this. Steps tried:

Simple test.php file with:

Cache-Control: max-age=10, stale-if-error=120

I get cached on first request, disable php upstream. Cache works for 10 seconds and after that I get bad gateway 502 error and not stale content.

Souin; fwd=uri-miss; key=GET-https-example.com-/test.php; detail=SERVE-HTTP-ERROR

STALE_GET-https-example.com-/test.php still has ttl of 3471 seconds.

Am I missing something?

fliespl avatar Jan 21 '24 11:01 fliespl

@fliespl what's your request? (curl)

darkweak avatar Jan 21 '24 11:01 darkweak

curl https://domain or curl -I https://domain

No matter if it's GET / HEAD same output.

fliespl avatar Jan 21 '24 12:01 fliespl

If your request doesn't send a stale-if-error directive the HTTP cache won't serve the stale response because the client doesn't allow it as explained in the RFC 7234. But reading the "new" 9111 RFC, they consider stale to be allowed by default. Maybe I misunderstood something in these RFCs.

darkweak avatar Jan 21 '24 12:01 darkweak

@darkweak isn't stale-if-error only response header? I haven't seen any browser utilizing it for "request".

I would assume it's origin response to cache servers that instructs them that in case they fail, cache server is allowed to serve this content to client.

fliespl avatar Jan 21 '24 12:01 fliespl

I meant use the max-stale request directive sorry

darkweak avatar Jan 21 '24 13:01 darkweak

@darkweak okay so my initial request still stands - allow serving stale content no matter what request sends (since max-stale is not used). Maybe it should allow it if mode is bypass request the same way it does for no-cache?

fliespl avatar Jan 21 '24 13:01 fliespl

Yes, I will create a PR for that! 👍

darkweak avatar Jan 21 '24 14:01 darkweak

@darkweak also found one other issue which is probably connected.

At default setup (without souin) if reverse proxy (php fastcgi) returns status 500 with html it gets displayed (i.e. wordpress error: https://ss.codeone.pl/ss-2024-01-21-22-20-19-1705872019-F83puPwH.png)

With souin enabled I get empty response and default chrome error: https://ss.codeone.pl/ss-2024-01-21-22-21-00-1705872060-HGzbuNTQ.png I feel like it's a bug somewhere with souin altering proxy response/headers.

fliespl avatar Jan 21 '24 21:01 fliespl

@fliespl there is a PR already open for that https://github.com/darkweak/souin/pull/441 (thanks to @vejipe) 😄

darkweak avatar Jan 21 '24 21:01 darkweak

@darkweak @vejipe Didn't realize it's connected - thanks much! :) Great job by the way!

fliespl avatar Jan 21 '24 21:01 fliespl