Convert /#<handle> to /users/profile/<handle> with nginx - nginx

I'm looking for an nginx rule that would do this:
input url: http://domain.com/#johndoe
what our backend sees: http://domain.com/users/profile/johndoe
Example: http://medium.com/#stuartkhall
The current rule I'm using (removed things that don't have to do with this question):
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name _;
root /var/html;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass mainphp;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
What kind of rule I can add to my current nginx config? I experimented with a rewrite but wasn't able to get it to work.

Better practice is location + return instead of rewrite, so try this (place before any location):
location ~ ^/#(.*)$ {
return 301 /users/profile/$1;
}
or identical rewrite in case you prefer it
rewrite ^/#(.*)$ /users/profile/$1 last;

Related

In NGINX 'location ~ .*' does not match any string

In the following site config file i am trying to:
Load index.php on the first visit.
Load files as they appear in the /uploads/ directory.
Any other request should still be handled by index.php.
server {
listen 80 default_server;
listen [::]:80 default_server;
root /home/va/www/example;
# Add index.php to the list if you are using PHP
# index index.php;
server_name example.dev;
location ~ .*
{
try_files /dev/null #php;
}
location /uploads/
{
try_files $uri =404;
expires 30d;
}
location #php
{
include snippets/fastcgi-php.conf;
#pretty url
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
}
However, the last part breaks. In other words:
/ works
/?test=test works
/uploads/test.jpeg works
/random_string does not work and returns 404 error
My understanding is that location ~ .* has no choice but to match everything. Where is the 404 error coming from?
Ok. After working on it some more, and completely rewriting the logic, i have gotten a muse from The MediaWiki Nginx guide. The final solution is:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /home/va/www/example;
server_name example.dev;
location = /
{
return 301 /home;
}
location = /index.php
{
include snippets/fastcgi-php.conf;
#pretty url
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
location /uploads/
{
try_files $uri =404;
expires 30d;
}
location /
{
rewrite ^/(?<pagename>.*)$ /index.php;
}
location /classes/ { deny all; }
location /config/ { deny all; }
}
I will then use $_SERVER['REQUEST_URI'] within PHP to route the request. Hopefully this solution will help somebody.

Variable username inside url address in NGINX

I still struggling with making mystaticusername variable user name. I mean when I have particular username /statisusername/ backend working properly on nginx. But how can I make my configuration for more users? Means use instead mystaticusername some redirection where each username will know login to backend.
How can I change my nginx configuration?
server {
server_name example.com www.example.com;
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
root /usr/share/nginx/www;
charset utf-8;
index index.html index.php /index.php;
location = / {
rewrite ^ /index.php;
}
location / {
rewrite ^([^\.]*)$ /$1.php;
rewrite ^/([A-Za-z0-9_]+)$ /admin/index.php?q=$uri&$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
location /mystaticusername {
try_files $uri/ /admin/index.php?q=$uri&$args;
}
location = /mystaticusername/options {
try_files $uri $uri/ /admin/index.php?hotelname=$1&do=options;
}
}
Not much context given, so I'm just guessin... but looks like you could condense your location directives to 3 statements.
This will default to index.php, but in the case of example.com/mystaticusername if would try that url and since it does not exist (guessing) it would serve up /admin/index.php?q=$uri&$args. This would also allow urls like exmaple.com/about to resolve. Just make certain to not allow users to create a username of 'about'
location / {
try_files $uri $uri/ /admin/index.php?q=$uri&$args;
}
Not certain what your goal is, but this would get you example.com/mystaticusername/options to try serve up /admin/index.php?hotelname=$1&do=options
location ~* ^/[a-zA-Z0-9]*/options$ {
try_files $uri /admin/index.php?hotelname=$1&do=options;
}
Leave php as-is
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}

Nginx rewrite in subfolder (404)

I has a site host on a NGINX server which used to work fine to remove index.php in nginx site config using try_files.
But now I am going to add a blog on it, where the URL will be www.foo.com/blog, I can access the blog and use index.php?p=.
But, once I use pretty permalink with Nginx Helper, www.foo.com/blog/2013/07/bar, I get 404.
server {
# don't forget to tell on which port this server listens
listen 80;
# listen on the www host
server_name foo.com;
# and redirect to the non-www host (declared below)
return 301 $scheme://www.ultra-case.com$request_uri;
}
server {
# listen 80 default_server deferred; # for Linux
# listen 80 default_server accept_filter=httpready; # for FreeBSD
listen 80;
# The host name to respond to
server_name www.foo.com;
# Path for static files
root /web/foo.com
#index file
index index.php;
#Specify a charset
charset utf-8;
# Custom 404 page
error_page 404 /404.html;
# Uri Rewrite
location /blog {
index index.php;
try_files $uri $uri/ /blog/index.php?$args;
}
location / {
autoindex on;
# This is cool because no php is touched for static content.
# include tihe "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi.conf;
fastcgi_intercept_errors on;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}
# Include the component config parts for h5bp
include conf/h5bp.conf;
}
The accepted answer routes everything through index.php.
This will break certain script includes, the wp-admin script being one of them.
You can use:
location /blog/ {
index index.php;
try_files $uri $uri/ /blog/index.php?$args;
}
Um... Thank you for all comments and answer. But finally I use this method to get it works
location /blog {
index index.php;
rewrite ^/blog/(.*)+$ /blog/index.php?$1; # it finally works
# return 200 $request_uri; # it is for inspect what $request_uri is
# try_files $uri $uri/ /blog/index.php$request_uri$is_args$args; # it gets 500 server error
}
Please point out if current setting has any problems. thank you!
I would suggest the following, to catch any permalinks under subfolder /blog
location /blog {
index index.php;
try_files $uri $uri/ /blog/index.php?$args;
}
Try this, I changed my answer to try to imitate the same behaviour you are using in your rewrite.
location ~ /blog(.*) {
index index.php;
try_files $uri /blog/index.php?$1&$args;
}
Try this
location /api {
# example: http://demo.com/api/channels/dmzb
root /data/webserver/demo.com/api/web;
rewrite ^/api/(.*) /$1 break;
try_files $uri $uri/ /api/index.php?$args;
location ~ ^/api/index\.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
# fix request_uri
set $changed_request_uri $request_uri;
if ($changed_request_uri ~ ^/api(.*)) {
set $changed_request_uri $1;
}
fastcgi_param REQUEST_URI $changed_request_uri;
# fix script_filename
fastcgi_split_path_info ^(?:\/api\/)(.+\.php)(.*);
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
}
Think for php, rewrite is no needed with something like this:
location /app/ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /path/to/your/app/index.php;
fastcgi_pass php;
}
With following fastcgi pass
upstream php {
server unix:/var/run/php5-fpm.sock;
}
A universal solution for pretty URLs in root and one subfolder level:
set $virtualdir "";
set $realdir "";
if ($request_uri ~ ^/([^/]*)/.*$ ) {
set $virtualdir /$1;
}
if (-d "$document_root$virtualdir") {
set $realdir "${virtualdir}";
}
location / {
try_files $uri $uri/ $realdir/index.php?$args;
}
I found that with permalink enabled, I needed a combination of both sets of answers given here, otherwise
With only the rewrite, none of the static files got served
With only the try files, the permalinks did not work
This is working on my set up
location /blog/ {
rewrite ^/blog/(blog/(tag|category|20??)/.*)+$ /blog/index.php?$1;
try_files $uri $uri/ /blog/index.php?$args =404;
}
ip url: 123.123.123/xxxxxxxxxx/
location /xxxxxxxxxx/ {
try_files $uri $uri/ /xxxxxxxxxx/index.php?$query_string;
}
# Rewrite multisite '.../wp-.*' and '.../*.php'.
if (!-e $request_filename) {
rewrite ^(/xxxxxxxxxx/.*)+(/wp-.*) /xxxxxxxxxx/$2 last;
rewrite ^(/xxxxxxxxxx/.*)+.*(/wp-admin/.*\.php)$ /xxxxxxxxxx/$2 last;
rewrite ^(/xxxxxxxxxx/.*)+(/.*\.php)$ /xxxxxxxxxx/$2 last;
}

