Varnish 4: Always miss - performance

I'm currently setting up Varnish 4 for my domain.
My Varnish caches all files like charm, except of the DOC-request.
But I can't figure out, why the DOC-request is always a "MISS".
I hope, that you guys can help me.
All details below. If you need more, tell me.
Thank you so much for your help!
Regards,
Hermsi
Varnish-Version:
/ # varnishd -V
varnishd (varnish-4.1.3 revision 5e3b6d2)
Copyright (c) 2006 Verdens Gang AS
Copyright (c) 2006-2015 Varnish Software AS
curl request:
$ curl -s -D - "https://www.example.com" -o /dev/null
HTTP/1.1 200 OK
Accept-Ranges: bytes
Age: 0
Cache-Control: max-age=0
Content-Type: text/html; charset=UTF-8
Date: Wed, 15 Nov 2017 20:25:14 GMT
Expires: Wed, 15 Nov 2017 20:25:14 GMT
Vary: Accept-Encoding
X-Cache: MISS
X-Cache-Age:
X-Cache-Grace:
X-Cache-Ttl-Remaining:
X-Hits: 0
X-Host: example.com
X-Varnish-Cookie-Debug: Cleaned request cookies:
Transfer-Encoding: chunked
Varnishlog:
* << BeReq >> 786983
- Begin bereq 786982 pass
- Timestamp Start: 1510849297.605099 0.000000 0.000000
- BereqMethod GET
- BereqURL /
- BereqProtocol HTTP/1.1
- BereqHeader Host: www.example.com
- BereqHeader User-Agent: curl/7.26.0
- BereqHeader Accept: */*
- BereqHeader X-Forwarded-Host: www.example.com
- BereqHeader X-Forwarded-Port: 443
- BereqHeader X-Forwarded-Proto: https
- BereqHeader X-Forwarded-Server: lb-proxy-1
- BereqHeader X-Real-Ip: XXX.XX.XXX.XXX
- BereqHeader X-Forwarded-For: XXX.XX.XXX.XXX
- BereqHeader Accept-Encoding: gzip
- BereqHeader X-Device: desktop
- BereqHeader X-Varnish: 786983
- VCL_call BACKEND_FETCH
- VCL_return fetch
- BackendOpen 23 boot.default XXX.XX.XXX.XXX 80 10.42.70.133 39122
- BackendStart XXX.XX.XXX.XXX 80
- Timestamp Bereq: 1510849297.619798 0.014699 0.014699
- Timestamp Beresp: 1510849297.676958 0.071859 0.057160
- BerespProtocol HTTP/1.1
- BerespStatus 200
- BerespReason OK
- BerespHeader Date: Thu, 16 Nov 2017 16:21:37 GMT
- BerespHeader Server: Apache
- BerespHeader Cache-Control: max-age=0
- BerespHeader Expires: Thu, 16 Nov 2017 16:21:37 GMT
- BerespHeader Vary: Accept-Encoding
- BerespHeader Content-Encoding: gzip
- BerespHeader Content-Length: 3252
- BerespHeader Content-Type: text/html; charset=UTF-8
- TTL RFC 0 10 -1 1510849298 1510849298 1510849297 1510849297 0
- VCL_call BACKEND_RESPONSE
- BerespHeader X-Varnish-Cookie-Debug: Cleaned request cookies:
- BerespHeader x-url: /
- BerespHeader x-host: www.example.com
- BerespHeader X-Cache: ZIP
- BereqHeader stale-while-revalidate: max-age=0
- TTL VCL -1 7200 0 1510849298
- TTL VCL 120 7200 0 1510849298
- VCL_return deliver
- Storage malloc Transient
- ObjProtocol HTTP/1.1
- ObjStatus 200
- ObjReason OK
- ObjHeader Date: Thu, 16 Nov 2017 16:21:37 GMT
- ObjHeader Server: Apache
- ObjHeader Cache-Control: max-age=0
- ObjHeader Expires: Thu, 16 Nov 2017 16:21:37 GMT
- ObjHeader Vary: Accept-Encoding
- ObjHeader Content-Encoding: gzip
- ObjHeader Content-Length: 3252
- ObjHeader Content-Type: text/html; charset=UTF-8
- ObjHeader X-Varnish-Cookie-Debug: Cleaned request cookies:
- ObjHeader x-url: /
- ObjHeader x-host: www.example.com
- ObjHeader X-Cache: ZIP
- Fetch_Body 3 length stream
- Gzip u F - 3252 10723 80 80 25946
- BackendReuse 23 boot.default
- Timestamp BerespBody: 1510849297.677148 0.072049 0.000190
- Length 3252
- BereqAcct 328 0 328 247 3252 3499
- End
* << Request >> 786982
- Begin req 786981 rxreq
- Timestamp Start: 1510849297.605008 0.000000 0.000000
- Timestamp Req: 1510849297.605008 0.000000 0.000000
- ReqStart 10.42.115.200 35666
- ReqMethod GET
- ReqURL /
- ReqProtocol HTTP/1.1
- ReqHeader Host: www.example.com
- ReqHeader User-Agent: curl/7.26.0
- ReqHeader Accept: */*
- ReqHeader X-Forwarded-For: XXX.XX.XXX.XXX
- ReqHeader X-Forwarded-Host: www.example.com
- ReqHeader X-Forwarded-Port: 443
- ReqHeader X-Forwarded-Proto: https
- ReqHeader X-Forwarded-Server: lb-proxy-1
- ReqHeader X-Real-Ip: XXX.XX.XXX.XXX
- ReqHeader Accept-Encoding: gzip
- ReqUnset X-Forwarded-For: XXX.XX.XXX.XXX
- ReqHeader X-Forwarded-For: XXX.XX.XXX.XXX, 10.42.115.200
- VCL_call RECV
- ReqUnset X-Forwarded-For: XXX.XX.XXX.XXX, 10.42.115.200
- ReqHeader X-Forwarded-For: XXX.XX.XXX.XXX
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqHeader Cookie:
- ReqUnset Cookie:
- ReqUnset Accept-Encoding: gzip
- ReqHeader Accept-Encoding: gzip
- ReqHeader X-Device: desktop
- VCL_return hash
- VCL_call HASH
- VCL_return lookup
- Debug "XXXX HIT-FOR-PASS"
- HitPass 786980
- VCL_call PASS
- VCL_return fetch
- Link bereq 786983 pass
- Timestamp Fetch: 1510849297.677182 0.072175 0.072175
- RespProtocol HTTP/1.1
- RespStatus 200
- RespReason OK
- RespHeader Date: Thu, 16 Nov 2017 16:21:37 GMT
- RespHeader Server: Apache
- RespHeader Cache-Control: max-age=0
- RespHeader Expires: Thu, 16 Nov 2017 16:21:37 GMT
- RespHeader Vary: Accept-Encoding
- RespHeader Content-Encoding: gzip
- RespHeader Content-Length: 3252
- RespHeader Content-Type: text/html; charset=UTF-8
- RespHeader X-Varnish-Cookie-Debug: Cleaned request cookies:
- RespHeader x-url: /
- RespHeader x-host: www.example.com
- RespHeader X-Cache: ZIP
- RespHeader X-Varnish: 786982
- RespHeader Age: 0
- RespHeader Via: 1.1 varnish-v4
- VCL_call DELIVER
- RespUnset x-url: /
- RespUnset x-host: www.example.com
- RespUnset X-Cache: ZIP
- RespHeader X-Cache: MISS
- RespHeader X-Hits: 0
- RespHeader X-Host: example.com
- RespUnset Server: Apache
- RespUnset X-Varnish: 786982
- RespUnset Via: 1.1 varnish-v4
- RespHeader X-Cache-TTL-Remaining:
- RespHeader X-Cache-Age:
- RespHeader X-Cache-Grace:
- VCL_return deliver
- Timestamp Process: 1510849297.677222 0.072215 0.000040
- RespHeader Accept-Ranges: bytes
- Debug "RES_MODE 2"
- RespHeader Connection: keep-alive
- Timestamp Resp: 1510849297.677275 0.072268 0.000053
- ReqAcct 290 0 290 446 3252 3698
- End
This is my VCL:
vcl 4.0;
import std;
include "cache_invalidation.vcl";
include "custom_subroutines.vcl";
backend default {
.host = "VARNISH_BACKEND_ADDRESS"; # IP or Hostname of backend
.port = "VARNISH_BACKEND_PORT"; # Port Apache or whatever is listening
.connect_timeout = 5s; # Wait a maximum of 5s for backend connection (Apache, Nginx, etc...)
.first_byte_timeout = 10s; # Wait a maximum of 10s for the first byte to come from your backend
.between_bytes_timeout = 2s; # Wait a maximum of 2s between each bytes sent
.max_connections = 300; # Max parallel connections to our backend
}
sub vcl_recv {
# IP forwarding.
if (req.restarts == 0) {
if (req.http.X-Forwarded-For && !req.http.X-Real-IP) {
set req.http.X-Real-IP = regsub(req.http.X-Forwarded-For, ".*\b(?!10|127|172)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*", "\1");
}else{
set req.http.X-Forwarded-For = req.http.X-Real-IP;
}
}
# Enforce redirect to HTTPS
if (req.http.X-Forwarded-Proto !~ "(?i)https") {
return(synth(720, "https://" + req.http.host + req.url));
}
# Remove the Google Analytics added parameters, useless for our backend
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
set req.url = regsub(req.url, "\?&", "?");
set req.url = regsub(req.url, "\?$", "");
}
# Remove anchor or hash references
if(req.url ~ "\#"){
set req.url = regsub(req.url, "\#.*$", "");
}
# Remove incomplete query string
if(req.url ~ "\?$"){
set req.url = regsub(req.url, "\?$", "");
}
# Remove Google Analytics Cookies, our server does not need it
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
# Remove DoubleClick offensive cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
# Remove the AddThis cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
# Remove a ";" prefix in the cookie if present
set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");
# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^\s*$") {
unset req.http.cookie;
}
if (req.url ~ "^[^?]*\.(bmp|bz2|css|doc|eot|flv|gif|gz|ico|jpeg|jpg|js|less|pdf|png|rtf|swf|txt|woff|xml)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
if (req.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av]|webm)(\?.*)?$") {
unset req.http.Cookie;
return (hash);
}
if(req.http.Accept-Encoding)
{
if(req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp[34]|ogg)$")
{
# No point compressing these extensions
unset req.http.Accept-Encoding;
} elsif(req.http.Accept-Encoding ~ "gzip")
{
set req.http.Accept-Encoding = "gzip";
} elsif(req.http.Accept-Encoding ~ "deflate")
{
set req.http.Accept-Encoding = "deflate";
} elsif(req.http.Accept-Encoding ~ "sdch")
{
set req.http.Accept-Encoding = "sdch";
} else
{
# Unknown Algorithm
unset req.http.Accept-Encoding;
}
}
}
# At this point, it is our last chance to make some decision (set|unset|mod) about some header that the backend should see.
sub vcl_backend_fetch {
unset bereq.http.X-Varnish-SESS-ID;
}
sub vcl_hit {
# Custom Headers for debug purposes
set req.http.X-Cache-TTL-Remaining = obj.ttl;
set req.http.X-Cache-Age = obj.keep - obj.ttl;
set req.http.X-Cache-Grace = obj.grace;
}
sub vcl_backend_response {
if (bereq.url ~ "^[^?]*\.(mp[34]|rar|tar|tgz|gz|wav|zip|bz2|xz|7z|avi|mov|ogm|mpe?g|mk[av]|webm)(\?.*)?$") {
unset beresp.http.set-cookie;
set beresp.do_stream = true; # Check memory usage it'll grow in fetch_chunksize blocks (128k by default) if the backend doesn't send a Content-Length header, so only enable it for big objects
set beresp.do_gzip = false; # Don't try to compress it for storage
}
# Do not Gzip image files in Varnish
if (beresp.http.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|mp4|ogg|swf)$") {
set beresp.do_gzip = false;
}
else {
set beresp.do_gzip = true;
set beresp.http.X-Cache = "ZIP";
}
# GZip the cached content if possible
if (beresp.http.content-type ~ "text") {
set beresp.do_gzip = true;
}
# If we are performing a redirection 301 / 302 from the backend and our web server and varnish instances are in the same node, apache mod_rewrite could append it's port
# typically varnish :80 apache/nginx/lighthttp :8080, so the redirect can then often redirect the end-user to a URL on :8080, where it should be :80.
if(beresp.status == 301 || beresp.status == 302) {
set beresp.http.Location = regsub(beresp.http.Location, ":[0-9]+", "");
}
# The example below is explained in detail in load_balancing.vcl as part of one of the strategies that we can take to handle Varnish Grace Mode
set bereq.http.stale-while-revalidate = regsub(beresp.http.Cache-Control, ".*stale-while-revalidate\=([0-9]+).*", "\1");
if(std.real(bereq.http.stale-while-revalidate, 0.0) > 0)
{
set beresp.grace = std.duration(bereq.http.stale-while-revalidate + "s", 10s);
} else {
set beresp.grace = 2h;
}
}
sub vcl_deliver {
# At this point this is our last change to set or unset the response headers before deliver it
if (obj.hits > 0)
{
set resp.http.X-Cache = "HIT";
} else
{
set resp.http.X-Cache = "MISS";
}
set resp.http.X-Hits = obj.hits;
# Remove www of our host in the backend response
set resp.http.X-Host = regsub(req.http.host, "^www\.", "");
# Remove PHP , Apache and Varnish versions
unset resp.http.x-powered-by;
unset resp.http.Server;
unset resp.http.X-Varnish;
unset resp.http.Via;
# Here we are ensuring to add this headers in the response (defined in the hit subroutine) for debug purposes
set resp.http.X-Cache-TTL-Remaining = req.http.X-Cache-TTL-Remaining;
set resp.http.X-Cache-Age = req.http.X-Cache-Age;
set resp.http.X-Cache-Grace = req.http.X-Cache-Grace;
}

