NGINX rewrite to file with query parameters - nginx

I want nginx to rewrite the url to specific php files that can be determined by the content before the first slash
For example:
testing.com/test or test.com/test would be rewritten to test.php
testing.com/test2/variable/another-variable would be rewritten to /test2.php?q=variable/another-variable
I would then use PHP to explode the q GET parameter.
What I currently have tried is:
location / {
try_files $uri $uri/ $uri.html $uri.php$is_args$query_string;
}
This works for example 1 I have displayed above, but returns a 404 for example 2 with a more complicated URL.

You can use a named location with the try_files directive to implement one or more rewrite statements. See this document for details.
For example:
location / {
try_files $uri $uri/ $uri.html #php;
}
location #php {
rewrite ^(/[^/]+)$ $1.php last;
rewrite ^(/[^/]+)/(.*)$ $1.php?q=$2 last;
}
location ~ \.php$ {
try_files $uri =404;
...
}
The rewrite statements are evaluated in order. The second try_files statement ensures that the PHP file actually exists and is to avoid passing uncontrolled requests to PHP.

Related

nGinx Rewrite Issue exclusion

I am attempting to rewrite my /support url, so I can grab the "page" as an appended querystring.
The issue I am running into now, is my assets are also contained in the /support subfolder, so they too are getting re-written.
How can I change this to exclude my assets? (where assets = /support/assets/styles, /support/assets/scripts, etc...)
Here is my current location block
location /support/ {
index index.php;
rewrite ^/support/(.*) /support/index.php?_p=$1 last;
try_files $uri $uri/ /support/index.php?$args;
}
You can check for the assets with try_files before performing the rewrite by using a named location.
For example:
location /support/ {
index index.php;
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^/support/(.*) /support/index.php?_p=$1 last;
}
See this document for more.

Wordpress Multisite with nginx. Match subdirectories within location

