Nginx wordpress rewrites for pattern to a particular page - wordpress

I'm trying to set it up so that certain URLs will rewrite (not change URL in address bar) to a particular page with identifying parameters.
I would like
site.com/reviews/froot_loops_review.php AND
site.com/reviews/froot_loops_review
to actually show
site.com/review?title=froot_loops
Additionally, I would like to be able to append any other parameters so:
site.com/reviews/froot_loops_review.php?var=1
would show what's at:
site.com/review?title=froot_loops&var=1
I'm having a hard time with this because it's my first time editing nginx conf files this is as far as I've got but it doesn't work (I think because it doesn't make the first match):
location /reviews/ {
rewrite ^/reviews/(.*)_review.php(.*) /review?title=$1 break;
return 403;
}
What am I doing wrong here? What should my next step be? What is a good resource for learning Nginx rewrites?

I am not sure if this is strictly an answer. But there are multiple issues with your current solution.
This is a WordPress site, so there is already a location ~ \.php$ block which is handling any URI that ends with .php. The URI /reviews/froot_loops_review.php will never make it to the location /reviews/ block in your question.
You can use the ^~ modifier on the location directive to force nginx to ignore any matching regular expression location block. See this document for details.
The rewritten URI cannot be processed within the same location block, so break is the wrong suffix to use. You will have more success using last. See this document for details.
But the main problem is WordPress itself. WordPress normally uses the REQUEST_URI (which is the URI as originally presented) to identify the requested page. Which is why we can rewrite everything to /index.php and still get the right page.
Trying to make WordPress use your rewritten URI without an external redirect (which you say you do not want to do) is tricky. You may be better off looking for a WordPress plugin to achieve it - or try to make the pretty permalinks work the way you want.

Related

Nginx forwarding to different app's different path using `#` symbol

Quick question. We have two apps. Ports 3001 and 3002. Our domain is www.domain.com.
What we want to have it once person enters www.domain.com/pathname we want them to be redirected into another app's specific path.
How to do it?
We already came up to this in my nginx
location /pathname/ {
proxy_pass http://127.0.0.1:3002/;
}
It nearly works. However, our app under 3002 works on path /#/pathname.
We can access it by typing www.domain.com/pathname/#/pathname. We want to access same link by typing www.domain.com/pathname.
How to shorten it? What do I miss?
(upd) Just redirect /pathname to /pathname/#/pathname
According to your comment, you want just redirect from /pathname to /pathname/#/pathname
Try these combined directives:
rewrite to append # and fragment identifier
and proxy_pass to reverse proxy to the app.
E.g.:
location /short_path_name/ {
rewrite ^ /pathname/#/$uri permanent;
break;
}
location /pathname/ {
proxy_pass http://127.0.0.1:3002/;
}
And use www.domain.com/short_path_name/ link for your app.
Unfortunately, nginx can't see the fragment identifier
Unfortunately, you can't. Because server never get the fragment identifier from browser.
The fragment identifier functions differently to the rest of the URI: its processing is exclusively client-sided with no participation from the web server
Naming a bit amusing, but it has a long history. See TBL (1997): Fragment Identifiers on URIs:
The URI reference is a thing you build by taking a URI for an information object, adding a "#" sign and then a Fragement identifier. (The last term is historical, so try not to thinl of it necessarily identifying a fragment).
Workarounds
There are workarounds, e.g. encode hashtag symbol into %23 but I'm not sure is it your way.
Handle request arguments with nginx
Note: rewriting url, nginx can preserve request arguments if you add ? at the end of rewrite directive.
See Nginx rewrite manual:
If a replacement string includes the new request arguments, the previous request arguments are appended after them. If this is undesired, putting a question mark at the end of a replacement string avoids having them appended, for example:
rewrite ^/users/(.*)$ /show?user=$1? last;

Nginx 301 Permanent Redirect For Language Support

I am now enabling language support for my web site. I am including the language as part of the URL. For example: domain.com/en/page I need to setup 301 redirects for existing search engine indexing.
The following works in Nginx to redirect from domain.com/blog to domain.com/en/blog
location = /blog {
return 301 /en/blog;
}
I don't understand the redirect needed to go from domain.com/blog/read/# to domain.com/en/blog/read/# (where # is the sequence field in a postgres database table)
I have spent time looking, searching and reading docs to find this answer myself. I am not understanding.
To prefix the existing requested URI with /en you can use:
return 301 /en$request_uri;
The above will add the three characters before the existing request and also include any arguments that may be present.
To match any URI that begins with /blog, use location /blog { ... }. To match any URI that begins with /blog/read/ use location /blog/read/ { ... }.
Nginx chooses a location to process a request based on a set of rules. So, you will need to consider the other location blocks present within your configuration.

Share lua data between blocks?

I'm trying to use lua to serve 301 redirects directly from nginx instead of having to go through php or other stuffs.
I'm inspired by this article here:
http://www.agileweboperations.com/supporting-millions-of-pretty-url-rewrites-in-nginx-with-lua-and-redis
The idea is that I can save a list of redirects directly to redis, then match and serve them with lua directly within nginx to increase performance.
Since the backend project is Symfony, I have to find a way to tweak the code a bit to suit my need, below is what I have:
Here I try to match the usual mysite.com/this/that requests. I include the lua script to handle the redirection first, if nothing match I let nginx try_files
location / {
include /etc/nginx/include.d/lua_st_redis_rewrites.lua;
try_files $uri #rewriteapp;
}
location #rewriteapp {
rewrite ^(.*)$ /app.php/$1 last;
}
Since I want to support the dev environment, I have to handle url like this as well: mysite.com/app_dev.php/this/that
These urls will not match the location / block so I have to call include lua here again. The problem is that now the links mysite.com/this/that will actually call the lua script twice.
My idea is that I can init a true/false flag in the first call and then use it in the second call to check if the script is already included? At this stage I'm quite confused with the scope of variable however:
# pass the PHP scripts to FastCGI server from upstream phpfcgi
location ~ ^/(app|app_dev)\.php(/|$) {
# # Setup var defaults
# set $no_cache "";
include /etc/nginx/include.d/lua_st_redis_rewrites.lua;
# some more usual code for symfony here
}
Should I use global variables in this case to share data among 2 blocks of lua code? I see the use of global variables is strongly discouraged?
If I include the lua script twice, can I safely assume that variables declared in the script will always be re-declared every time it is called?
Thank you, I'm completely new to this so please forgive my obvious question.
As far as I know you can't include Lua files directly like that. Assuming you are using Openresty you need to use the relevant *_by_lua phase to process the request, in this case rewrite_by_lua.
Different blocks can't access each others globals but you can use the ngx.ctx table which sticks around for the duration of the request.
There's a handy diagram of the openresty phases here.

