How to check substring using regular expression in Nginx config? - nginx

I try to check some parameters in request. Here is my url:
http://localhost:8080/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&LAYERS=004C0000064F&
STYLES=&WIDTH=256&HEIGHT=256&FORMAT=image%2fjpeg&CRS=EPSG%3a100000&DPI=96&
MAP_RESOLUTION=96&FORMAT_OPTIONS=dpi%3a96&
BBOX=1530569.52624839870259166%2c524135.21126760687911883%2c1531064.27656850102357566%2c524629.96158770937472582
I trying to get REQUEST parameter. Here is my nginx 1.12.1 config:
server {
listen 8080;
server_name 127.0.0.1 localhost;
set $site_backend localhost:56297;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location /favicon.ico {
error_page 403 404 = #tomcat_static_mapping;
}
location ~* /wms {
internal;
add_header URI $request_uri;
add_header X-debug-message1 "$request_uri" always;
if ($request_uri ~* REQUEST=([^&]*)) {
add_header X-debug-message2 "hi" always;
set $requesttype $1;
}
}
}
And in browser i got header:
X-debug-message1: /wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&LAYERS=004C0000064F&STYLES=&WIDTH=256&HEIGHT=256&FORMAT=image%2fjpeg&CRS=EPSG%3a100000&DPI=96&MAP_RESOLUTION=96&FORMAT_OPTIONS=dpi%3a96&BBOX=1530569.52624839870259166%2c524135.21126760687911883%2c1531064.27656850102357566%2c524629.96158770937472582
But not get X-debug-message2 header. I check regular expression here https://rubular.com/ and it's found match and return GetMap as like i want.
What can be wrong here?

Something is not complete / matching in your post. I got X-debug-message2: hi only which does match to how nginx has to behave:
These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level
For more intuitive outcome, use Headers-More module.
more_set_headers "URI: $request_uri";
more_set_headers 'X-debug-message1: "$request_uri"';
location ~* /wms {
if ($request_uri ~* REQUEST=([^&]*)) {
more_set_headers 'X-debug-message2: hi';
set $requesttype $1;
}
}

Related

Correct proxy configuration for nginx server to access rest api

I have a nginx-server configured as follows:
server {
listen 3000;
listen [::]:3000;
server_name .+;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
...
index index.html;
root /usr/share/nginx/html;
location /cam/ {
proxy_pass http://cam:8000/;
}
location /api {
proxy_pass https://some_ip:some_port;
proxy_pass_request_headers on;
proxy_set_header X-API-KEY xxxxx;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
proxy_ssl_server_name on;
}
location /share/ {
alias /usr/src/share;
}
location / {
try_files $uri $uri/ /index.html;
}
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
client_max_body_size 1M;
keepalive_timeout 10;
}
For displaying my frontend, this configuration works fine. The proxy for the cam is also working correctly.
I am getting problems in the configuration of the proxy for the api. The api has a sanity-check under "https://some_ip:some_port", which just returns "200: ok". Otherwise I should be able to make request using a fetch request such as
const res = await fetch(`api/subaddress/${system_id.toString()}/base`, {
method: 'POST',
headers: {
'Content-type': 'application/json',
'X-API-KEY': xxxxx,
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'HEAD, GET, POST, PUT, PATCH, DELETE',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token'
},
body: JSON.stringify(data_body),
});
Which, if successfull, returns "202: ok".
If I make such a request using curl, it works just fine (both of the requests), so the api should not be the problem.
At the current configuration, I get a "200: ok", which tells me that I have connected to the api, but the proxy does not take in account my subaddresses.
Besides the given configuration, I tried the following:
location /api {
proxy_pass https://some_ip:some_port$request_uri;
...
}
which always gives me "502: bad gateway"
location /api/ {
proxy_pass https://some_ip:some_port/;
...
}
which always gives me "403: forbidden"
location /api {
rewrite ^/api/(.*) /$1 break;
proxy_pass https://some_ip:some_port/$1;
...
}
which causes nginx to crash, as it tells me that it cannot resolve it. I would like to avoid using a resolver, unless definitly necessary (I have tried it using a resolver before too and it did not work either).
What is the correct way to accomplish this?
I solved this. Apparently the 403: forbidden was caused my some of the configurations of the proxy. After removing those, I did not get that error anymore.
In the end I used
location /api {
rewrite ^/api/(.*) /$1 break;
proxy_pass https://some_ip:some_port/$1;
...
}
which I made work by putting
resolver 1.1.1.1 valid=30s;
at the top of the configuration file.

