How to add url prefix after host in nginx? - nginx

I have this location:
location /foo {
proxy_pass http://backend/;
proxy_set_header Host $host;
}
When I get static from http://frontserver/foo, my requests of backed url prefix: http://frontserver/..., but I'd like to see http://frontserver/foo/....
If I make something like proxy_set_header Host $host/foo; I get 400 error.
How can I make it correctly?

You should not add the URI in the proxy_set_header but in your proxy_pass directive instead. It accepts a full URI
location /foo {
proxy_pass http://backend/foo; # will work
proxy_set_header Host $host;
}
proxy_pass nginx docs
Sets the protocol and address of a proxied server and an optional URI to which a location should be mapped. As a protocol, “http” or “https” can be specified. The address can be specified as a domain name or IP address, and an optional port:
Adding it to proxy_set_header would ultimately make your reverse proxy send a hostname that includes a uri, which isn't a valid hostname.

Related

Nginx redirect subfolder to another port showing original port

How to enable Nginx redirect subfoler to another port using original port? e.g.,
Service1: http://127.0.0.1:5000
Service2: http://127.0.0.1:8080
Exposed IP port via Nginx is 127.0.0.1:6060
The goal is when accessing http://127.0.0.1:6060/sub, it will access http://127.0.0.1:8080, but the URL user see is still http://127.0.0.1:6060/sub.
I tried two configurations, but they didn't work.
server {
listen 6060;
server_name 127.0.0.1;
location /sub/ {
# method 1: use proxy pass, browser says "static resources not found"
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host:6060;
proxy_pass http://127.0.0.1:8080;
# method 2: use rewrite, the URL will be http://127.0.0.1:8080
rewrite ^/pct/(.*)$ http://127.0.0.1:8080 redirect;
}
location / {
proxy_pass http://127.0.0.1:5000;
}
Thanks.

Ngnix proxy_pass dosen't work when url contains path

im trying to mock sites from my own FS. i want to intercept any http request and redirect it to my server that will return the needed file.
i have wrote a simple default sever:
server {
listen <<SERVICE_PORT>> default_server;
server_name _;
location / {
proxy_set_header X-ORIGINAL-URI $request_uri;
proxy_set_header X-ORIGINAL-REFERRER $http_referer;
proxy_set_header X-ORIGINAL-HOST $http_host;
proxy_pass <<BROWSE_RESOURCE_URL>>/browsing/resource/;
proxy_redirect off;
}
}
when a url as "http://exapmle.com" enters it works fine. but when any path is added as "http://exapmle.com/bar" it dose not pass the to <<BROWSE_RESOURCE_URL>>/browsing/resource/. currently i recive 404 but not from my server.
offcurce i dont need the orignal uri to be concated to my proxy_pass at all.
why dosent it work for me?
From Nginx's documentation:
A request URI is passed to the server as follows:
If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive
So, for your given configuration, when you request http://example.com/bar:
The normalized request URI will be /bar
The URI specified in the proxy_pass directive will be /browsing/resource/
The final URI that will be passed to the backend server is /browsing/resource/bar.
You have not configured the backend server to understand /browsing/resource/bar. So it only understands /browsing/resource/. That's why your backend server returned a 404 not found.
Because you don't want Nginx to combine the request URI with the URI specified in the proxy_pass directive, you can use another feature of the proxy_pass directive as mentioned in the Nginx's documentation:
When the URI is changed inside a proxied location using the rewrite directive, and this same configuration will be used to process a request (break):
...
In this case, the URI specified in the directive is ignored and the full changed request URI is passed to the server.
So you will instruct Nginx to rewrite all request URIs to the same URI /browsing/resource/ as follows:
location / {
proxy_set_header X-ORIGINAL-URI $request_uri;
proxy_set_header X-ORIGINAL-REFERRER $http_referer;
proxy_set_header X-ORIGINAL-HOST $http_host;
rewrite ^ /browsing/resource/ break;
proxy_pass <<BROWSE_RESOURCE_URL>>;
proxy_redirect off;
}

Nginx redirects instead of doing reverse proxy with proxy_pass

I have an nginx running on a docker container, which serves a web client.
I want to proxy requests from the client, so that the nginx will pass the POST requests to the server, since the actual destination endpoint is not accessible to the client.
This is the location directive:
location /zipkin {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header Host $host;
proxy_pass http://my-ip:9411/;
}
The client makes requests to http://localhost:8080/zipkin/api/v2/span, which I want the nginx to pass (without redirection) to http://my-ip:9411/api/v2/span.
What happens in practice is that I get a 301 response (to http://localhost:8080/api/v2/span), and the POST is never sent to the destination.
Edit: another try that returns 404 -
location /zipkin/ {
rewrite ^/zipkin/(.*) /$1 break;
proxy_pass http://my-ip:9411$uri; # tried 9411;, 9411/, 9411$uri, 9411$uri/
}
Here $uri is /api/v2/span.
The solution in the end was:
location ~ ^/zipkin(/?)(.*) {
proxy_pass http://my-ip:9411/$2;
}
One of my tries was ^/zipkin(.*) but it evidently didn't work.
Probably the / after the /zipkin is problematic, so (/?) removes it,
And that leaves the (.*) the clean part of the url which needs to be attached to the proxy_passed url.

Nginx domain resolving issue

I had a proxy server which redirects communications to some api on customer side via https. When I use configuration with set upstream variable (proxy_pass $upstream_endpoint$request_uri;), the DNS resolving for this domain (dynamic changing IP adress) is working well but I get response 403 unauthorized.
When I use configuration without upstream (proxy_pass https://api-test.example.com/api/), point directly to customer domain it works well, I am getting response 200 but DNS resolver is not working anymore..
Nginx config:
location /api-test.example.com/api/ {
resolver 10.100.10.1 valid=5s;
set $upstream_endpoint https://api-test.example.com;
proxy_pass $upstream_endpoint$request_uri;
#proxy_pass https://api-test.example.com/api/;
proxy_ssl_name api-test.example.com;
proxy_ssl_server_name on;
proxy_set_header Host api-test.example.com;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
By adding a URI to the proxy_pass statement, the requested URI is rewritten before passing it upstream. See this docuement for details.
So the URI /api-test.example.com/api/foo is rewritten to /api/foo.
You can achieve the same behaviour with a rewrite...break statement. See this document for details.
location /api-test.example.com/api/ {
rewrite ^/api-test.example.com(.*)$ $1 break;
set $upstream_endpoint https://api-test.example.com;
proxy_pass $upstream_endpoint;
...
}

Nginx proxy with Docker containers

This is my docker infra.
nginx webserver serving on port 80 (exposed to host)
media and blog serving on port 80 (not exposed to host) running under individual container
All running on the same VM.
Name Command State Ports
----------------------------------------------------------------------------------
media docker-php-entrypoint apac ... Up 80/tcp
mysql_db_blog docker-entrypoint.sh mysqld Up 3306/tcp
mysql_db_media docker-entrypoint.sh mysqld Up 3306/tcp
webserver nginx -g daemon off; Up 0.0.0.0:80->80/tcp
blog docker-entrypoint.sh apach ... Up 80/tcp
My nginx config:
server {
listen 80 default_server;
server_name 192.168.0.7;
server_tokens off;
location /story/ {
proxy_pass http://blog/;
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_set_header X-Forwarded-Host $server_name;
}
location /videos/ {
proxy_pass http://media/;
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_set_header X-Forwarded-Host $server_name;
}
}
My issue:
When I try to access any of the below URLs
1) http://webserver/story
2) http://webserver/videos
after the first request, the last part 'story' or 'videos' gets deleted form the url.
What am I missing from nginx conf to make sure 'story' or 'videos' doesn't gets removed from the url?
It's to do with how proxy_pass is written in your stanza.
From proxy_pass:
A request URI is passed to the server as follows:
If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:
location /name/ {
proxy_pass http://127.0.0.1/remote/;
}
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 change your proxy_pass:
location /videos/ {
proxy_pass http://media;
Note - lack of trailing slash, means it preserves the original URI.
You might also want to look at rewrite as that does something related.

Resources