I have a reverse nginx proxy where I want to route all request that come in with :
http://dns.com/content/xyz <—to—> http://dns.com/content/1.0/xyz
I have an upstream :
upstream backend_api.content.com {
server localhost:8080 max_fails=5 fail_timeout=30;
keepalive 100;
}
and location :
#Content Service
location ~* ^/content/?(.*) {
set $proxy_pass "http://backend_api.content.com";
rewrite ^/content/1.0(/.*)$ /content/1.0$1 break;
proxy_pass $proxy_pass
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host "api.stg.xxx.com";
proxy_set_header X-3scale-proxy-secret-token $secret_token;
proxy_set_header Original-Host $http_host;
proxy_set_header Authorization $outbound_auth_header;
proxy_set_header Original-Uri $scheme://$http_host$uri;
post_action /out_of_band_oauth_authrep_action;
}
but it seems like anything with http://dns/content/xyz fails and only when I give http://dns/content/1.0/xyz does it work.
You seem to be capturing part of the URI on the location ~* ^/content/?(.*) statement, but do nothing with it.
You also have a rewrite ^/content/1.0(/.*)$ /content/1.0$1 break; statement that does nothing, it simply writes the same URI back.
A quick and dirty solution might be to use two rewrite statements like this:
rewrite ^/content/1.0(/.*)$ /content/1.0$1 break;
rewrite ^/content(/.*)$ /content/1.0$1 break;
Which means that anything that does not match the first (non-) rewrite will be processed by the second, and get a /1.0 inserted.
Personally, I do not like it, and would rather use two location blocks:
location /content/1.0 {
set $proxy_pass "http://backend_api.content.com";
proxy_pass $proxy_pass;
proxy_http_version 1.1;
proxy_set_header ...
...
}
location /content {
rewrite ^/content(/.*)$ /content/1.0$1 last;
}
But check the evaluation order of your other location blocks. Note that prefix location blocks and regular expression location blocks have different evaluation rules. See this document for details.
Related
I would like to disable access logging for some specific paths but still proxy it to another container. In other words "match multiple locations without returning/exiting" which is not possible as far as I know.
The following config will make nginx cancel the request without entering the proxy pass location.
server {
# ...
# do not log requests for /_nuxt/* and /_ipx/*
location ~ ^/(_ipx|_nuxt) {
access_log off;
}
# still proxy these paths
location ~* ^(\/|\/(foo|bar|_nuxt|_ipx)$ {
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $server_name:$server_port;
}
}
Is there a more clean way of achieving the desired behavior other than duplicating the proxy configuration and adding the access log config line to that second location?
server {
# ...
# proxy pass without _nuxt and _ipx
location ~* ^(\/|\/(foo|bar)$ {
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $server_name:$server_port;
}
# access log + proxy pass
location ~ ^/(_ipx|_nuxt) {
access_log off;
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $server_name:$server_port;
}
}
You're right, location working like switch case taking the first hit and break.
Maybe you can try something like that:
if ($request_uri ~ ^/(_ipx|_nuxt)) {
access_log off;
}
instead of your first location statement.
The access_log directive has the following syntax:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]; ...
...
The if parameter (1.7.0) enables conditional logging. A request will not be logged if the condition evaluates to “0” or an empty string. In the following example, the requests with response codes 2xx and 3xx will not be logged:
map $status $loggable {
~^[23] 0;
default 1;
}
access_log /path/to/access.log combined if=$loggable;
Applied to the asked question, that means the following config should achieve the desired goal:
map $uri $loggable {
~^/_(ips|nuxt) 0;
default 1;
}
server {
...
access_log /path/to/access.log <format> if=$loggable;
}
I would like to do the following in my NGINX configuration: I want to proxy pass the path and query parameters but not include the first path parameter (path1).
Request URL
https://my-domain.com/path1/path2?query1=some-query
I want this to proxy_pass to
http://localhost:8000/path2?query1=some-query
I have tried with the following location block
location /path1/path2/ {
proxy_pass http://localhost:8000$request_uri;
proxy_http_version 1.1;
}
However, this does not go to the correct endpoint because I think it includes the path1 parameter too. I have several different path2 routes and so I want to be able to catch and redirect them all easily - without having to manually define each one like this:
location /path1/path2a/ {
proxy_pass http://localhost:8000/path2a?query1=some-query;
proxy_http_version 1.1;
}
location /path1/path2b/ {
proxy_pass http://localhost:8000/path2b?query1=some-query;
proxy_http_version 1.1;
}
location /path1/path2c/ {
proxy_pass http://localhost:8000/path2c?query1=some-query;
proxy_http_version 1.1;
}
ADDITIONAL EDIT:
I also cannot simply do
location /path1/ {
proxy_pass http://localhost:8000/;
proxy_http_version 1.1;
}
because I already have the location /path1/ block that gets upgraded to a WebSocket connection at a different endpoint:
location /path1/ {
proxy_pass http://localhost:9000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
I have searched a lot online but cannot find a configuration that works for my specific scenario.
This is really simple:
location /path1/ {
proxy_pass http://localhost:8000/;
proxy_http_version 1.1;
}
Read this Q/A for details.
Update
This solution isn't usable after OP clarifies his question.
If all of the additional paths share common suffix path2:
location /path1/path2 {
rewrite ^/path1(.*) $1 break; # remove '/path1' URI prefix
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
}
If they aren't, replace location /path1/path2 with location ~ ^/path1/(?:path2a|path2b|path2c).
If you need to pass to the backend query arguments that are different from those came with the request, use
set $args query1=some-query;
within the location block.
I have some issues with a "basic" rewriting rule under a proxy_pass location type :
location ~* /test1/network/v1/operator/ke3/dataUp {
rewrite ^(?<begin>/test1/network/v1/operator/ke3/dataUp)(?<parametersPart>.*)(?<mustDie>/dataUp)$ $parametersPart break;
proxy_pass http://server_preproduction;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Host $host;
}
I expect any calls sent to : .../test1/network/v1/operator/ke3/dataUp?param1=GHJ¶m2=865/dataUp
To be equal to : .../test1/network/v1/operator/ke3/dataUp?param1=GHJ¶m2=865
So I just want to parse the parameters section in order to remove any extra /dataUp from the original request.
But when I try to use any kind of regex to do so, nginx seems to return to the location / and use the default request...
I'm sure that the proper location is use, becanse when I use a rewrite like : rewrite ^(?<begin>/test1/network/v1/operator/ke3/dataUp)(?<parametersPart>.*)$ TEST$parametersPart break;
The log on the proxy server received : TEST?param1=GHJ¶m2=865/dataUp
I do not add a / at the end of the proxy_pass because I want replace all the url.(but it's not mandatory ! I tried lot of combinations...)
If someone can save my day :p
Thanks !!
I find a way to manipulate the argument with a simple if statement...
if ($query_string ~ "^(?<argsok>/dataUp.*)(?<argsko>/dataUp)$") {
proxy_pass http://server_preproduction/$argsok;
}
Bug in the upstream vendor app. Wrote a route in our node app to proxy the request and avoid the bug but can't get the NGINX rewrite to work correctly. I've tried many variations of rewrite and now at my wit's end. Spent more time on the rewrite than the actual code... =(
IN: /Txtranscription/transcription/TranscriptionHandler.ashx?q=c3R1ZHlfaWQ...
OUT: /Txtranscription/transcription/TranscriptionHandler.ashx?q=c3R1ZHlfaWQ...
EXPECTED: /transcription?encoded=c3R1ZHlfaWQ...
### override handling of /Txtranscription/transcription/TranscriptionHandler.ashx
location /Txtranscription/transcription/TranscriptionHandler.ashx {
add_header Access-Control-Allow-Origin $cors_header;
access_log logs/vapi.proxy.log lfupstream;
error_log logs/vapi.error.log error;
rewrite ^/Txtranscription/transcription/TranscriptionHandler\.ashx\?q=(.*)$ /transcription?encoded=$1 break;
proxy_pass http://vapi;
}
You shouldn't need to rewrite the request at all, you can append a path to a proxy_pass directive and Nginx will replace the matching part of the location block from the original request URI with the URI of your proxy_pass directive.
So this should work:
location /Txtranscription/transcription/TranscriptionHandler.ashx {
set $args encoded=$arg_q;
....
proxy_pass http://vapi/transcription$is_args$args;
Example:
location ~ ^/connector(/?)(.*)$ {
proxy_buffer_size 64k;
proxy_buffers 16 32k;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
proxy_set_header Authorization "";
set $upstream_endpoint http://YOUR-END-POINT/$2$is_args$args;
proxy_pass $upstream_endpoint;
}
The magic is -> location ~ ^ /admin (/?)(.*)$
And then -> /$2$is_args$args;
Assuming I want to redirect URIs like
http://server1:8081/test/admin/option?options
http://server1:8081/test/admin/option/suboption?options
http://server1:8081/test/admin/option/suboption/subsuboption?options
to
http://server2:8080/tomcat/admin/option?options
http://server2:8080/tomcat/admin/option/suboption?options
http://server2:8080/tomcat/admin/option/suboption/subsuboption?options
what nginx rules I have to use? I've tried the following but it doesn't work
location =/test/admin {
proxy_pass http://server2:8080/tomcat/admin;
proxy_redirect off;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Try something along these lines ..
location /test/admin {
rewrite ^/test/admin(.*)$ /tomcat/admin$1;
}
location /tomcat/admin {
internal;
proxy_pass http://server2:8080;
[…]
}
That is, rewrite the requests to "tomcat/admin" which you can optionally make open to internal requests only.
In that location block, you can then proxy passthe request.