NGINX conditional Rewrite extensionless URLS - nginx

I am trying to provide extensionless URLs for a client. The systems URLs will be generated without the extension in the navigation elements and links so I will have links that look like.
www.somesite.com
www.somesite.com/foo
www.somesite.com/foo/bar
www.somesite.com/bar/foo/barfoo
lets pretend for a moment that the calls will be either routed to a proxy that can handle a defined file extension or simply serve the html page if it exists. If the url is correctly rewritten then I would think a location command with a matching regex for the extension should work.
so behind the scenes we have.
www.somesite.com/index.abc
www.somesite.com/foo.def
www.somesite.com/foo/bar.abc
www.somesite.com/bar/foo/barfoo.def
...
with Apache .htaccess I can solve this problem by first testing for the existence of the page with a desired filetype.
RewriteCond %{REQUEST_FILENAME}.abc -f
RewriteRule ^(.*)$ $1.abc [L]
I would also make sure that directory browsing is off and that trailing slashes would be removed
#ensure trailing slash is removed
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)(?:/)$ $1 [R=301,L]
all well and good for Apache, and for me relatively intuitive, but this is NGINX and quite frankly I have no idea how to solve this use-case.
All the similar use cases I have found deal with html & php (How to remove both .php and .html extensions from url using NGINX?) and simply use try_files until they fall-through to a named location that rewrites the uri with .php extension. This would work if one is only dealing with a single dynamic language and fails miserably if we have two dynamic languages.
So the question is how do I do something similar in NGINX like can be done with the .htaccess condition/rewrite above
any help would be appreciated!
Cheers
Gary
UPDATE:
I have been able to get it "mostly" working by using the standard php approach. The issue is www.somesite.com is being directed to www.somesite.com/.php instead of serving the default document. Trailing slashes are also being removed correctly.
so to recap:
www.somesite.com - not working - www.somesite.com/.php
www.somesite.com/foo - working
www.somesite.com/foo/bar - working
www.somesite.com/bar/foo/barfoo - working
here my config:
location / {
index index.php index.html
autoindex off;
#remove trailing slash
rewrite ^/(.*)(?:/)$ /$1 permanent;
#try html files or route to named location
try_files $uri $uri.html #php;
}
location ~ \.php$ {
...
}
location #php {
rewrite ^(.*)$ $1.php last;
}
in other posts the try_files block looks like this: try_files $uri $uri.html $uri/ #php; the problem is if I add $uri/ it will work for the default document e.g. serve www.somesite.com but all other urls like www.somesite.com/foo/ or www.somesite.com/foo/bar/ , which are also directories and have files of the same name, will be redirected to infinity instead of their respective pages.

Assuming that you have three ways to process an extensionless URI, you would need three location blocks. You can use try_files to test for the existence of a file by type, and cascade to the next location block in the chain, if the file is not found. See this document for details.
For example:
root /path/to/document/root;
location / {
try_files $uri $uri.html $uri/ #php;
}
location #php {
try_files $uri.php #proxy;
fastcgi_pass ...;
...
}
location #proxy {
proxy_pass ...;
}
The first block processes normal files within the document root. You probably have a location ~ \.php$ block to process PHP files, and the second block is essentially a replica. The third block sends everything else upstream.

Related

How do I properly add try_url or rewrite for a .html add?

So, coming from the Apache world I am new to configuring NGNIX more than just the root site. I have tried to use an Apache to NGNIX rewrite, but the output doesn't seem to render the pages correctly.
Original .htaccess code:
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
RewriteRule ^([^\.]+)$ $1.html [NC,L]
The output doesn't seem to work after reloading the new configuration.
I have been trying different configurations under my location block trying to just add .html and end of the URI/URL. This is for a sub-directory called "wiki" just serving static HTML files.
Here's my current configuration under HTTPS:
root /var/www/html/;
index index.php index.html;
...
location ^~ /wiki/ {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^(.+)/$ $1.html permanent;
}
The alias or path is /var/www/html/wiki
Please advise. I was able to get /wiki/index.html to render, but any other HTML files do not rewrite from wiki/product to product/product.html. I keep getting 404 errors.

Nginx remove leading slash and trailing file type suffix and pass to php

I have received to migrate an existing website written in old php hosted on Apache, and I will deploy to an Nginx.
I wish to have URL like this: http://example.com/about.html
To be executed like this http://example.com/content.php?page=about
So I need to remove leading slash and remove html. The config below works if I hardcode a specific page:
location / {
try_files $uri $uri/ /content.php?page=about;
}
But of course it always serve about regardless if I access our-company.html, or our-services.html. I am not sure what I need to replace the "about" string in the config.
You should use a rewrite directive to perform the actual translation. You can invoke it from a named location specified as the last parameter on the try_files statement.
For example:
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^/(.*)\.html$ /content.php?page=$1 last;
}
See this document for more.

