NginX: rewrite backslashes to Forward-slashes - nginx

I want to write NginX rewrite rule to convert all Backslashes to forward-slashes.
Something exactly like: Using .htaccess to replace backslash in URL with forward-slash
however, I am working in NginX while above link refers to Apache.
I migrated my application from Windows IIS to Linux Tomcat and hence I need to get this done.
My URL has multiple Backslashes which gets resolved fine in IE and Chrome but Firefox is resolving them to its Unicode %5C and hence I need to rewrite.
My sample URL in WIndows/IIS: https://doman.com/company/.\images\company\companylogo.png
When I moved stuff to Linux/Tomcat, above URL works in Chrome and IE, but Firefox is converting above backslashes to %5C. So Firefox is trying to resolve: https://doman.com/company/.%5Cimages%5Ccompany%5Ccompanylogo.png
And needless to say, Firefox fails to load the image.
Here is what I tried so far in my nginX configuration (Once statement at a time)):
rewrite \ / permanent;
rewrite \\ \/ permanent; # with escaping thinking it might help
rewrite (.*)\(.*)\(.*)\(.*) $1/$2/$3/$4 permanent;
rewrite (.*)\(.*)\(.*)\(.*) $1\/$2\/$3\/$4 permanent;
Howcer , none seem to work and last 2 statements are throwing NginX configuration Error.
Any pointers would be of great help. There are thousands such URLs and I cannot imagine of converting all of them into Forward-Slash'd style.

Finally, I figured it out myself.
First off, in NginX, a backslash needs to be escaped twice. Nginx Uses Lua launguage module extensively for parsing request. So, NginX config parser as well as Lua module will strip off the escaping backslashes. Hence need to escape it twice.
This is wrong: \\
This is Correct: \\\
This part bugged me for 2 days as I was following typical PCRE standards for escaping characters and NginX would throw regex error at me.
More about this behaviour is explained here: http://wiki.nginx.org/HttpLuaModule#Special_PCRE_Sequences
Now, over to my question:
Source URL: https://domain.com/company/.\images\company\companylogo.png
Redirected URL: https://domain.com/company/./images/company/companylogo.png
I wanted to convert all \ to / in above URL. So, for this purpose, below rewrite rule is needed:
rewrite ^/(.+)\\\(.+)\\\(.+)\\\(.+)$ /$1/$2/$3/$4 redirect;
Above rule will do a single redirect (HTTP Code 302) and will get all the three \ converted to /.
However, If you have varying number of \ in the URL, then above rule may(not) work. Hence in that case, use below rule to convert ALL \ to /
rewrite ^/(.+)\\\(.+)$ /$1/$2 redirect;
Please note that, with above rule in place multiple redirects (HTTP Code 302) will happen causing some latency. The number of redirects will be equal to number of \ in the source URL. This would work on my URL too. But then it would have done the redirect for 3 times (as I have 3 backslashes in my URL). So, I am good with the 1st rule I mentioned above.
Nonetheless, I had a great learning all along and I understand NginX better now.
Here are few (out of hundreds of) links which helped solving this issue:
http://wiki.nginx.org/HttpLuaModule
https://blog.engineyard.com/2011/useful-rewrites-for-nginx
http://nginx.org/en/docs/http/ngx_http_core_module.html#location
http://blog.rackcorp.com/2010/05/nginx-location-and-rewrite-configuration-made-easy/
http://www.cyberciti.biz/faq/unix-linux-bsd-nginx-redirect-url-http-301-status-code/

Related

Nginx reverse proxy to CDN with automatically finds the right image size by configured array

