How to rewrite based on accept heads in nginx - nginx

I recently switched over to nginx and am fairly new at it, so forgive me if this has been covered extensivly before.
What im trying to do is rewrite the user request based on tthe accept header sent out.
In paticular:
if the accpet header is an image/gif or image/webp then serve the image, if not concat off the .gif of the url and serve that.
hears my apache configuration, but again im on nginx now and trying to learn how i could convert it over:
RewriteCond %{HTTP_ACCEPT} ^image/gif [NC]
RewriteCond %{HTTP_ACCEPT} ^image/webp [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com(.*)$ [NC]
RewriteRule ^i/(.*)\.gif http://example.com/i/$1 [R=302,L]
as you can see the above htaccess file works like a charm, but nginx is completly different it seems.
Ive done some reading and come up with this:
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
with the following inside the server block
location ~* ^/i/.+\.(gif)$ {
root /storage-pool/example.com/public;
add_header Vary Accept;
try_files $uri$webp_suffix $uri =404;
}
Sadly, this doesnt work and I still dont know how to trouble shoot in nginx either.
Any information would be greatly appreciated, thanks.

From your location, the try_files will concat $uri with $webp_suffix which might not what you want, for example if you have a request to /i/test.gif with HTTP_ACCEPT header set to image/webp your location config above will try to find files at:
/storage-pool/example.com/public/i/test.gif.webp
You probably want something like this below instead:
location ~* ^(?P<basename>/i/.+)\.gif$ {
root /storage-pool/example.com/public;
add_header Vary Accept;
try_files $basename$webp_suffix $uri =404;
}
This location will capture the image path without the .gif suffix and it will be available as variable named $basename
More information about named capture here: http://nginx.org/en/docs/http/server_names.html#regex_names

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 conditional Rewrite extensionless URLS

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.

nignx rewrite with or without if

I recently enabled nginx + php-fpm on our centos plesk server. Apache has been stopped and i'm looking for a way to disable it completely.
I run a wordpress site that should be getting quite a bit of traffic in the next few days (1000+ concurrent). Here is my question:
I have these two options as far as i can tell regarding wordpress permalinks with nginx
rewrite /$ /index.php break;
--or--
if (!-e $request_filename) { rewrite ^(.*)$ /index.php break; }
The first one work, and really fast at that too, but it breaks index.htlm in subdirectories, robots.txt, xml sitemap etc (404)
The second one works exactly like a want it but i get a performance hit. It takes about a sec more to start loading the page.
Any of you fine lads have any ideas as I couldn't find anything?
You should give this a read http://wiki.nginx.org/Pitfalls it answers your question in the "Check IF File Exists" section.
A much better way than using if is to use a location match and try_files
location / {
try_files $uri $uri/ /index.php?$args;
}

root defaults to welcome to Nginx when using a "greedy" location

It seems like similar questions have been asked consistently on the site, but despite of browsing dozens of similar questions, none of the solutions seem to work for me.
When I go to mydomain.com, then nginx shows the default "welcome to nginx" page, however, when I visit mydomain.com/whatever/blablabla/whatever then Nginx sends the user to index.php?q=$uri which is the expected behavior.
So the problem only happens when visiting the actual root domain: mydomain.com.
This is my default file:
server {
listen 80;
location / {
include /etc/nginx/include/php;
index index.php;
root /var/www/mydomain.com/current/web;
}
location ~ /(.*)/? {
try_files $uri $uri/ /index.php?$uri;
}
}
Under that configuration, visiting mydomain.com defaults to "welcome to nginx" page, but mydomain.com/whatever is sent to index.php as expected.
When I tweak that to, something like:
location ~ /^(.*)/?$ {
try_files $uri $uri/ /index.php?$uri;
}
or
location ~ /^.*/? {
try_files $uri $uri/ /index.php?$uri;
}
then mydomain.com starts working again, but mydomain.com/whatever starts showing a 404 page. I've tried a bunch of different configurations, but none of the configurations I've tried seem to fully work as I expect.
Basically what I want is pass the whole URL to a front controller, to parse it and take actions depending on the contents of such URL.
If it helps, I want to mimic in Nginx this behavior from Apache:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php
I also have another virtual host:
server {
listen 0.0.0.0:443;
root /var/www/mydomain.com/current/web;
index index.html index.php;
fastcgi_param HTTPS on;
include /etc/nginx/include/ssl;
include /etc/nginx/include/php;
}

Pinnect's htaccess rules to nginx

so I've been playing around with the rules trying to transform them, the pinnect script's rules are:
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine on
#RewriteBase /
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
# fix for uploadify 302, 406 errors
SetEnvIfNoCase Content-Type "^multipart/form-data;" "MODSEC_NOPOSTBUFFERING=Do not buffer file uploads"
I have pinnect on pinnect/ on the server, however VB is running on the index for now,
I've tried
location /pinnect {
try_files $uri $uri/ /index.php;
}
And different variations of that, however let's say I go to the /install directory - it tries to redirect me to pinnect/forums.php(because of VB), if I try to go to index.php directly, an endless loop occurs, anyone could give me a hand with this?
EDIT:
So i've got this rule currently
location ~ ^/pinnect/index.php { try_files maintenance.html #index.php; }
location ~ ^/pinnect/ {
rewrite ^/pinnect$ /pinnect/index.php last;
rewrite ^/pinnect/$ /pinnect/index.php last;
#rewrite ^/pinnect/([^.]+)$ /pinnect/index.php/$1 last;
rewrite ^/pinnect/(.*) /pinnect/index.php/$1 last;
}
However where ever I go, I get a 301, 302 so it's not behaving same way as the htaccess, could anyone help?
If it's just a matter of status code returned, you might have to use return instruction on your location block.
location ~ ^/pinnect/index.php { try_files maintenance.html #index.php; }
location ~ ^/pinnect/ {
rewrite ^/pinnect$ /pinnect/index.php last;
rewrite ^/pinnect/$ /pinnect/index.php last;
#rewrite ^/pinnect/([^.]+)$ /pinnect/index.php/$1 last;
rewrite ^/pinnect/(.*) /pinnect/index.php/$1 last;
return 200;
}
Read more…
As we are here, you should replace last by break since you have your instructions in a location block.
Also, you might prefer using ? instead of (.*) to drop the original arguments.
Read more…

Categories

Resources