Nginx rewrite unencodes url - nginx

It seems Nginx it always un-encodes urls when used with a regular expression. I have a rewrite rule:
location /api/ {
rewrite /api/(.*)$ $1 break;
proxy_pass http://127.0.0.1:8000/$1;
}
I would like to remove the api from the usl but keep the rest of the path. Part of the path is an email address someone#somewhere.com. I am passing someone%40somewhere.com but Nginx is turning it back with the # sign.

The correct answer seem to be
location /api/ {
rewrite ^ $request_uri;
rewrite ^/api/(.*) $1 break;
return 400;
proxy_pass http://127.0.0.1:8000/$uri;
}
See Nginx pass_proxy subdirectory without url decoding for full answer and original author.
(I realize this question is older than the one I referenced but I found this in google search and may not be the last one, so ...)

That is how Nginx handles urls. You can bypass it by changing your web application to escape the "%" character as "%25" and pass someone%2540somewhere.com.
This will be unescaped as someone%40somewhere.com.

Related

Form url for existing Nginx rewrite rule

i have question to Nginx specialist. There are such rules on Nginx.
If i request with header 'main', it adds /ismain to url:
if ($http_main) {
rewrite ^(.*)$ /ismain/$1;
}
Next it cut /ismain/ from url and goes to Host
location /ismain/ {
rewrite ^/ismain/(.*)$ $1 break;
proxy_pass http://Host:9999;
}
It works good and i can't change it because of company sequrity policy.
But now i need to do callback and headers are not allowed.
So i request in such a way(without header):
http://11.11.117.111:8077/ismain/someaddress
But Nginx cut off all slashes after port... and responses 400 Bad URI.
In logs i can see such url after cut:
http://11.11.117.111:8077someaddress
I tried request with double slashes:
http://11.11.117.111:8077//ismain/someaddress
http://11.11.117.111:8077/ismain//someaddress
But it's not work. I have the same response. I'm in frustration why i works with header, but doesn't want with my formed path. I suppose it's the same.
Maybe i need to screen slash with some symbol ? Can you advice me ?
All Nginx URIs contain a leading /.
Your first rewrite statement is adding a double //. You should use:
rewrite ^(.*)$ /ismain$1;
or:
rewrite ^/(.*)$ /ismain/$1;
Your second rewrite statement relies on the first bug. You should use:
rewrite ^/ismain(/.*)$ $1 break;
or:
rewrite ^/ismain/(.*)$ /$1 break;

What's the rewrite syntax for an NGINX regex location?

Using NGINX as a load balancer running on 10.1.2.15:9002, I have a need to rewrite http://10.1.2.15:9002/proxy.stream?opt=1 to http://10.1.2.15:9002/app/proxy.stream?opt=1.
Following are bits from my nginx.conf file:
http {
upstream app_cluster {
server 10.1.2.23:8080;
server 10.1.2.25:8080;
}
server {
listen 9002 default_server;
location /app/ {
proxy_pass http://app_cluster/;
}
location ~ ^/proxy.stream(.*)$ {
rewrite ^(.*)$ /app/$request_uri last;
}
}
}
By the way, I can replace the rewrite line with return 401 (for example), and I can see the 401 HTTP status returned using Chrome Developer Tools, so I know the regex is matching. I just can't get the URI rewritten properly. In fact, I only see the original request with a 406 status in Developer Tools, so I suspect something is wrong with my rewrite syntax.
Does anyone see what is wrong with this configuration?
Using $request_uri in the replacement string of a rewrite statement is problematic, as it has not been normalised and also contains the query string, which by default, rewrite will append again.
Also, your replacement string contains //, as you are appending a URI which already has a leading /.
The regular expression location is not necessary, as a prefix or exact match location will suffice and is more efficient for nginx to process. See this document for more.
For example:
location /proxy.stream {
rewrite ^ /app$uri last;
}
Make use of the matching part from the regex instead of $request_uri
rewrite ^(.*)$ /app/$1 last;

proxy_pass in nginx to publish webapp under a different directory

I have this location element:
location ~* ^/publicapp {
proxy_pass https://myserver.domain.local;
}
The server myserver.domain.local hosts a web application located under /myapp.
I want to make it publicly available via https://www.mywebsite.com/publicapp. How do I tell nginx to translate /myapp to /publicapp?
Please keep in mind that I use ~* to allow case-insensitivity. Thus, I cannot use a URI with proxy_pass.
Kind regards,
Kevin
Try this:
location ~* /publicapp/ {
rewrite ^/publicapp/(.*)$ /myapp/$1 break;
proxy_pass https://myserver.domain.local;
}
This will rewrite your path and use new one at the .local server.
It works using
rewrite ^/publicapp/(.*) /myapp/$1 break;
At least it does with my very simple application.
Now I have to figure out how to do proper link translation (sorry for using ISA Server/TMG terms, don't know if it's the same in nginx).
Thanks to pythagor :-)
edit:
Works only if I keep a trailing slash after the url in the browser (https://www.mywebsite.com/publicapp/).
another edit:
To make sure URLs end with a slash:
rewrite ^([^.]*[^/])$ $1/ permanent;
Taken from: here (first answer)

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;
}
}

nginx 'proxy_pass' cannot have URI part in location?

I have a location block as
location #test{
proxy_pass http://localhost:5000/1;
}
but nginx complains that "proxy_pass cannot have URI part in location given by regular expression..." Does anyone know what might be wrong?
I'm trying to query localhost:5000/1 when an upload is complete:
location /upload_attachment {
upload_pass #test;
upload_store /tmp;
...
}
Technically just adding the URI should work, because it's documented here and it says that it should work, so
location #test{
proxy_pass http://localhost:5000/1/; # with a trailing slash
}
Should have worked fine, but since you said it didn't I suggested the other way around, the trick is that instead of passing /my/uri to localhost:5000/1, we pass /1/my/uri to localhost:5000,
That's what my rewrite did
rewrite ^ /1$1
Meaning rewrite the whole URL, prepend it with /1 then add the remaining, the whole block becomes
location #test{
rewrite ^ /1$1;
proxy_pass http://localhost:5000;
}
Note: #Fleshgrinder provided an answer explaining why the first method didn't work.
What's actually happening here?
nginx cannot process your desired URI part in the proxy_pass directive because you're within a named location (hence the error message). This is because nginx is built in a modular fashion and each configuration block is read in various stages by the various modules. So just remember that you cannot have a URI within your proxy_pass directive in the following cases:
Regular Expression Locations
Named Locations
if Blocks
How could we solve this problem?
Mohammad AbuShady explained how to do a rewrite and pass the requested URI to the proxy server. I just wanted to clarify the reason.
Try omitting the "/" (URI part) and check.
location #test{
proxy_pass http://localhost:5000;
}

Resources