content-type related nginx expires header - nginx

Is it possible to set a content-type dependent expires header in nginx? I'm quite new to nginx and tried the following:
location ~ /files\.php$ {
...
if ($content_type = "text/css") {
add_header X-TEST1 123;
expires 7d;
}
if ($content_type = "image/png") {
add_header X-TEST2 123;
expires 30d;
}
if ($content_type = "application/javascript") {
add_header X-TEST3 123;
expires 1d;
}
#testing
if ($content_type != "text/css") {
add_header X-TEST4 abc;
}
#testing
if ($content_type = text/css) {
add_header X-TEST5 123;
}
}
But the only header added is "X-TEST4" on all requests.
I know about the other solution using file extension:
location ~* \.(ico|css|js|gif|jp?g|png)\?[0-9]+$
But it's not applicable for my application.

I think the code should be in location / { } instead of location ~ /files\.php$ { }...

Have you tried
$content_type ~= application/javascript
Also, make sure to read this:
http://wiki.nginx.org/IfIsEvil

If you have the lua module installed you could do something similar like this:
server {
location / {...}
header_filter_by_lua_block {
local cct = {} -- # cached content types
cct["text/css"] = true
cct["application/javascript"] = true
cct["application/x-javascript"] = true
cct["text/javascript"] = true
cct["image/jpeg"] = true
cct["image/png"] = true
cct["application/vnd.ms-fontobject"] = true
cct["application/font-woff"] = true
cct["application/x-font-truetype"] = true
cct["image/svg+xml"] = true
cct["application/x-font-opentype"] = true
if cct[ngx.header.content_type] ~= nil and ngx.header["expires"] == nil then
local now = os.time()
local expires = os.date("%a, %d-%b-%Y %H:%I:%S GMT", now+604800) -- # one week in seconds
ngx.header["expires"] = expires
end
}
}
Responses with the specified content-type will now get an expires-header.
When the response already has an expires-header the lua block will not touch the header.

Related

prometheus-nginxlog-exporter dosn't show correct statistics

