Url rewriting and Proxying in Nginx - nginx

I'm using nginx to proxy a request to an URL contained in the query string.
Basically my idea is proxying this request:
/proxy?url=http://google.com
to
http://google.com
How can I accomplish this?
I tried with
location /proxy\?url=(.*)$ {
proxy_pass http://$1;
}
but it doees not work.
Suggestions?

The query string is not part of the normalized URI used by the location and rewrite directives. However, all of the arguments are available as $arg_ variables.
For example:
location /proxy {
proxy_pass http://$arg_url;
}

Related

How does nginx proxy pass works for nested paths?

I'm try to send the following over to a different node with the nested path
server_name http://cloudflare.myserver.com
location /api/client {
proxy_pass http://cloudflare.anotherserver.com
}
How can I forward the request
http://cloudflare.myserver.com/api/client/users/1
to
http://cloudflare.anotherserver.com/users/1
notice the users/1 needed to be forwarded also.
As per the docs:
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 your location block needs to look like this:
location /api/client/ {
proxy_pass http://cloudflare.anotherserver.com/;
}

Passing URI query param nginx reverse proxy

I have a post server listening on port 8081 and sample path.
I want to be able to redirect the entire URI query param the the node service.
How should i do it.
for example i want the following post request url http://exmaple.com/foo/bar?bla=1 to passed to http://example.com:8081/foo/bar?bla=1
It looks very simple and straight forward example but just can't get it working, any ide?
location ^~ /foo/bar {
rewrite_log on;
rewrite ^/foo/bar(.*) /$1 break;
proxy_pass http://example.com:8081/foo/bar;
}
By default proxy_pass will not change the request URI (including the query string). The example in your question illustrates two ways in which the URI can be changed prior to being sent upstream - by appending an optional URI to the proxy_pass statement (see this document) or with a rewrite...break statement (see this document).
If you remove both, the URI will be sent upstream unmolested and with the query string intact:
location ^~ /foo/bar {
proxy_pass http://example.com:8081;
}

How nginx rewrite and proxy? http://sa.com/rabbitmq/api/#/queues/%2F/somequeue

