nginx : rewrite rule to remove /index.html from the $request_uri - nginx

I've seen a few ways to rewrite the $request_uri and add the index.html to it when that particular file exists in the file system, like so:
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
but i was wondering if the opposite is achievable:
i.e. when somebody requests http://example.com/index.html, they're redirected to http://example.com
Because the nginx regexp is perl compatible, i tried something like this:
if ( $request_uri ~* "index\.html$" ) {
set $new_uri $request_uri ~* s/index\.html//
rewrite $1 permanent;
}
but it was mostly a guesswork, is there any good documentation describing the modrewrite for nginx ?

I use the following rewrite in the top level server clause:
rewrite ^(.*)/index\.html$ $1 permanent;
Using this alone works for most URLs, like http://example.com/bar/index.html, but it breaks http://example.com/index.html. To resolve this, I have the following additional rule:
location = /index.html {
rewrite ^ / permanent;
try_files /index.html =404;
}
The =404 part returns a 404 error when the file is not found.
I have no idea why the first rewrite alone isn't sufficient.

The following config allowed me to redirect /index.html to / and /subdir/index.html to /subdir/:
# Strip "index.html" (for canonicalization)
if ( $request_uri ~ "/index.html" ) {
rewrite ^(.*)/ $1/ permanent;
}

For some reason most of the solutions mentioned here did not work. The ones that worked gave me errors with missing / in the url. This solution works for me.
Paste in your location directive.
if ( $request_uri ~ "/index.html" ) {
rewrite ^/(.*)/ /$1 permanent;
}

This one works:
# redirect dumb search engines
location /index.html {
if ($request_uri = /index.html) {
rewrite ^ $scheme://$host? permanent;
}
}

For the root /index.html, the answer from Nicolas resulted in a redirect loop, so I had to search for other answers.
This question was asked on the nginx forums and the answer there worked better.
http://forum.nginx.org/read.php?2,217899,217915
Use either
location = / {
try_files /index.html =404;
}
location = /index.html {
internal;
error_page 404 =301 $scheme://domain.com/;
}
or
location = / {
index index.html;
}
location = /index.html {
internal;
error_page 404 =301 $scheme://domain.com/;
}

This is working for me:
rewrite ^(|/(.*))/index\.html$ /$2 permanent;
It covers both the root instance /index.html and lower instances /bar/index.html
The first part of the regex basically translates as: [nothing] or /[something] - in the first case $2 is an empty string so you redirect to just /, in the second case $2 is [something] so you redirect to /[something]
I actually went a bit fancier to cover index.html, index.htm, and index.php
rewrite ^(|/(.*))/index\.(html?|php)$ /$2 permanent;

The solutions quoting $scheme://domain.com/ assume that the domain is hard-coded. It was not in my case and so I used:
location / {
...
rewrite index.html $scheme://$http_host/ redirect;
... }

Related

Nginx rewrite - not working

I have simple nginx rewrite I can't get to work.
I have this url:
https://example.com/accessories/3427-tote-bag-grey-212345050033.html
I want to redirect to:
https://example.com/dk/accessories/3427-tote-bag-grey-212345050033.html
My nginx config:
location / {
index /index.php;
rewrite ^/dk/$1/$2.html /$1/$2.html last;
}
any idea want is wrong here?
$1 and $2 are used for captures. You have to use pattern to with groups to create captures
Try below
location / {
index /index.php;
rewrite ^/([^/]+)/([^/]+).html$ /dk/$1/$2.html last;
}
Or you can do something like below
location / {
index /index.php;
location /accessories/ {
alias <yourroot>/dk/accessories/;
}
}

How to use my index.htm in this location script?