The varnish log you are providing does not match the curl request you are doing (wrong user agent for example).
If it is still relevant, in your varnishlog you can see that the backend request contains the headers :
BereqHeader Cache-Control: no-cache
BereqHeader Pragma: no-cache
and the backend response contains the following
BerespHeader Cache-Control: max-age=0
which prevent Varnish from caching the response.
Can you share the varnish log part for the Request (not the BackendRequest) ?
Without it, my guess could be that you always get a miss because the builtin.vcl make your request a pass (you do not do any return (pass) in your conf nonetheless the backend request comes from the pass state
Begin bereq 1048612 pass
It could be triggered by these two rules in the builtin.vcl :
if (req.method != "GET" && req.method != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
/* Not cacheable by default */
return (pass);
}
EDIT
That's weird. You should not have any Cookie using Curl.
Try scoping your cookie handling code and use req.http.Cookie (with an uppercase C) like this :
if (req.http.Cookie) {
# Remove Google Analytics Cookies, our server does not need it
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_ga=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "_gat=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmctr=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmcmd.=[^;]+(; )?", "");
set req.http.Cookie = regsuball(req.http.Cookie, "utmccn.=[^;]+(; )?", "");
# Remove DoubleClick offensive cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__gads=[^;]+(; )?", "");
# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");
# Remove the AddThis cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__atuv.=[^;]+(; )?", "");
# Remove a ";" prefix in the cookie if present
set req.http.Cookie = regsuball(req.http.Cookie, "^;\s*", "");
# Are there cookies left with only spaces or that are empty?
if (req.http.Cookie ~ "^\s*$") {
unset req.http.Cookie;
}
}
Another thing here, in your vcl log you can see that Varnish is doing Hit-For-Pass, that is, Varnish is caching the fact that your request is not cached. If you want to truly test, you'll need to purge the content beforehands.
One last thing : your backend server (apache) responds with a Cache-Control : max-age =0 header which prevent caching, you should change that if you want to cache content.