i've just started to work with prometheus-nginxlog-exporter
https://github.com/martin-helmich/prometheus-nginxlog-exporter
my nginx.conf has only one change
log_format custom '$remote_addr - $remote_user [$time_local] $request_method "$request_uri " $status';
access_log /var/log/nginx/access.log custom;
I have two simple site
server {
listen 82;
server_name localhost;
access_log /var/log/nginx/access_default_site.log custom;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
upstream prom {
server 127.0.0.1:9090;
keepalive 15;
}
server {
listen 80;
location / {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/htpasswd.prom;
proxy_pass http://prom;
proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
}
}
etc/prometheus-nginxlog-exporter.hcl
listen {
port = 4040
}
namespace "nginx" {
source = {
files = [
"/var/log/nginx/access.log"
]
}
metrics_override = { prefix = "allnginx" }
namespace_label = "vhost"
format = "$remote_addr - $remote_user [$time_local] $request_method \"$request_uri\" $status"
labels {
app = "prod"
}
}
namespace "default" {
source = {
files = [
"/var/log/nginx/access_default_site.log"
]
}
metrics_override = { prefix = "allnginx" }
namespace_label = "vhost"
format = "$remote_addr - $remote_user [$time_local] $request_method \"$request_uri\" $status"
labels {
app = "test"
}
}
if check prometheus metrics
curl http://localhost:4040/metrics
output is
# HELP allnginx_http_response_count_total Amount of processed HTTP requests
# TYPE allnginx_http_response_count_total counter
allnginx_http_response_count_total{app="prod",method="",status="200",vhost="nginx"} 28
allnginx_http_response_count_total{app="prod",method="",status="302",vhost="nginx"} 7
allnginx_http_response_count_total{app="prod",method="",status="400",vhost="nginx"} 30
# HELP allnginx_parse_errors_total Total number of log file lines that could not be parsed
# TYPE allnginx_parse_errors_total counter
allnginx_parse_errors_total{vhost="default"} 0
allnginx_parse_errors_total{vhost="nginx"} 0
allnginx_http_response_count_total{app="prod",method="",status="200",vhost="nginx"} 28
Why is method empty? How to configure it correct?
How to get statistics about requests to location e.g. how many requests to "/", "/api"
as mentions in documentations
https://github.com/martin-helmich/prometheus-nginxlog-exporter#custom-labels-pass-through
we should you relabel
my working config is
listen {
port = 4040
}
namespace "nginx" {
source = {
files = [
"/var/log/nginx/access.log"
]
}
metrics_override = { prefix = "allnginx" }
namespace_label = "vhost"
format = "$remote_addr - $remote_user [$time_local] $request_method \"$request_uri\" $status"
relabel "method" { from = "request_method" }
relabel "request_uri" { from = "request_uri" }
labels {
app = "prod"
}
}
namespace "default" {
source = {
files = [
"/var/log/nginx/access_default_site.log"
]
}
metrics_override = { prefix = "allnginx" }
namespace_label = "vhost"
format = "$remote_addr - $remote_user [$time_local] $request_method \"$request_uri\" $status"
relabel "method" { from = "request_method" }
relabel "request_uri" { from = "request_uri" }
labels {
app = "test"
}
}
in metrics we can see somthing like this
allnginx_http_response_count_total{app="prod", instance="localhost:4040", job="nginx", method="DELETE", request_uri="/api/dashboards/uid/GLEY_3g7k", status="200", vhost="nginx"}
1
allnginx_http_response_count_total{app="prod", instance="localhost:4040", job="nginx", method="GET", request_uri="/", status="302", vhost="nginx"}
1
allnginx_http_response_count_total{app="prod", instance="localhost:4040", job="nginx", method="GET", request_uri="/", status="401", vhost="nginx"}
2
allnginx_http_response_count_total{app="prod", instance="localhost:4040", job="nginx", method="GET", request_uri="/api/alerts/states-for-dashboard?dashboardId=2", status="200", vhost="nginx"}
1
allnginx_http_response_count_total{app="prod", instance="localhost:4040", job="nginx", method="GET", request_uri="/api/alerts/states-for-dashboard?dashboardId=3", status="200", vhost="nginx"}

nginx + upstreams and switch upstreams by arg from url

I searched many forums , found many similar topics, but none works for me(
I have this configuration:
upstream 8083 { server 127.0.0.1:8083; }
upstream 8084 { server 127.0.0.1:8084; }
split_clients "upstream${remote_addr}" $default {
50% 8083;
50% 8084;
}
map $arg_upstream $upstream {
default $default;
"8083" "8083";
"8084" "8084";
}
location / {
if ($arg_upstream = "8083") {
proxy_pass http://8083;
break;
}
if ($arg_upstream = "8084") {
proxy_pass http://8084;
break;
}
proxy_pass http://$default;
}
But after going by url site/?upstream=8084 I have no switching to 8084 upstream.
If I test my config by changing to:
if ($arg_upstream = "8083") {
return 200 "upstream 8083"
}
if ($arg_upstream = "8084") {
return 200 "upstream 8084"
}
I see text perfectly like needed! Where am I going wrong?
Thanks!
this is answer to my question, it was decided by map 'http_cookies':
upstream default {
ip_hash;
server 127.0.0.1:8083;
server 127.0.0.1:8084;
}
upstream 8083 { server 127.0.0.1:8083; }
upstream 8084 { server 127.0.0.1:8084; }
map $arg_upstream $upstream {
'8083' '8083';
'8084' '8084';
default 'default';
}
map $http_cookie $upstream_cookie {
default '';
"~*upstream=(?<variable>[^;]+)" "$1";
}
and location part:
location / {
if ($upstream_cookie) { set $upstream $upstream_cookie; }
if ($arg_upstream) { add_header Set-Cookie upstream=$arg_upstream always; }
proxy_pass http://$upstream;
}

What is the priority level of multi prefix match in nginx

location ^~ /upload/images/ {
return 200;
}
location ^~ /admin/ {
return 300;
}
When I visit http://ip/admin/upload/images/pic.jpg , it return 300.
How could I do to make http://ip/admin/upload/images/pic.jpg and http://ip/upload/images/pic.jpg and http://ip/anyother/upload/images/pic.jpg return 200

Using variables in body_filter_by_lua_block

I am new to nginx, and I need to return altered request and from my understanding it is made in body_filter_by_lua_block scope by setting ngx.arg[1]. This is a simple base example of my usecase:
server {
listen 80;
server_name localhost;
location / {
body_filter_by_lua_block {
ngx.arg[1] = '{ "Subject": "someval" }'
ngx.arg[2] = true
}
}
}
My question is, how can "someval" be turned into a variable, i.e:
server {
listen 80;
server_name localhost;
location / {
set $someval "hello";
body_filter_by_lua_block {
ngx.arg[1] = '{ "Subject": "$someval" }'
ngx.arg[2] = true
}
}
}
Your nginx variable is available for get and set in the lua block with ngx.var.someval.

Varnish trailing slash rewrite

I'm trying to setup varnish to handle my default url which is example.url.co.uk.
If it hits example.url.co.uk or example.url.co.uk/ I want it to redirect or rewrite to example.url.co.uk/site which within the tomcat application sends it to a login page.
sub vcl_recv {
if ((req.url ~ "") || (req.url ~"^/")) {
set req.http.location = "https://example.url.co.uk/site" + req.url;
return (synth(750, "Found"));
}
}
sub vcl_synth {
if (resp.status == 301) {
set resp.http.Location = req.http.x-redir;
return (deliver);
}
if (resp.status == 750) {
set resp.http.Location = req.http.location;
set resp.status = 302;
return (deliver);
}
}
However when I use my attempt that this I get example.url.co.uk/site/site/site/site...
So I'm obviously stuck in a loop and I've been banging my head on this for a week trying to find the right solution! Please save me from my own stupidity I'm sure!
the problem is that req.url ~ "" matches everthing. as it is used as a regular expression. also your req.url ~ "^/" is too open.
changing it to:
if (req.url == "" || req.url ~"^/$") {
should fix it, verifying that it is either empty or / it self.
here is a simple varnishtest to verify the behaviour:
varnishtest "Test Redirect"
server s1 {
rxreq
txresp
rxreq
txresp
} -start
varnish v1 -vcl+backend {
sub vcl_recv {
if (req.url == "" || req.url ~"^/$") {
set req.http.location = "https://example.url.co.uk/site" + req.url;
return (synth(750, "Found"));
}
}
sub vcl_synth {
if (resp.status == 301) {
set resp.http.Location = req.http.x-redir;
return (deliver);
}
if (resp.status == 750) {
set resp.http.Location = req.http.location;
set resp.status = 302;
return (deliver);
}
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.status == 302
} -run
client c1 {
txreq -url "/site"
rxresp
expect resp.status == 200
} -run
you can run it with varnishtest test.vtc

Resources