nginx rewrite with try_files 403

I have a webserver with /usercp/ and usercp.php. I'm using tryfiles and re-write to see if file.php exists do file, otherwise goto /file/ (in my case file = usercp)
Here is my nginx conf.
location / {
try_files $uri $uri/ #extension-php;
}
location #extension-php {
rewrite ^(.*)$ $1.php last;
}
This also makes site.com/usercp/ give a 403 error. Any ideas?
The problem is that you are prioritizing the folder indexing over the php file if you want the opposite I recommend not to use the autoindex on because it exposes the contents of your folder and swap the last 2 items in the try_files, try this
location / {
try_files $uri $uri.php $uri/;
}
PS: $uri/ will always return 403 if it doesn't contain the index file specified in index because by default it forbids folder listing, you should either put the index file if that's what you intend to do, or just remove the whole $uri/ from the try_files so that it would return 404 instead of 403
http://nginx.org/r/try_files
What it does is simply checks the existence of files, and then serves the file that exists.
You claim /usercp/ exists. As such, that's what it'll try to serve. But you probably don't have autoindex on, hence, directory listing is disallowed — 403 Forbidden.

nginx rewrite nice urls with homemade CMS

I have a home-made CMS, serving a site which I inherited. I'm not really familiar with nginx rewrite rules, although I could set up tiny URLs. Here is my relevant part of the configuration:
*location / {
index index.php index.html;
root /var/www/www.valami.hu;
try_files $uri $uri/ #seo;
}
location #seo {
rewrite ^/([a-z]+)$ /index.php?oldal=$1 last;
break;
}*
The problem is that the site has a blog which is located on blogspot.com and the stuff from the blog is taken from there. So what I need help with is a rule for this sort of URL:
http://www.valami.hu/index.php?oldal=blog&options=2012/01/some-title-here.html
So, it would be fine like:
http://www.valami.hu/blog/2012/01/some-title-here
The most important is the first rule should be work also as it is more frequently used.
This is actually trivial. Watch and learn!
location / {
try_files $uri $uri/ #site;
}
location #site {
rewrite ^/blog/(.+)$ /index.php?oldal=blog&options=$1 last;
rewrite ^(.+)$ /index.php?oldal=$1 last;
}
The order makes all the difference. You can also do it by removing the last flag and redirecting to /blog with the options query string parameter explicitely set. No if is needed.
well seems we only have 2 cases, the /blog and the non /blog, I'd write 2 location blocks
location ~ ^/blog/(.*) {
try_files $uri /index.php?oldal=blog&options=$1;
}
location ~ /(.*) {
try_files $uri /index.php?oldal=$1;
}
I would have used just / and $request_uri in the second location but that would put a preceeding / in olda1, if that wouldn't matter with you then i'd prefer that method, cause it doesn't involve regex.
About index index.php index.html; and root /var/www/www.valami.hu;, it's better if you move them to the server block instead of the location block, if possible of course.

rewrite rule nginx

Can someone help me for my nginx rewrite rule. I have the problem like this
if file not found in www.abc.com/name_dir/* it will redirect to www.abc.com/name_dir/index.php .
for example :
not found in www.abc.com/xxx/* redirect to www.abc.com/xxx/index.php
not found in www.abc.com/yyy/* redirect to www.abc.com/yyy/index.php
not found in www.abc.com/zzz/* redirect to www.abc.com/zzz/index.php
not found in www.abc.com/kk/* redirect to www.abc.com/kkk/index.php
...
the problem i have thousand of name_dir. I have nginx.conf like this
if (-f $request_filename) {
break;
}
if (-d $request_filename) {
rewrite (^.+$) $1/
break;
}
if (!-e $request_filename) {
rewrite ^/xxx/(.*)$ /xxx/index.php?$1 last;
rewrite ^.+?(/.*\.php)$ $1 last;
}
In configuration above only redirect name_dir xxx. How rewrite rule to redirect all directory ?
Thank for your help
You want to use try_files to check for the existence of files instead of if statements here (because If's are Evil in Nginx).
To to a single directory, it would be like:
location /xxx/{
try_files $uri $uri/ /xxx/index.php;
index index.php
}
What this does is try the uri as a file first. If that doesn't work, it'll try as a directory. If neither work, it'll default to index.php of /xxx/. The extra index line is to keep it from showing a blank page if you go directly to whatever.com/xxx
Using regex, we can expand this rule to work with more than one directory:
location ~* ^(/.*)/{
try_files $uri $uri/ $1/index.php?$uri&$args;
index index.php
}
This should grab the full directory structure and rout it to the appropriate index.
abc.com/yyy/nonexistant.php ==> abc.com/yyy/index.php
abc.com/yyy/zzz/nonexistant.php ==> abc.com/yyy/zzz/index.php
If you only wanted the second example to go to yyy/index.php, use this regex in the location instead:
^(/.*?)/

Resources