Fix duplicate query string in nginx

I've got a strange case where my app is now for some reason appending a duplicate query string onto a URL that already has one. I don't have the access or the time to dig into the application code right now, but I do have access to Nginx configs.
What I need is a rewrite rule that will ignore the duplicate query string, ie
http://foo.com?test=bar?test=bar will redirect to http://foo.com?test=bar
Is this even possible? Thank you.
Here, add this inside your server block, before any other location or if:
if ($query_string ~ ^([^?]+)\?\1$) {
set $clean $1;
rewrite . $uri?$clean?;
}
It's quite tricky to get right, because there are more than a few obscure behaviours:
$query_string is the query string without the initial ?
the \1 in the regexp matches a second copy of the first group (...)
you need to save $1 into a new variable because rewrite will overwrite it
you need to use $uri and not $request_uri in the rewrite, because the latter contains a copy of the original query string
you need to add a trailing ? to the rewrite, otherwise the rewrite would append a copy of the original query string! (that's probably the most obscure bit of Nginx syntax, ever)
The simple form of rewrite (without the redirect flag) should be enough for most applications, plus it doesn't require an additional round-trip to the browser.
If it does not work for you, you can try using the $clean query string into the appropriate backend directive (such as fastcgi_param QUERY_STRING and such) or, as a last resort, issuing a browser redirect using the redirect rewrite flag.

nginx multi-stage 404 handling

We just moved to a new site, and want to redirect old links where necessary - however, some still work. For instance,
/holidays/sku.html
still works, while
/holidays/christmas/
no longer works. I'd like to be able to allow the site to attempt to serve a page, and when a 404 is reached, THEN try to pass it through a series of regex redirects, that may look like:
location ~* /holidays/(.*)+$ { set $args ""; rewrite ^ /holidays.html?r=1 redirect; }
I'm using a ~* location directive instead of doing a direct rewrite because we're moving from a Windows-based ASPX site to Magento with php-fpm behind nginx, so we suddenly have to worry about case sensitivity.
Without using nested location directives (which are actively discouraged by nginx documentation) with an #handler of some sort, what's the best way to allow nginx to attempt to serve the page first, THEN pass it across redirects if it fails?
Thanks!
http://wiki.nginx.org/NginxHttpCoreModule#try_files

Resources