I need URL http://myexample.org (root) redirecting to my local index.htm, not rewriting it to Github... How to do it?
I was testing many variations of location = / { try_files ...} but no one works. Using a UBUNTU 16 LTS server.
/etc/nginx/sites-available/myexample.org
server {
server_name myexample.org;
root /var/www/myexample.org;
index index.html index.htm;
# ?? location =/ {...} is not working!
location / {
# also not work a root rewrite
# rewrite ^/?$ index.htm break;
rewrite ^/?git$
http://github.com/myexample-org/test
break;
rewrite ^/?tickets$
http://github.com/myexample-org/test/issues
break;
rewrite ^/?(.+)$
http://github.com/myexample-org/test/$1
break;
}
}
Change your last rewrite directive to match ^/(.+)$
location = / will not work for an index, as the rewritten URI will match location / which will then hit your final rewrite statement.
Your original solution (a few questions ago) with the named location, should work fine:
root /path/to/file;
index index.htm;
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^/... http://example.com/...;
rewrite ^/... http://example.com/...;
rewrite ^/... http://example.com/...;
}
Assuming that a file called /path/to/file/index.htm exists on this server. The break flag is unnecessary as the destination URL begins with http://. If you want to add a flag, the redirect or permanent flag would be pertinent. See this document for details.

Nginx - if pattern 404 - go to

I have list of urls like:
domain.com/some-url-key-with-possible-id-after-it-99999.html
I need to try that URL, and IF it returns 404, redirect to:
domain.com/some-url-key-with-possible-id-after-it.html
Is that possible?
location ~ /([a-zA-Z0-9\-]+)-([0-9]+).html$ {
## IF ABOVE IS 404
return 301 http://domain.com/$1.html;
## ENDIF
}
I found something like this:
server {
listen 12440;
root /some/path/here/nginx/html/noahc/;
server_name www.domain.net, domain.net;
port_in_redirect off;
location /{
error_page 404 = #foobar;
}
location #foobar {
rewrite .* / permanent;
}
}
But it doesn't satisfy me, because I need to redirect to url with variable from request pattern. It could be ok, if I'll be able to pass ([a-zA-Z0-9-]+)-([0-9]+) to it as an argument.
So you have a URI and you would like to rewrite it if the static file does not exist. Use try_files to test for file existence.
root /path/to/docroot;
location ~ ^(/[a-zA-Z0-9-]+)-[0-9]+\.html$ {
try_files $uri #rewrite;
}
location #rewrite {
return 301 $1.html;
}
You can use return 301 or rewrite ... last in the named location, depending on how visible you want the rewrite to be.
See this document for help with nginx directives.

nginx rewrite URL only if the original one gives 404 error

I've this rewrite rule:
rewrite ^/components/com_jshopping/files/img_products/full_(.*)$ http://www.domain.tdl/components/com_jshopping/files/img_products/$1 permanent;
It redirects every request of images which starts with full_ to the same image without the prefix.
Now I'd like to apply this rule only if the requested image does not exists (404 error).
How can I do?
You could use try_files with named location that will do redirect:
location /components/com_jshopping/files/img_products/full_ {
try_files $uri #redirect;
}
location #redirect {
rewrite ^(/components/com_jshopping/files/img_products/)full_(.*)$ http://www.domain.tdl$1$2 permanent;
}

Nginx rewrite a folder with exclude

i am working on nginx webserver.
I want to redirect all urls inside folder1 www.site.com/folder1/ but not the subfolder1 www.site.com/folder1/subfolder1
I created these rules to nginx configuration but no luck.
location = /folder/subfolder {
}
location /folder {
rewrite ^/folder(.*) www.redirect.com permanent;
}
Am i missing something?
Ok so here's a refined answer including some of the comments I've read plus one of mine, to be able to access the assets inside the subfolder I added the try_files, and the 301 redirect in all other urls was added for the redirection.
location /folder/subfolder {
try_files $uri $uri/ =404;
}
location /folder {
return 301 $scheme://example.com;
}
Your new set of rules should be as follows. I am assuming that valid file hits are okay (i.e. the user knew the file). If you do not want this behaviour, replace try_files with the content of the #rw block:
location /folder {
try_files $uri $uri/ #rw;
}
location #rw {
rewrite ^/folder/([^\/]*) http://www.redirect.com/ permanent;
}
These should work.
Remove the "=" because that's for "exact" match. So it only matches the folder itself, and a request for "/folder/subfolder/a_file.html" won't match that block. Also you need to add $scheme in your rewrite rule. And if you just want to redirect to the home page (http://www.redirect.com), you can remove the "$1" part.
location /folder/subfolder {
}
location /folder {
rewrite ^/folder(.*)$ $scheme://www.redirect.com$1 permanent;
}

Resources