> On 7 Jun 2022, at 01:09, Maxim Dounin <mdounin@mdounin.ru> wrote:
>
> Hello!
>
> On Mon, Jun 06, 2022 at 05:42:20PM +0400, Sergey Kandaurov wrote:
>
>> On Sun, Apr 24, 2022 at 06:42:47PM +0300, Maxim Dounin wrote:
>>> Hello!
>>>
>>> On Sun, Apr 24, 2022 at 07:55:17AM +0300, Maxim Dounin wrote:
>>>
>>> [...]
>>>
>>>> As far as I can tell, proper behaviour, assuming we parse cache
>>>> control extensions independently of X-Accel-Expires, can be
>>>> implemented by using just one flag.
>>>
>>> No, that's wrong, as with just one flag it wouldn't be possible to
>>> correctly disable caching of responses with:
>>>
>>> Cache-Control: private
>>> Cache-Control: max-age=10
>>>
>>> So it needs at least two flags. Updated patch below, review and
>>> testing appreciated.
>>>
>>> # HG changeset patch
>>> # User Maxim Dounin <mdounin@mdounin.ru>
>>> # Date 1650814681 -10800
>>> # Sun Apr 24 18:38:01 2022 +0300
>>> # Node ID 940ba4317a97c72d1ee6700cbf58a543fee04c7a
>>> # Parent a736a7a613ea6e182ff86fbadcb98bb0f8891c0b
>>> Upstream: fixed X-Accel-Expires/Cache-Control/Expires handling.
>>> [..]
>> [..]
>> As the above note covers a corner case of X-Accel-Expires,
>> I believe it's fine to commit as is.
>
> This patch doesn't try to change handling of X-Accel-Expires in
> the past.
>
> And, honestly, the only documented way to _disable_ caching is to
> use 'X-Accel-Expires: 0'. The 'X-Accel-Expires: @0' only
> documented to set the time up to which the response may be cached
> to 0 seconds the Epoch. Expires and Cache-Control handling used
> to disable caching in similar situations, yet this behaviour was
> questioned more than once. X-Accel-Expires never disabled caching
> for absolute times in the past, and this is known to be used as a
> workaround to cache a pre-expires response[1][2].
>
> Pushed to http://mdounin.ru/hg/nginx.
>
> [1] https://trac.nginx.org/nginx/ticket/1182
> [2] https://mailman.nginx.org/pipermail/nginx-ru/2013-November/052614.html
>
Tests:
# HG changeset patch
# User Sergey Kandaurov <pluknet@nginx.com>
# Date 1654617432 -14400
# Tue Jun 07 19:57:12 2022 +0400
# Node ID ed5fe35807f6c4853be1eb8ac429524e04ac5d67
# Parent 4f238efded81e00c635c146df6ecb585fa0907ec
Tests: added X-Accel-Expires tests.
diff --git a/proxy_xae.t b/proxy_xae.t
new file mode 100644
--- /dev/null
+++ b/proxy_xae.t
@@ -0,0 +1,160 @@
+#!/usr/bin/perl
+
+# (C) Sergey Kandaurov
+# (C) Nginx, Inc.
+
+# Tests for proxy Expires / Cache-Control / X-Accel-Expires preference.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()->has(qw/http proxy cache rewrite map/)->plan(19);
+
+$t->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+http {
+ %%TEST_GLOBALS_HTTP%%
+
+ proxy_cache_path %%TESTDIR%%/cache levels=1:2
+ keys_zone=NAME:1m;
+
+ map $arg_e $e {
+ epoch "Thu, 01 Jan 1970 00:00:01 GMT";
+ max "Thu, 31 Dec 2037 23:55:55 GMT";
+ }
+
+ server {
+ listen 127.0.0.1:8080;
+ server_name localhost;
+
+ location / {
+ proxy_pass http://127.0.0.1:8081;
+ proxy_cache NAME;
+
+ proxy_cache_background_update on;
+
+ add_header X-Cache-Status $upstream_cache_status;
+ }
+
+ location /ignore {
+ proxy_pass http://127.0.0.1:8081/return-xae;
+ proxy_cache NAME;
+
+ proxy_ignore_headers X-Accel-Expires;
+
+ add_header X-Cache-Status $upstream_cache_status;
+ }
+ }
+
+ server {
+ listen 127.0.0.1:8081;
+ server_name localhost;
+
+ location / {
+ add_header Expires $e;
+ add_header Cache-Control $arg_c;
+ add_header X-Accel-Expires $arg_x;
+ add_header X-Accel-Expires $arg_xx;
+
+ return 204;
+ }
+
+ location /rev {
+ add_header X-Accel-Expires $arg_x;
+ add_header Cache-Control $arg_c;
+ add_header Expires $e;
+
+ return 204;
+ }
+ }
+}
+
+EOF
+
+$t->run();
+
+###############################################################################
+
+# Cache-Control is preferred over Expires, and
+# X-Accel-Expires is preferred over both Cache-Control and Expires,
+
+like(get('/?e=max'), qr/HIT/, 'Expires');
+like(get('/?c=max-age=60'), qr/HIT/, 'Cache-Control');
+like(get('/?x=60'), qr/HIT/, 'X-Accel-Expires');
+like(get('/?x=@2145902155'), qr/HIT/, 'X-Accel-Expires at');
+
+like(get('/ignore?x=60&ign=1'), qr/MISS/, 'X-Accel-Expires ignored');
+
+TODO: {
+local $TODO = 'not yet' unless $t->has_version('1.23.0');
+
+like(get('/?x=60&xx=0'), qr/HIT/, 'X-Accel-Expires duplicate');
+
+}
+
+# handling of caching parameters in Expires / Cache-Control / X-Accel-Expires
+
+like(get('/?e=max&c=no-cache'), qr/MISS/, 'Expires on CC off');
+like(get('/?e=max&x=0'), qr/MISS/, 'Expires on X-Accel-Expires off');
+like(get('/?c=max-age=60&x=0'), qr/MISS/, 'CC on X-Accel-Expires off');
+
+TODO: {
+local $TODO = 'not yet' unless $t->has_version('1.23.0');
+
+like(get('/?e=epoch&c=max-age=60'), qr/HIT/, 'Expires off CC on');
+like(get('/?e=epoch&x=60'), qr/HIT/, 'Expires off X-Accel-Expires on');
+like(get('/?c=no-cache&x=60'), qr/HIT/, 'CC off X-Accel-Expires on');
+
+}
+
+# and in the reversed order: X-Accel-Expires / Cache-Control / Expires
+
+like(get('/rev/?e=max&c=no-cache'), qr/MISS/, 'CC off Expires on');
+like(get('/rev?e=max&x=0'), qr/MISS/, 'X-Accel-Expires off Expires on');
+like(get('/rev?c=max-age=60&x=0'), qr/MISS/, 'X-Accel-Expires off CC on');
+
+like(get('/rev?e=epoch&c=max-age=60'), qr/HIT/, 'CC on Expires off');
+like(get('/rev?e=epoch&x=60'), qr/HIT/, 'X-Accel-Expires on Expires off');
+like(get('/rev?c=no-cache&x=60'), qr/HIT/, 'X-Accel-Expires on CC off');
+
+# Cache-Control caching extensions preserved after X-Accel-Expires
+
+TODO: {
+local $TODO = 'not yet' unless $t->has_version('1.23.0');
+
+my $time = time() - 1;
+like(get("/rev?c=max-age=60,stale-while-revalidate=60&x=\@$time"),
+ qr/STALE/, 'Cache-Control extensions after X-Accel-Expires');
+
+}
+
+###############################################################################
+
+sub get {
+ my ($uri) = @_;
+ http_get($uri);
+ http_get($uri);
+}
+
+###############################################################################
--
Sergey Kandaurov
_______________________________________________
nginx-devel mailing list -- nginx-devel@nginx.org
To unsubscribe send an email to nginx-devel-leave@nginx.org