I have multiple WordPress sites running in subdirectories.
Everything works great, but I'm looking to simplify my nginx configuration.
At the moment, when I add a location, I need to add an entry to my server {} configuration for the specified directory.
location / {
try_files $uri $uri/ /index.php?q=$args;
}
location /site1 {
try_files $uri $uri/ /site1/index.php?q=$args;
}
location /site2 {
try_files $uri $uri/ /site2/index.php?q=$args;
}
location /site2 {
try_files $uri $uri/ /site3/index.php?q=$args;
}
location /site4 {
try_files $uri $uri/ /site4/index.php?q=$args;
}
I tried adding a regex to match the subdirectory, but seem to have a problem with it.
location /([_-0-9a-zA-Z]/?) {
try_files $uri $uri/ /$1index.php?q=$args;
}
does not appear to do the trick. In theory that should match a subdirectory, or nothing, and be able to let me add new directories without having to touch the nginx configuration.
Any pointers would be appreciated.
#jedifans pointed out how to get the regex to work
Thanks. That did the trick on any pages, but when I go to / it just tries to download the index.php.
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_pass php70;
fastcgi_keep_conn on;
}
location ~ ^/([_\-0-9a-zA-Z]*/?) {
try_files /$1$uri /$1$uri/ /$1index.php?q=$args;
}
However when I go to domain.com/site1/ i get a download of the index.php not the homepage. What's missing?
I think you are missing the following from your new location block, the ~ operator that says to nginx that it's a regular expression. Try:
location ~ ^/([_-0-9a-zA-Z]*/?) {
A few regex tweaks too, ^ to say it must begin with / and * to match more than one of those characters within [ and ]
Edit: after your question update, try the following try_files directive:
try_files $uri $uri/ /$1/index.php?q=$args;
$uri should work without the matched string prepended and I have added a / in between the matched query and the index.php;
Also make sure to have index index.php; at server{} level.

nginx try_files without any files - internal redirect

Given:
location ~ /foo/ {
try_files $uri $uri/ /foohandler.py;
}
try_files: "If none of the files were found, an internal redirect to the uri specified in the last parameter is made" 1.
If I know $uri and $uri/ will never exist, how do I always do an internal redirect to /foohandler.py without using try_files?
Using try_files /foohandler.py is invalid syntax. What is the proper equivalent? return? rewrite?
location ~ /foo/ {
rewrite ^ /foohandler.py break;
}
You can still use try_files. It requires more than one parameter, so just add a 404 code to avoid the syntax error:
location ~ /foo/ {
try_files /foohandler.py =404;
}
On a side note, if your uri always begins with /foo/ then a prefix location would be better:
location /foo/ {
try_files /foohandler.py =404;
}

nginx rewrite if specific name is included

I would like to rewrite all requests that contain 'xhr.php' to /xhr.php instead of the original path.
The request:
type: "POST",
url: "/system/classes/templates/address/xhr.getAddress.php",
data: vars,
dataType: "html"
Should go to /xhr.php with the path as argument. I tried this:
rewrite ^/(.*)/xhr.(.*)\.php$ /xhr.php?parameter=$1&parameter2=$2 last;
However it does not work. Any ideas? My Config looks like this:
location / {
root /var/www/http;
try_files $uri $uri/ index.php /index.php$is_args$args #rewrite;
}
location #rewrite {
rewrite ^/(.*)/xhr.(.*)\.php$ /xhr.php?parameter=$1&parameter2=$2 last;
}
Is this basically possible with nginx? Whats wrong here?
Thanks :)
//EDIT:
I solved it, however it does not look very efficient …
location / {
root /var/www/http;
try_files $uri $uri/ index.php /index.php$is_args$args;
}
if ($request_uri ~ .*/xhr.*) {
rewrite ^/(.*)/xhr.(.*)\.php$ /xhr.php?parameter=$1&parameter2=$2 break;
}
You can remove the if and let the rewrite at the same level of location. In this way you'll save one regex for each request (the one inside the if).
Actually I think you can remove the location / too:
root /var/www/http;
rewrite ^/(.*)/xhr.(.*)\.php$ /xhr.php?parameter=$1&parameter2=$2 break;
try_files $uri $uri/ index.php /index.php$is_args$args;

Nginx - multiple/nested IF statements

What i want to do:
Check if request comes from Facebook
Check if URL is like domain.com/2
If above conditions are true - show content from /api/content/item/$1?social=1
If above conditions are false - show "normal page"
It is a single page app. Before my changes configuration looked like this (and it worked):
location / {
root /home/eshlox/projects/XXX/project/project/assets/dist;
try_files $uri $uri/ /index.html =404;
}
I've tried to use if statements:
location / {
set $social 1;
if ($http_user_agent ~* "facebookexternalhit") {
set $social UA;
}
if ($uri ~* "^/(\d+)$") {
set $social "${social}URL";
}
if ($social = UAURL) {
rewrite ^/(\d+)$ /api/content/item/$1?social=1;
}
root /home/eshlox/projects/XXX/project/project/assets/dist;
try_files $uri $uri/ /index.html =404;
}
With this configuration everything works as i expected only if both conditions are true or false.
If one of conditions is true and the second is false (or vice versa) then nginx always returns status 404.
I have found "IfIsEvil" on nginx site, i've tried to use mapping (can i use mapping in this case?) but still i can't resolve this problem.
Any ideas?
Best regards.
There is good article about common pitfalls in nignx wiki.
First, I've moved root directive to server level. Second, location is the best way to check urls. So I rethink your requirements as
if location consist of digits
and request from facebook
we have to rewrite url, and the result is:
root /home/eshlox/projects/XXX/project/project/assets/dist;
location / {
try_files $uri $uri/ /index.html;
}
location ~ "^/\d+$" {
if ($http_user_agent ~* "facebookexternalhit") {
rewrite (.+) /api/content/item$1?social=1;
}
try_files $uri $uri/ /index.html;
}
Also, there is almost no reason to have =404 after /index.html in try_files directive.

Resources