Related

Varnish: ban URL with any GET parameters

I'm using Varnish cache 6.0.6. Sometimes I need to invalidate cache based on URL ignoring GET params and any headers. I use BAN command for this.
GET commands to retrieve content. The results they receive are different.
curl --user login:secret 'http://example.com/v1/account/123'
curl --user login2:secret2 'http://example.com/v1/account/123?origin=abc'
BAN command to ban both cache.
curl -X BAN example.com -H "X-Ban: /v1/account/123"
Varnish config
if (req.method == "BAN") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed"));
}
ban("obj.http.x-host == " + req.http.host + " && obj.http.x-url ~ " + req.http.X-Ban);
return (synth(200, "Ban added"));
}
However ban command invalidates cache only for the first request. The second request stays cached.
How can I invalidate everything that starts with ^/v1/account/123?
I've tested it on a local setup and it does seem to work without any need for changes.
Initial cached request:
Here's the initial request, you can see that Age: 35 means the item has been stored in cache for 35 seconds.
➜ ~ curl -I localhost/v1/account/123\?origin=abc
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Fri, 15 May 2020 07:26:59 GMT
Content-Length: 216
x-host: localhost
x-url: /v1/account/123?origin=abc
X-Varnish: 32788 32786
Age: 35
Via: 1.1 varnish (Varnish/6.0)
Accept-Ranges: bytes
Connection: keep-alive
Ban request
The next request issues the ban, using the exact syntax you described in your VCL:
➜ ~ curl -X BAN localhost -H "X-Ban: /v1/account/123"
<!DOCTYPE html>
<html>
<head>
<title>200 Ban added</title>
</head>
<body>
<h1>Error 200 Ban added</h1>
<p>Ban added</p>
<h3>Guru Meditation:</h3>
<p>XID: 14</p>
<hr>
<p>Varnish cache server</p>
</body>
</html>
The results
When I execute the initial curl call again, the Age header is reset to zero, which means the page was not served from cache. Which is the desired outcome.
➜ ~ curl -I localhost/v1/account/123\?origin=abc
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Fri, 15 May 2020 07:40:23 GMT
Content-Length: 213
x-host: localhost
x-url: /v1/account/123?origin=abc
X-Varnish: 16
Age: 0
Via: 1.1 varnish (Varnish/6.0)
Accept-Ranges: bytes
Connection: keep-alive
VCL
This is the full VCL is use for this example. Please adjust backend & ACL settings to your needs.
Please make sure x-host & x-url are properly set in sub vcl_backend_response, otherwise your ban statement will not be able to match those values. This is what we call Lurker-friendly bans.
vcl 4.0;
backend default {
.host="localhost";
.port="8080";
}
acl purge {
"localhost";
}
sub vcl_recv {
if (req.method == "BAN") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed"));
}
ban("obj.http.x-host == " + req.http.host + " && obj.http.x-url ~ " + req.http.X-Ban);
return (synth(200, "Ban added"));
}
}
sub vcl_backend_response {
set beresp.http.x-host = bereq.http.host;
set beresp.http.x-url = bereq.url;
}

