I need to set proxy_pass for the below url pattern.
location ~ ^/hosts/bu/(.*)/app/(.*)$ {
proxy_pass http://appserver.cnma.com:3000/hosts/bu/$1/app/$2;
}
When I try with the URL it does not pass the second parameter correctly. Please let me know where I am going wrong.
Orig docs say:
If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:
location /some/path/ {
proxy_pass http://127.0.0.1;
}
So there is enough:
proxy_pass http://appserver.cnma.com:3000$request_uri;
you can use named capture in nginx while using regular expressions
location ~ ^/hosts/bu/(.*)/app/(.*)$ {
proxy_pass http://appserver.cnma.com:3000/hosts/bu/$1/app/$2;
}
You can modify block to below like this
location ~ ^/hosts/bu/(?<loc1>.+)/app/(?<loc2>.+)$ {
proxy_pass http://appserver.cnma.com:3000/hosts/bu/$1/app/$loc2;
}
Related
I need to get the host address from the request and redirect to another host with the rewritten address, but in all possible ways I failed
Here's an example (one of the attempts):
location / {
proxy_pass http://...;
...
}
location /service/(.*)$/ {
rewrite /service/$1/(.*)$ /$2 break;
proxy_pass http://$1.localhost:8080/;
...
}
Works only if hardcoded:
location /service/hostaname/ {
rewrite /service/hostaname/(.*)$ /$1 break;
proxy_pass http://hostaname.localhost:8080/;
...
}
But this is not a suitable solution for me
Help meeeeeee, thanks!
Your location syntax is invalid, as it is missing the regular expression operator. The rewrite statement contains an invalid regular expression.
You do not need the rewrite statement as you can extract the parts of the URI from the location statement.
For example:
location ~ ^/service/([^/]+)/(.*)$ {
proxy_pass http://$1.localhost:8080/$2;
}
You may need to define a resolver statement as the proxy_pass contains variables. See this document for details.
I am trying to use variable to set the hostname in a proxy_pass, but once I try that, the path after the location is ignored.
If I try and get localhost:8001/dirA/x/y/z.html. The following returns the file from http://server1:8888/dirB/dirC/x/y/z.html. This is what I expect to happen.
location ^~ /dirA/ {
proxy_pass http://server1:8888/dirB/dirC/;
But if I try the following config which is just using a variable for hostname... and try and get localhost:8001/dirA/x/y/z.html
location ^~ /dirA/ {
set $endpoint server1;
proxy_pass http://$endpoint:8888/dirB/dirC/;
I get http://server1:8888/dirB/dirC/index.html returned instead.
That's just how proxy_pass works. If you use a variable in the value, you need to provide the entire URI. See this document for details;
You could use a regular expression location. For example:
location ~ ^/dirA/(.*)$ {
set $endpoint server1;
proxy_pass http://$endpoint:8888/dirB/dirC/$1;
}
Note that the order of regular expression locations is significant. See this document for details.
Alternatively, a rewrite...break should also work.
location ^~ /dirA/ {
set $endpoint server1;
rewrite ^/dirA/(.*)$ /dirB/dirC/$1 break;
proxy_pass http://$endpoint:8888;
}
I need to route traffic based on the http request origin. I have two environments and we need to redirect every http request for "/us-en" to Environment1 and others to Environment2 using "$http_referer".
Redirection based on location works.
location ~ /us-en {
proxy_pass Environment1;
proxy_set_header Host Environment1;
}
With '$http_referer' the below option does not work. Request your suggestion on the same.
if ($http_referer ~ ^https?://dev.xyz.com/us-en){
rewrite ^/us-en(/*)$ HOME_PAGE$1 break;
proxy_pass Environment1;
}
Error: nginx: [emerg] "proxy_pass" directive is not allowed here in /opt/nginx/conf/nginx.conf.
Note: By default all the traffic goes to Environment2 as an upstream configuration is present.
# needed if your proxy destination specified with domain name instead of IP address
resolver 8.8.8.8;
location /home/ {
proxy_set_header Host HOST1;
# setup other proxied headers if needed
if ($http_referer ~ ^https?://dev.xyz.com/home) {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_pass https://HOST1:8080; # this can be specified by IP address
}
}
With such configuration requests to your_domain.com/home/path/file from dev.xyz.com/home/... (but not from dev.xyz.com/any/other/path!) will be proxied to https://HOST1:8080/HOME_PAGE/path/file. If you specify your proxy destination with domain name instead of IP address, you'll need to specify the additional parameter resolver in your server config. You can use your local name server if you have one, or use something external like Google public DNS (8.8.8.8) or DNS provided for you by your ISP. Anyway such configuration leads to additional DNS lookups, so if you can, specify your proxy destination with IP address.
Update
There is another way to do it with the valid_referers directive:
# needed if your proxy destination specified with domain name instead of IP address
resolver 8.8.8.8;
location /home/ {
proxy_set_header Host HOST1;
# setup other proxied headers if needed
valid_referers example.com/home;
if ($invalid_referer = "") {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_pass https://HOST1:8080; # this can be specified by IP address
}
}
Update # 2020.11.11
Besides this answer somehow achieved a score of 5, the given solution has an extremely bad design (it isn't a good approach to have different content handlers in the location and the nested if block; moreover, having an if block with any directive other than from the nginx rewrite module should be avoided if possible) and won't work at all on early nginx versions (I wanna cry when I look at some of my early answers). An original OP question was
The logic should be like below but has some syntax mistakes.
if ($http_origin ~ '^http?://(dev.xyz.com/home)') {
set $flag 'true';
}
if ($flag = 'true') {
location /home/ {
proxy_pass "https://HOST1:8080/HOME PAGE/";
}
}else{
Do Not proxy pass
}
It is unclear what do not proxy pass means. If it means returning some HTTP error (for example, HTTP 403 Forbidden), it can be done with the following configuration:
location /home/ {
if ($http_referer !~ ^https?://dev.xyz.com/home) {
return 403;
}
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_set_header Host HOST1;
# setup other proxied headers if needed
proxy_pass https://HOST1:8080; # this can be specified by IP address
}
If do not proxy pass means to serve the request locally, the solution is more complex:
map $http_referer $loc {
~^https?://dev.xyz.com/home loc_proxy;
default loc_local;
}
server {
...
location /home/ {
try_files /dev/null #$loc;
}
location #loc_proxy {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_set_header Host HOST1;
# setup other proxied headers if needed
proxy_pass https://HOST1:8080;
}
location #loc_local {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
root /path/to/required/page;
...
}
The try_files /dev/null #the_named_location; trick is taken from this excellent answer.
However now the edited OP's question states for a different requirements, which also could be achieved with the map directive help:
map $http_referer $environment {
~^https?://dev.xyz.com/home Environment1;
default Environment2;
}
server {
...
location /home/ {
rewrite ^/home(/.*)$ HOME_PAGE$1 break;
proxy_set_header Host $environment;
# setup other proxied headers if needed
proxy_pass https://$environment;
}
I need to get the parameter from an URL, for example, abc=MY_STRING:
https://my-address/test?abc=MY_STRING
And at the reverse proxy (my-address), is configured like this:
location /test?(.*) {
proxy_pass http://local-server:1234/test?$args
}
but it is not working.
I tried another configuration:
location /test?(.*) {
proxy_pass http://local-server:1234/test?$1
}
but not worked too.
You cannot match the query string part of the URI with a location or rewrite statement, as it is not part of the normalized URI.
But you don't need to. The URI (complete with query string) will be passed upstream
unless you redirect it using a rewrite or try_files statement.
For example:
location /test {
proxy_pass http://localhost:1234;
}
The URI /test?abc=MY_STRING will match the location and be passed to localhost:1234 exactly the same. See this document for more.
I have been struggling with setting up Nginx for our use case.
When I set up Nginx with the following config:
location /dep-core {
proxy_pass http://node-server:7070/;
}
and call the server with following endpoint:
<END-POINT>/dep-core/api/login
the call is redirected to
<ADDRESS-AFTER-RESOLUTION>//api/login
with two leading //s.
and when I remove the trailing / in proxy_pass after 7070:
location /dep-core {
proxy_pass http://node-server:7070;
}
the call is redirected to
<ADDRESS-AFTER-RESOLUTION>/dep-core/api/login
with leading /dep-core appended.
I want my call to redirect my call to:
<ADDRESS-AFTER-RESOLUTION>/api/login
What would be the standard way to achieve this??
For correct translation from /dep-core/foo to /foo, the location directive requires a trailing /.
For example:
location /dep-core/ {
proxy_pass http://node-server:7070/;
}
See this document for details.
To translate /dep-core to /, you can use a rewrite...break with a clever regular expression in the second block of your question. But a simple solution is to add an exact match location for that single edge case.
For example:
location = /dep-core {
rewrite ^ $uri/ last;
}
location /dep-core/ {
proxy_pass http://node-server:7070/;
}