Nginx how to set proxy pass using map based on the host and location

Currently I setting proxy pass dynamicaly using map directive. Now I would like for a specifc location /dcs/ I would like to set a different proxy pass rather than one mentioned through map.conf and proxy_pass.map. Is there a way to say use different map for a specific location /dcs/.
Should just use If stantement like if host is dev-api.mysite.com then set proxypass to http://abcdef.com. Is this the only option.
MySite.conf
server {
listen 80;
server_name ~^(api|dev-api|staging-api)\.mysite\.com$;
location / {
proxy_set_header Cookie "";
add_header Strict-Transport-Security "max-age=0; includeSubDomains" always;
proxy_hide_header 'Access-Control-Allow-Origin';
add_header 'Access-Control-Allow-Origin' '*' always;
include /etc/nginx/conf.d/headers.inc;
}
location /dcs/ {
set $proxy_host $host;
set $proxy_pass Set-different-host based of dev,staging,prod;
proxy_set_header Cookie "";
add_header Strict-Transport-Security "max-age=0; includeSubDomains" always;
proxy_hide_header 'Access-Control-Allow-Origin';
add_header 'Access-Control-Allow-Origin' '*' always;
include /etc/nginx/conf.d/headers.inc;
}
}
maps.conf
map $host $proxy_pass {
hostnames;
include /etc/nginx/conf.d/proxy_pass.map;
}
proxy_pass.map
# mysite.com
api.mysite.com myst.plat:8080;
staging-api.mysite.com staging.myst.plat:8081;
dev-api.mysite.com dev.plat:8080;
headers.inc
proxy_pass $upstream_proto://$proxy_pass;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Forwarded-Proto $real_scheme;
proxy_set_header X-Forwarded-Scheme $real_scheme;
proxy_set_header Host $proxy_host;
proxy_ssl_session_reuse on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-GeoIP-Country-Code $geoip_country_code;
proxy_set_header X-Site-Id $site_id;
add_header X-Cache-Time $date_gmt;
add_header X-Cache-Date $upstream_http_date;
add_header X-Proxy-Cache $upstream_cache_status;
# add_header X-Site-Id $site_id;
You can use several chained map blocks:
map $host $proxy_by_host {
hostnames;
include /etc/nginx/conf.d/proxy_pass.map;
}
map $uri $proxy_pass {
~^/dcs/ abcdef.com;
default $proxy_by_host;
}
Update
Looks like I slightly misunderstood your question, to use two different map blocks depending on request URI, use something like
map $host $proxy_by_host {
hostnames;
include /etc/nginx/conf.d/proxy_pass.map;
}
map $host $dcs_proxy_by_host {
hostnames;
include /etc/nginx/conf.d/dcs_proxy_pass.map;
}
map $uri $proxy_pass {
~^/dcs/ $dcs_proxy_by_host;
default $proxy_by_host;
}
This way if all the other parameters for your locations are equal, you can use only one location / { ... } for all requests.

Nginx Config for Camunda Webapp