Mod_security - help needed

I need help configuring mod_security. I installed the component in joomla CMS. One function does not work. I think it's the fault of configuring mod_security. However, I can't handle the configuration.
Can anyone suggest me how to configure mod_security so that the following error does not appear?
Thank you for any suggestions
greetings
Mariusz
--70c75e19-H--
Apache-Handler: application/x-httpd-php
Stopwatch: 1576492965429719 55389 (- - -)
Stopwatch2: 1576492965429719 55389; combined=3, p1=0, p2=0, p3=0, p4=0, p5=3, sr=0, sw=0, l=0, gc=0
Producer: ModSecurity for Apache/2.9.2 (http://www.modsecurity.org/); OWASP_CRS/2.2.9.
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
--70c75e19-Z--
--f4ebab2d-A--
[16/Dec/2019:11:43:18 +0100] Xfdfxt4HssQCZkLHjRnp17QAAAAA 192.168.11.19 54334 222.222.222.222 443
--f4ebab2d-B--
POST /administrator/index.php?option=**com_arismartbook**&task=ajaxOrderUp&categoryId=16 HTTP/1.1
Host: test2.tld.pl
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: */*
Accept-Language: pl,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded
Content-Length: 119
Origin: https://test2.tld.pl
Connection: keep-alive
Referer: https://test2.tld.pl/administrator/index.php?option=com_arismartbook&view=categories
Cookie: wf_browser_dir=eczasopisma/Akcent/Rok_2014/nr1; cookieconsent_status=dismiss; e8c44a98a762cac37a9dc36fe9daa126=pl0h5nbstk465jhgoohn1kc5m9; joomla_user_state=logged_in; b00894f58bebfc7f2swE6f509b1869a6=dvkignad5f8r2fn9mkt1v5kca6
--f4ebab2d-F--
HTTP/1.1 500 Internal Server Error
X-Content-Type-Options: nosniff
X-Powered-By: PHP/7.2.25
Cache-Control: no-cache
Pragma: no-cache
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
--f4ebab2d-H--
Apache-Handler: application/x-httpd-php
Stopwatch: 1576492998778551 50173 (- - -)
Stopwatch2: 1576492998778551 50173; combined=3, p1=0, p2=0, p3=0, p4=0, p5=3, sr=0, sw=0, l=0, gc=0
Producer: ModSecurity for Apache/2.9.2 (http://www.modsecurity.org/); OWASP_CRS/2.2.9.
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
--f4ebab2d-Z--

nginx proxy_cache key hash change on each another browser request

I was create config of nginx like:
proxy_cache_path /tmp/nginx/static levels=1:2 keys_zone=static_zone:10m inactive=10d use_temp_path$
proxy_cache_key "$request_uri$args";
location ~* \.(css|gif|ico|jpe?g|js(on)?|png|svg|webp|ttf|woff|woff2|txt|map)$ {
proxy_hide_header Date;
proxy_cache_revalidate on;
proxy_pass http://static:8080;
proxy_cache_bypass $cookie_nocache $arg_nocache;
proxy_ignore_headers "Cache-Control" "Expires" "Set-Cookie";
proxy_hide_header "Set-Cookie";
proxy_buffering on;
proxy_cache static_zone;
proxy_cache_valid 200 301 302 30m;
proxy_cache_valid 404 10m;
#expires max;
add_header X-Proxy-Cache $upstream_cache_status;
access_log off;
add_header Cache-Control "public";
add_header Pragma "public";
expires 30d;
log_not_found off;
tcp_nodelay off;
}
On first request from Chrome all work as excepted x-proxy-cache:MISS other request got from disk cache with header x-proxy-cache:HIT. After refresh it's also HIT. But when I open page from other browsers(Opera,Edge) on this machine this request is MISS. In file system nginx create two files with different md5sum hash on a same content. For example filename 438476ac40665c852d3acde1acf769f1 head:
^C^#^#^#^#^#^#^#/^V
W^#^#^#^#��^CW^#^#^#^#'^O
W^#^#^#^#m�,�^#^#�^#�^A^N"5703e3a7-67e"^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#$
KEY: /js/catalog.js
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Apr 2016 15:07:19 GMT
Content-Type: application/javascript
Content-Length: 1662
Last-Modified: Tue, 05 Apr 2016 16:11:19 GMT
Connection: close
Vary: Accept-Encoding
ETag: "5703e3a7-67e"
Accept-Ranges: bytes
The second filename a6f57423c2220fba3ada5f516f6dd91c with a same content and this head:
^C^#^#^#^#^#^#^# ^V
W^#^#^#^#��^CW^#^#^#^#^A^O
W^#^#^#^#m�,�^#^#�^#�^A^N"5703e3a7-67e"^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#$
KEY: /js/catalog.js
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 12 Apr 2016 15:06:41 GMT
Content-Type: application/javascript
Content-Length: 1662
Last-Modified: Tue, 05 Apr 2016 16:11:19 GMT
Connection: close
Vary: Accept-Encoding
ETag: "5703e3a7-67e"
Accept-Ranges: bytes
By documentation the name of file must be md5 from key, and there is echo -n '/js/catalog.js'| md5sum is a6f57423c2220fba3ada5f516f6dd91c as name of one of files (it was first request). I don't want to cache in server js|css per each user|browser. Just cache it once and receive from cache to all users requests. P.S. My site use https, http2, version of nginx 1.9.14.
Based on the Vary: Accept-Encoding header that's there, I would guess that Edge and Opera send different "Accept-Encoding" headers for the request. For example, one may simply send "gzip" while the other sends "gzip, deflate". Those are technically different Accept-Encoding request headers.
If you know that the origin won't send meaningfully different encodings that won't work between browsers you can add:
proxy_ignore_headers Vary;
You already have the proxy_ignore_headers, so you can probably just add to that.
Since all major browsers support gzip, the risk is likely very low. However, "webp" is also done via the Accept-Encoding, so that could create surprising results for some images if the origin can handle webp.
TLDR: Request Header Accept-Encoding matters.
Consider its normal value : Accept-Encoding: gzip, deflate, br.
When you change it to Accept-Encoding: gzip, deflate, lolkek then Nginx will store cached response in different file. And those 2 files ( under /var/cache/nginx/) will be of the same content but with different names.
The same issue: https://trac.nginx.org/nginx/ticket/1840

Nginx mod_rewrite $request_uri manipulation

I would like to do some redirects but involving the $args.
I am trying to to the following:
rewrite /aaa?a=1&aa=2 /bbb?b=1&bb=2 permanent;
But it does not work. The line below works fine, though
rewrite /aaa /bbb permanent;
I added those lines to my config file:
proxy_set_header x-request_uri "$request_uri";
proxy_set_header x-args "$args";
And I can see those headers:
GET /aaa?a=1&aa=2 HTTP/1.0
Host: www.example.com
x-request_uri: /aaa?a=1&aa=2
x-args: a=1&aa=2
Connection: close
User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Accept: */*
What I am doing wrong? is there a way to accomplish redirect taking full $request_uri in consideration?
I've got the answer on irc.freenode.net #nginx:
Mod_rewrite does not match against url-with-args only without, use if or map instead.
I managed to get it working with if:
if ( $request_uri = '/aaa?a=1&aa=2' ){
return 301 $scheme://$host/bbb?b=1&bb=2;
}
Response header:
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.0.15
< Date: Wed, 02 Jul 2014 20:05:34 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< Location: http://www.example.com/bbb?b=1&bb=2
< x-uri: /aaa?a=1&aa=2

GZIP encoding in Jersey 2 / Grizzly

I can't activate gzip-encoding in my Jersey service. This is what I've tried:
Started out with the jersey-quickstart-grizzly2 archetype from the Getting Started Guide.
Added rc.register(org.glassfish.grizzly.http.GZipContentEncoding.class);
(have also tried rc.register(org.glassfish.jersey.message.GZipEncoder.class);)
Started with mvn exec:java
Tested with curl --compressed -v -o - http://localhost:8080/myapp/myresource
The result is the following:
> GET /myapp/myresource HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 zlib/1.2.3.4 ...
> Host: localhost:8080
> Accept: */*
> Accept-Encoding: deflate, gzip
>
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Sun, 03 Nov 2013 08:07:10 GMT
< Content-Length: 7
<
* Connection #0 to host localhost left intact
* Closing connection #0
Got it!
That is, despite Accept-Encoding: deflate, gzip in the request, there is no Content-Encoding: gzip in the response.
What am I missing here??
You have to register the org.glassfish.jersey.server.filter.EncodingFilter as well. This example enables deflate and gzip compression:
import org.glassfish.jersey.message.DeflateEncoder;
import org.glassfish.jersey.message.GZipEncoder;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.filter.EncodingFilter;
...
private void enableCompression(ResourceConfig rc) {
rc.registerClasses(
EncodingFilter.class,
GZipEncoder.class,
DeflateEncoder.class);
}
This solution is jersey specific and works not only with Grizzly, but with the JDK Http server as well.
Try the code like:
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(
BASE_URI, rc, false);
CompressionConfig compressionConfig =
httpServer.getListener("grizzly").getCompressionConfig();
compressionConfig.setCompressionMode(CompressionConfig.CompressionMode.ON); // the mode
compressionConfig.setCompressionMinSize(1); // the min amount of bytes to compress
compressionConfig.setCompressableMimeTypes("text/plain", "text/html"); // the mime types to compress
httpServer.start();

Resources