I try to use a single domain to proxy several programs like this:
http://sa.com/rabbitmq/ ---> http://localhost:15672/
http://sa.com/zabbix/ ---> http://localhost:10000/
and my conf is blow:
location /rabbitmq {
rewrite /rabbitmq(.*) $1 break;
proxy_pass http://localhost:15672;
It works well until I click a queue name to watch the detail,
which url is as the title said:
http://sa.com/rabbitmq/api/#/queues/%2F/somequeue
an 404 error occured, I saw an request in dev-tools of chrome:
http://rabbitmq.testing.gotokeep.com:15672/api/queues/%2F/dailyNewLike?lengths_age=60&lengths_incr=5&msg_rates_age=60&msg_rates_incr=5
this request returned 404.
I guess that when rewrite processed, the uri was decoded (.../%2F/... -> ...///...) and the extra slashes will be removed...
Is my guess right? Is there a solution?
Your guess is good, but no, the real problem is that nginx converts %2F into %252F (% -> %25).
%2F is vhost name (/). I don't found the real solution for this problem, and my workaround was to use other vhost name which do not contains / symbol (e.g. pool1).
You can use $request_uri to prevent nginx decode the uri.
use conf like below
location /rabbitmq {
if ($request_uri ~* "/rabbitmq/(.*)") {
proxy_pass http://localhost:15672/$1;
}
}

Avoid nginx decoding query parameters on proxy_pass (equivalent to AllowEncodedSlashes NoDecode)

I use nginx as a load balencer in front of several tomcats. In my incoming requests, I have encoded query parameters. But when the request arrives to tomcat, parameters are decoded :
incoming request to nginx:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http%3A%2F%2Fwww.google.com%2F"
incoming request to tomcat:
curl -i "http://server/1.1/json/T;cID=1234;pID=1200;rF=http:/www.google.com/"
I don't want my request parameters to be transformed, because in that case my tomcat throws a 405 error.
My nginx configuration is the following :
upstream tracking {
server front-01.server.com:8080;
server front-02.server.com:8080;
server front-03.server.com:8080;
server front-04.server.com:8080;
}
server {
listen 80;
server_name tracking.server.com;
access_log /var/log/nginx/tracking-access.log;
error_log /var/log/nginx/tracking-error.log;
location / {
proxy_pass http://tracking/webapp;
}
}
In my current apache load balancer configuration, I have the AllowEncodedSlashes directive that preserves my encoded parameters:
AllowEncodedSlashes NoDecode
I need to move from apache to nginx.
My question is quite the opposite from this question : Avoid nginx escaping query parameters on proxy_pass
I finally found the solution: I need to pass $request_uri parameter :
location / {
proxy_pass http://tracking/webapp$request_uri;
}
That way, characters that were encoded in the original request will not be decoded, i.e. will be passed as-is to the proxied server.
Jean's answer is good, but it does not work with sublocations. In that case, the more generic answer is:
location /path/ {
if ($request_uri ~* "/path/(.*)") {
proxy_pass http://tracking/webapp/$1;
}
}
Note that URL decoding, commonly known as $uri "normalisation" within the documentation of nginx, happens before the backend IFF:
either any URI is specified within proxy_pass itself, even if just the trailing slash all by itself,
or, URI is changed during the processing, e.g., through rewrite.
Both conditions are explicitly documented at http://nginx.org/r/proxy_pass (emphasis mine):
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
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
The solution depends on whether or not you need to change the URL between the front-end and the backend.
If no URI change is required:
# map `/foo` to `/foo`:
location /foo {
proxy_pass http://localhost:8080; # no URI -- not even just a slash
}
Otherwise, if you do need to swap or map /api of the front-end with /app on the backend, then you can get the original URI from the $request_uri variable, and the use the rewrite directives over the $uri variable similar to a DFA (BTW, if you want more rewrite DFA action, take a look at mdoc.su). Note that the return 400 part is needed in case someone tries to get around your second rewrite rule, as it wouldn't match something like //api/.
# map `/api` to `/app`:
location /foo {
rewrite ^ $request_uri; # get original URI
rewrite ^/api(/.*) /app$1 break; # drop /api, put /app
return 400; # if the second rewrite won't match
proxy_pass http://localhost:8080$uri;
}
If you simply want to add a prefix for the backend, then you can just use the $request_uri variable right away:
# add `/webapp` to the backend:
location / {
proxy_pass http://localhost:8080/webapp$request_uri;
}
You might also want to take a look at a related answer, which shows some test-runs of the code similar to the above.
There is one documented option for Nginx proxy_pass directive
If it is necessary to transmit URI in the unprocessed form then directive proxy_pass should be used without URI part:
location /some/path/ {
proxy_pass http://127.0.0.1;
}
so in your case it could be like this. Do not worry about request URI it will be passed over to upstream servers
location / {
proxy_pass http://tracking;
}
Hope it helps.
In some cases, the problem is not on the nginx side - you must set the uri encoding on Tomcat connector to UTF-8.

Correct proxy path in nginx.conf

we have two servers, A and B. Server A is accessed worldwide. He has nginx installed. That's what I have in conf:
location /test {
proxy_pass http://localserver.com;
}
What it should do, is translate the addreess http://globalserver.com/test (that is server A) to internal server address http://localserver.com. However, it does append the location path, that is, itries to look for http://localserver.com/test, which is not available at all. How can I make the proxy pass to the correct address, throwing out the last part in the location?
That should work. Nginx should strip the '/test' path on the upstream local server. So what I can say is that is not the cause. To make it a bit better, try this:
location /test/ {
proxy_pass http://localserver.com/;
}
The 2 slashes I added at the first 2 lines will avoid mistakenly match '/testABC' and send the wrong request to the upstream local server, for example.
Do you have a
proxy_redirect
line in the same location block? If your upstream local server has redirects, then a mistake on that line will cause an issue like you described.
[UPDATE] Found the root cause why the original config didn't work and mine works: nginx does NOT replace URI path part if the proxy_pass directive does not have a URI path itself. So my fix of adding a slash (slash is treated as a URI path) at the end triggers the URI path replacement.
Reference: http://wiki.nginx.org/HttpProxyModule#proxy_pass
If it is necessary to transmit URI in the unprocessed form then directive proxy_pass should be used without URI part
location /some/path/ {
proxy_pass http://127.0.0.1;
}
try to add as specified here http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass:
proxy_pass http://localserver.com/;
try rewrite
location /test {
rewrite ^ $scheme://$host/;
proxy_pass http://localserver.com;
}
some helpful links...
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
http://wiki.nginx.org/Pitfalls

Resources