I have the following URL's on a CDN
https://storage.googleapis.com/my-bucket/1.png
https://storage.googleapis.com/my-bucket/1_50x50.png
https://storage.googleapis.com/my-bucket/1_150x150.png
https://storage.googleapis.com/my-bucket/1_300x300.png
https://storage.googleapis.com/my-bucket/1_500x500.png
https://storage.googleapis.com/my-bucket/1_1000x1000.png
https://storage.googleapis.com/my-bucket/1_3000x3000.png
I want Nginx to forward the following url, (because I have an external service which I can't edit that does these requests)
https://my-reverse-proxy.domain.com/my-bucket/1.png?width=350&height=350
to
https://storage.googleapis.com/my-bucket/1_500x500.png
So it should find to nearest number (higher or equal) in the CDN but if it is higher than 3000 it should return the original image.
Unfortunately we are not sure if the external services uses the exact same numbers as we have available, so the external service could send width=350 while we only have 300 or 500 images available.
I have no idea if this can be done in the Nginx config. Is this possible and how should it be done? I'm open to alternative solutions!
The width and height in the CDN are always the same, so looking at the width only would be fine!
The best option here would be to create rewrite rules in Nginx, and match your desired paths with regular expressions. Here, you can find a document describing the creation and usage of rewrite rules [1].
Here’s a sample NGINX rewrite rule that uses the rewrite directive. It matches URLs that begin with the string /download and then include the /media/ or /audio/ directory somewhere later in the path. It replaces those elements with /mp3/, and adds the appropriate file extension, .mp3 or .ra. The $1 and $2 variables capture the path elements that aren't changing. As an example, /download/cdn-west/media/file1 becomes /download/cdn-west/mp3/file1.mp3. If there is an extension on the filename (such as .flv), the expression strips it off and replaces it with .mp3:
server {
# ...
rewrite ^(/download/.*)/media/(\w+)\.?.*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(\w+)\.?.*$ $1/mp3/$2.ra last;
return 403;
# ...
}
[1] https://www.nginx.com/blog/creating-nginx-rewrite-rules/

How to use multiple nginx rewrite flags

I have a config like this in my nginx site configuration that is throwing a syntax error:
rewrite ^/favicon\.ico$ /static/ico/favicon.ico last permanent;
The idea was to make this the last rewrite rule that's processed, and to also configure it to return a permanent redirect.
Is there a trick for this?
(Answering my own question...)
Looking at the docs, it appears the syntax takes the following form:
rewrite regex replacement [flag];
Alas, just one flag is allowed at a time. I've done some minor testing though, and it seems that when you use the permanent flag, you don't have to use the last flag.
So the result becomes:
rewrite ^/favicon\.ico$ /static/ico/favicon.ico permanent;

Rewrite URL /blog/content/images/**/* to /content/images/**/*

My front-end is hitting /blog/content/foo/bar.jpg when looking for static assets.How can I make NGINX redirect those requests to /content/foo/bar.jpg instead?
At first I tried this:
location ~ ^/blog/content/ {
root /var/www/ghost/content/;
}
Apparently it didn't work – (btw, I'm testing each change in the .conf file with a sudo nginx -s reload + F5 in the browser.. is there a better way to test/debug NGINX behavior (and actually understand what's going on instead of this "worked / didn't work" feedback I get with each F5?)
Then, I tried this one I found in a cheatsheet – at the server level:
rewrite ^/blog/content/(.*)$ /$1 last;
Again, without luck. What bothers me is that I can't even see what the line above is doing and why it isn't working.
Someone, please, get me out of this "google for a solution -> try something that looks promising --> hit F5 hoping it works (it doesn't) -> google for a solution" loop.
The solution I found was to rewrite with:
rewrite ^/blog/(.*)$ /$1 last;
But it isn't ideal. I'd prefer to rewrite only when the URI contains "/blog/content/"..

Rewrite rule to add characters to beginning of urls in nginx where they are missing

I'm working on a legacy site where all urls must begin with the single available language code '/en'.
Is it possible with nginx to rewrite urls that do not begin with '/en' so that it is added (the legacy application will then be able to find the content and serve it)?
E.g.
http://www.example.com/ -> http://www.example.com/en/
http://www.example.com/page1 -> http://www.example.com/en/page1
http://www.example.com/en/page1 -> http://www.example.com/en/page1
Yes, this is possible. It's a bit difficult to give you a full solution since you haven't provided the config file, but I'll give it a shot.
You're looking for something along the lines of:
if ($request_uri !~ "^/en.*"){
return 301 $scheme://www.example.com/en$uri;
}
Note: This should appear immediately after your server_name and listen directives and not in a location block (see here).
I hope this helps.

nginx rewrite rule missing slash

I have a thumbnail class and it accepts external hosts too. It works like this right now :
http://mysite.com/resize/src=http://google.com/logo.png&w=50&h=50
I want to make it clean url with my "resize.mysite.com" subdomain like this :
http://resize.mysite.com/400x200/http://google.com/logo.png
I almost done it with this rewrite rule :
rewrite ^/([^x]*)x([^/]*)/(.*)$ /resize.php?w=$1&h=$2&src=$3 last;
But it's sending "src" without second slash after "http:" and it causes to resize class error, like this :
http:/google.com/logo.png
http://google.com/logo.png (what I expect)
How this can be fixed?
The first thing comes in mind is that your are using somewhere in your nginx configuration file special directive merge_slashes, is it true? If yes and your are using merge_slashes on then all your requests with double or triple and so on slashes will comes as one slash.
Can it be a solution to your problem to set directive merge_slashes off ?

Resources