I am configuring camunda webapp with nginx reverse proxy. Applications is loading perfectly fine using location / (Root Path). But I need to access it using a readable location path e.g. /process/. I tried a lot with several rewrites and redirections but to no success.
At root path all the static content loads but with other location path it fails. I'm a newbie in Nginx So it would make complete sense if i'm missing something very trivial.
Here is my config with location as Root Path:
server {
listen 8080;
server_name abc.xyz.net;
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
location / {
# Simple requests
if ($request_method ~* "(GET|POST)") {
add_header "Access-Control-Allow-Origin" *;
}
# Preflighted requests
if ($request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
return 200;
}
proxy_pass http://camunda-webapp.xyz.net;
proxy_set_header X-Forwarded-Host $host/;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass_request_headers on;
proxy_read_timeout 180s;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
On another context, If I try to give full URL in proxy_pass(Refer below config) then it works but the browser URL gets completely changed to proxy_pass URL.(I had even tried with proxy_redirect to retain the original URL but it doesn't work)
server {
listen 8080;
server_name abc.xyz.net;
rewrite_log on;
error_log /var/log/nginx/localhost.error_log notice;
location /process/ {
rewrite ^\/(?>[process]+)(\/.*) $1 break;
# Simple requests
if ($request_method ~* "(GET|POST)") {
add_header "Access-Control-Allow-Origin" *;
}
# Preflighted requests
if ($request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
return 200;
}
proxy_pass http://camunda-webapp.xyz.net/app/welcome/default;
proxy_redirect http://camunda-webapp.xyz.net/app/welcome/default https://abc.xyz.net/process
proxy_set_header X-Forwarded-Host $host/process;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass_request_headers on;
proxy_read_timeout 180s;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Any kind of info or help will be appreciated. Thanks in Advance.
Bella Ciao!
I think the trick is to specify the same location context of the nginx as the context path of the your application.
Also, please remove url rewrite as its not needed here.

NGINX: add_header for GET not working

The following (simplified) NGINX config results in OPTIONS calls correctly getting the Access-Control-Allow-Origin header headers in return, but GET not:
location / {
if ($request_method = OPTIONS ) {
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
return 204;
}
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
I've tried every combination in the location block, but nothing works, the only solution I could think of that works is moving the this line into the location #proxy_to_app section:
add_header 'Access-Control-Allow-Origin' '$http_origin' always;
It's like that proxy_to_app block is removing the added headers again.
As Alexey Ten stated, I moved add_header into location #proxy_to_app

Nginx - reverse proxy a Ghost blog with /subfolder redirect

I have a working nginx instance with the rules below. But I'm having difficulties pointing all the requests to domain.com/ghost
I tried modifying the location / {} block to location /ghost/ {} but with no success. I just get a 404 from the ghost app. Any suggestions?
server {
listen 80;
server_name domain.com;
root /home//user/ghost/;
index index.php;
# if ($http_host != "domain.com") {
# rewrite ^ http://domain.com$request_uri permanent;
# }
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:2368;
}
location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
access_log off;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, mustrevalidate, proxy-revalidate";
proxy_pass http://127.0.0.1:2368;
}
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
location ~ /\.ht {
deny all;
}
}
I'm using a regexp location directive for a similar proxy setup. This is the minified configuration file:
worker_processes 1;
pid /path/to/file.pid;
worker_priority 15;
events {
worker_connections 512;
accept_mutex on;
}
http {
server {
error_log /path/to/log/error.log error;
listen 127.0.0.1:9000;
server_name example.com;
location ~* (/ghost) {
expires epoch;
proxy_no_cache 1;
proxy_pass http://localhost:1234;
}
location / {
proxy_pass http://localhost:1234;
}
}
}
Have solved similar problem with other apps which have no support for subfolders. Both apps are built on one platform, so they both tries to work in /fx dir. I had to place one of them in to subfolder /gpms .
The idea is to redirect requests with referer from subfolder to destinations which links outside of subfolder - i just add subfolder to beginning of such uris. It is not ideal, but it works.
Here is my nginx config:
server {
listen 80;
server_name mydomain.com;
location / {
rewrite ^/$ /fx/;
proxy_pass http://127.0.0.1:56943/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300;
}
error_log /var/log/nginx/debug.log debug;
set $if_and_hack "";
if ( $http_referer ~ '^http://mydomain.com/gpms/.*$' ) {
set $if_and_hack "refgpms";
}
if ( $uri !~ '^/gpms/.*$' ) {
set $if_and_hack "${if_and_hack}_urinogpms";
}
if ( $if_and_hack = "refgpms_urinogpms" ) {
rewrite ^/(.*)$ http://$host/gpms/$1;
}
location /gpms/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cookie_path /fx /;
proxy_pass http://127.0.0.1:12788/fx/;
proxy_redirect default;
}
}
External links will be broken, but it is not critical for me and i guess it may be corrected.
$if_and_hack is for overcome nginx limitation on nested conditions.
By the way i have got a cookies issue, because they was set with path, and hit browser bug with not sending cookies for a new path after redirect, so i just remove path from cookies.
Note full link form in rewrite - this form of rewrite immediately redirects browser to new page, you should not change it to just "/gpms/$1".
As alternative, i guess, it may be possible to use nginx module to inspect html content and modify links. I have not tried this. Or consider to use subdomains instead of subfolders.
Good news! As of version 0.4.0 Ghost now supports subdirectory installation. And there are already people who've figured this out and created tutorials.

Resources