Configuring subdomain in NGINX

I am trying to configure a subdomain in NGINX. Where am I going wrong?
Following is the configuration file:
server {
listen 80;
server_name www.teamomattic.com;
rewrite ^/(.*) http://teamomattic.com permanent;
}
server {
listen 80 default;
server_name teamomattic.com *.teamomattic.com;
root /home/jclark/web/teamomattic.com;
access_log /var/log/nginx/$host-access.log;
error_log /var/log/nginx/dev-error.log error;
index index.php index.html index.htm;
try_files $uri $uri/ #rewrite;
location #rewrite {
rewrite ^/(.*)$ /index.php/$1;
}
location ~ \.php {
# try_files $uri =404;
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
}
server {
listen 80;
server_name test.teamomattic.com;
root /home/jclark/web/teamomattic.com/images;
access_log /var/log/nginx/$host-access.log;
error_log /var/log/nginx/dev-error.log error;
index index.php index.html index.htm;
}
Just guessing. I would do it this way.
server
{
listen 80;
server_name subdomain.teamomattic.com;
location / { return 303 http://teamomattic.com$request_uri; }
}
303 is the new temporary redirect. I never use permanent redirects, b/c you stay flexible and don't need to ask your custormers to clear cache.
You may not need this location block wrapper and can directly use return in server. But it is best practice to use always location, b/c you can add more locations easily.
Please use https if possible.
request_uri passes path and query string through - so you don't loose that info.

nginx server configuration: subdomain to folder

I migrated from Apache 2 to nginx and I've got problems to handly my subdomain control.
What I want: When x.domain.tld is requested, internally rewrite to domain.tld/x
The problem I've got is that nginx always redirects the page by telling the browser to redirect to. But what I really want is to do this internally, like Apache 2 did.
Also, if I only request x.domain.tld, nginx returns a 404. It only works when I do x.domain.tld/index.php
Here's my config:
server {
listen 80 default;
server_name _ domain.tld www.domain.tld ~^(?<sub>.+)\.domain\.tld$;
root /home/domain/docs/;
if ($sub) {
rewrite (.*) /$sub;
}
# HIDDEN FILES AND FOLDERS
rewrite ^(.*)\/\.(.*)$ #404 break;
location = #404 {
return 404;
}
# PHP
location ~ ^(.*)\.php$ {
if (!-f $request_filename) {
return 404;
}
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/etc/nginx/sockets/domain.socket;
}
}
Thanks!
As I found this Q&A on Google while looking for a solution for the same problem, I wanted to post the solution I finally used.
The first server block by MTeck looks pretty nice, but for the subdomains part you could simply do the following:
server {
listen 80;
server_name "~^(?<sub>.+)\.domain\.tld$";
root /path/to/document/root/$sub;
location / { try_files $uri $uri/ /index.php; }
location ~ \.php {
include fastcgi_params;
fastcgi_pass unix:/etc/nginx/sockets/domain.socket;
}
}
This makes the root configuration directive dependent on the subdomain.
I spent hours beating my head against the wall and this is what works for me
server {
listen 80;
server_name ~^(?P<sub>.+)\.example\.com$; #<-- Note P before sub, it was critical for my nginx
root /var/www/$sub; #<-- most important line cause it defines $document_root for SCRIPT_FILENAME
location / {
index index.php index.html; #<-- try_files didn't work as well
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000; #<-- probably you have another option here e.g. fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
}
You should take a look at http://wiki.nginx.org/IfIsEvil. You're doing a whole lot wrong in this configuration file.
server {
server_name domain.tld www.domain.tld;
location / {
try_files $uri /index.php;
}
location ~ \.php {
include fastcgi_params;
fastcgi_pass unix:/etc/nginx/sockets/domain.socket;
}
}
server {
server_name "~^(?<sub>.+)*\.(?<domain>.*)$";
return 301 $scheme://$domain/$sub$request_uri;
}
If what you want is to keep that internal, you won't be able to rewrite it. By definition, a cross site rewrite needs to be sent back to the browser. You'll have to proxy the request.
server {
server_name "~^(?<sub>.+)*\.(?<domain>.*)$";
proxy_pass http://$domain/$sub$request_uri;
}
You should read the Nginx wiki. All of this is explained in depth.
This will work for www also.
server {
listen 80 default_server;
listen [::]:80 default_server;
index index.php index.html index.htm index.nginx-debian.html;
server_name ~^www\.(?P<sub>.+)\.domain\.com$ ~^(?P<sub>.+)\.domain\.com$;
root /var/www/html/$sub;
location / {
try_files $uri $uri/ /index.php?$args;
}
}

Resources