Nginx Replace Query string redirect - regex

We were running on apache previously and used the below code to redirect/replace one of our query parameters.
RewriteCond %{QUERY_STRING} ^limit=(.*)$ [NC]
RewriteRule ^ %{REQUEST_URI}?product_list_limit=%1 [L,R=301]
This would successfully redirect the below URL
www.example.com/clothing.html?limit=all
TO
www.example.com/clothing.html?product_list_limit=all
I have used a htaccess redirect convertor that has produced the below. This doesn't work
location ~ / {
if ($query_string ~* "^limit=(.*)$"){
rewrite ^(.*)$ /$request_uri?product_list_limit=%1 redirect;
}
}
Any help appreciated
Thanks

You should not use $request_uri to construct the rewritten URI, as it also contains ?limit=all - so your rewritten URI would look like: /clothing.html?limit=all?product_list_limit=all
The rewrite statement resets numeric captures, so you will need to use a named capture in the if statement.
The URI without query string is available as $uri or as a capture from the rewrite statement's regular expression.
Either of these forms should work for you:
if ($query_string ~* "^limit=(?<limit>.*)$") {
rewrite ^(.*)$ $1?product_list_limit=$limit? redirect;
}
Note the trailing ? to prevent the original query string from being appended. See this document for more.
Or:
if ($query_string ~* "^limit=(.*)$") {
return 302 $uri?product_list_limit=$1;
}
The value of the limit argument is also available as $arg_limit, so you could also use this:
if ($arg_limit) {
return 302 $uri?product_list_limit=$arg_limit;
}
See this document for details.

Related

regex with query string containing?

I am trying to redirect the following URL:
url/efx.aspx?xxxxxxx
to url/car-audio/efx-hardware/amp-install-kits
However it is redirecting whatever contains efx.aspx with the letters without the ? sign. I was wondering how I can fix this?
for example it is redirecting the following:
domain.com/efx.aspxlsdkjfhlasdf
but it is not redirecting
domain.com/efx.aspx?lsdkjfhlasdf
here is the .htaccess rule I wrote. how can I correct it?
RewriteCond %{REQUEST_URI} /efx.aspx[^/]+$
RewriteRule (.*) /car-audio/efx-hardware/amp-install-kits [R,L]
You can use this rule:
RewriteRule ^efx\.aspx$ /car-audio/efx-hardware/amp-install-kits? [R=301,NC,L]
Query string is not part of REQUEST_URI hence [^/]+ after efx.aspx fails your rule.
Also ? at the end of target URI removes any existing query string.

Rewrite with 404 urls with nginx

I'm trying to rewrite some urls which are showing up as 404's but the I can't get the rewrite to work. The Urls look like this /ossobuco-alla-milanese​​/1451114854360.1451114854360?time=1451114851111. I would like to remove 1451114854360.1451114854360?time=1451114851111 with a rewrite.
In my nginx config I have the following rewrite rule
rewrite "^\/(.*)\/(\d{13}\.\d{13}\?time=\d{13})$" /$1/ permanent;
I tested the regex in 2 online regex tools regex101 and regex pal and it should work but the don't seem to work on my server.
To match query string use $args:
location / {
if ($args ~* "^time=\d+") {
set $args '';
rewrite "^/(.+)/\d+\.\d+/?$" /$1 permanent;
}
}
PS: If you want to match only 13digits.13digits then use:
rewrite "^/(.+)/\d{13}\.\d{13}/?$" /$1 permanent;
In the end its was just a really simple location block and the ? removes the args.
location ~* ^/(.+)/\d+\.\d+$ {
rewrite ^/(.+)/\d+\.\d+$ /$1? permanent;
}

Rewriting a URL to a query string on Apache and Nginx

I'm trying to set up some path rewrites on two separate servers, one using mod-rewrite on Apache and one using HttpRewriteModule on Nginx. I don't think I'm trying to do anything too complex, but my regex skills are a little lacking and I could really use some help.
Specifically, I'm trying to transform a formatted URL into a query string, so that a link formatted like this:
http://www.server.com/location/
would point to this:
http://www.server.com/subdirectory/index.php?content=location
Anything extra at the end of the formatted URL should be appended to the "content" parameter in the query string, so this:
http://www.server.com/location/x/y/z
should point to this:
http://www.server.com/subdirectory/index.php?content=location/x/y/z
I'm pretty sure this should be possible using both Apache mod-rewrite and Nginx HttpRewriteModule based on the research I've done, but I can't see to get it working. If anyone could give me some pointers on how to put together the expressions for either or both of these setups, I'd greatly appreciate it. Thanks!
In nginx you match "/location" in a rewrite directive, capture the tailing string in the variable $1 and append it to the replacement string.
server {
...
rewrite ^/location(.*)$ /subdirectory/index.php?content=location$1 break;
...
}
In Apache's httpd.conf this looks quite similar:
RewriteEngine On
RewriteRule ^/location(.*)$ /subdirectory/index.php?content=location$1 [L]
Have a look at the examples at the end of this page: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
Search string: (.+)/location/(.*)$
replacement string: $1/subdirectory/index.php?content=location/$2
For Apache, in the htaccess file in your document root, add:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/subdirectory/index\.php$
RewriteRule ^(.*)$ /subdirectory/index.php?content=$1 [L]
In nginx, you want to first make sure requests for /subdirectory/index.php get passed through, then rewrite everything else:
location ~ /subdirectory/index\.php$
{
}
location /
{
rewrite ^(.*)$ /subdirectory/index.php?content=$1 break;
}
This would probably be the best way to do it in nginx:
location ^~ /location/ {
rewrite ^/(location/.*)$ /subdirectory/index.php?content=$1 last;
}
For more details, see:
http://nginx.org/r/location
http://nginx.org/r/rewrite

mod_rewrite to nginx rewrite rules

I have converted most of my Apache HTTPd mod_rewrite rules over to nginx's HttpRewrite module (which calls PHP-FPM via FastCGI on every dynamic request). Simple rules which are defined by hard locations work fine:
location = /favicon.ico { rewrite ^(.*)$ /_core/frontend.php?type=ico&file=include__favicon last; }
I am still having trouble with regular expressions, which are parsed in mod_rewrite like this (note that I am accepting trailing slashes within the rules, as well as appending the query string to every request):
mod_rewrite
# File handler
RewriteRule ^([a-z0-9-_,+=]+)\.([a-z]+)$ _core/frontend.php?type=$2&file=$1 [QSA,L]
# Page handler
RewriteRule ^([a-z0-9-_,+=]+)$ _core/frontend.php?route=$1 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/$ _core/frontend.php?route=$1 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)$ _core/frontend.php?route=$1/$2 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/$ _core/frontend.php?route=$1/$2 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)$ _core/frontend.php?route=$1/$2/$3 [QSA,L]
RewriteRule ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/$ _core/frontend.php?route=$1/$2/$3 [QSA,L]
I have come up with the following server configuration for the site, but I am met with unmatched rules after parsing a request (eg; GET /user/auth):
attempted nginx rewrite
location / {
# File handler
rewrite ^([a-z0-9-_,+=]+)\.([a-z]+)?(.*)$ /_core/frontend.php?type=$2&file=$1&$3 break;
# Page handler
rewrite ^([a-z0-9-_,+=]+)(\/*)?(.*)$ /_core/frontend.php?route=$1&$2 break;
rewrite ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)(\/*)?(.*)$ /_core/frontend.php?route=$1/$2&$3 break;
rewrite ^([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)\/([a-z0-9-_,+=]+)(\/*)?(.*)$ /_core/frontend.php?route=$1/$2/$3&$4 break;
}
What would you suggest for dealing with my File Handler (which is just filename.ext), and my Page Handler (which is a unique route request with up to 3 properties defined by a forward slash)?
As I haven't gotten a response from this yet, I am also unsure if this will override my PHP parser which is defined with location ~ \.php {}, which is included before these rewrite rules.
Bonus points if I can solve the parsing issues without the need to use a new rule for each number of route properties.
I ended up writing the following rules:
File Handler
location ~ ^/([a-zA-Z0-9-_]*)\.([a-zA-Z0-9]*)$ { include /web/_config/php.conf; rewrite ^/([a-zA-Z0-9-_]*)\.([a-zA-Z0-9]*)$ /_core/frontend.php?type=$2&file=$1 last; }
The file handler grabs the name and extension and writes it into type={ext}&file={name}.
Page Handler
location ~ ^/([a-z0-9-_]*)$ { include /web/_config/php.conf; rewrite ^/([a-z0-9-_]*)$ /_core/frontend.php?route=$1 last; }
location ~ ^/([a-z0-9-_]*)/?([a-z0-9-_]*)$ { include /web/_config/php.conf; rewrite ^/([a-z0-9-_]*)/?([a-z0-9-_]*)$ /_core/frontend.php?route=$1/$2 last; }
location ~ ^/([a-z0-9-_]*)/?([a-z0-9-_]*)/?([a-z0-9-_]*)$ { include /web/_config/php.conf; rewrite ^/([a-z0-9-_]*)/?([a-z0-9-_]*)/?([a-z0-9-_]*)$ /_core/frontend.php?route=$1/$2/$3 last; }
The page handler (which in this case handles up to 3 "directories") grabs the string between each separator(/), does a regex-validation and writes it as a query string.
The main difference between this and my original configuration was that each entry has its own location handler, with the last rule it processes it on the first match, so performance should be slightly better.
I also discovered that nginx appends query strings by default, so that regex isn't required, another performance improvement.
Note that /web/_config/php.conf is simply a FastCGI pass-through configuration, and the one shipped with nginx (usually /etc/nginx/fastcgi.conf) should work fine. Note that if you're dealing exclusively with PHP, you don't need to define this in each rule, just prepend them with the include.
Hope this helps.

Regular expression transcription

I have to translate this: http://*myurl*/feedback.php?rcode=1307954819&lang=it
in
http://*myurl*/index.php?option=com_cake&module=lodgings&task=feedback&id=1307954819
Can someone help me ? :)
Edit:
I have to write it in .htaccess so I need rewrite rules.
# activate rewrite engine
RewriteEngine On
# mark / as a root
RewriteBase /
# rewrite feedback.php
RewriteCond %{QUERY_STRING} ^rcode=(\d+)
RewriteRule ^feedback.php$ index.php?option=com_cake&module=lodgings&task=feedback&id=%1 [L]
The rule above will rewrite /feedback.php?rcode=1307954819&lang=it into /index.php?option=com_cake&module=lodgings&task=feedback&id=1307954819 without changing URL in address bar of the browser.
If you need to change URL in address bar as well (to make a redirect) then change [L] into [R=301,L]
You don't need RegEx for this.
You can use str_replace.
$URL='http://myurl/feedback.php?rcode=1307954819&lang=it';
$newURL=str_replace(array('http://myurl/feedback.php','?rcode=','&lang=it'),array('http://myurl/index.php','?option=com_cake&module=lodgings&task=feedback&id=',''),$URL);
Without taking into acount option amd module params:
$url = 'http://*myurl*/feedback.php?rcode=1307954819&lang=it';
echo preg_replace('%^http://([^/]*)/([^.]*)\.php\?rcode=([0-9]*).*$%','http://$1/index.php?option=com_cake&module=lodgings&task=$2&id=$3',$url);
In .htaccess it should be:
RewriteRule ^/([^.]*)\.php\?rcode=([0-9]*).*$ /index.php?option=com_cake&module=lodgings&task=$1&id=$2
My example is in C# (not a php developer), but the regex pattern should work in both languages..
void Main()
{
string input = #"http://myurl/feedback.php?rcode=1307954819&lang=it";
Regex pattern = new Regex(".+?&?rcode=([^&]+)");
string output = pattern.Replace(input, #"http://myurl/index.php?option=com_cake&module=lodgings&task=feedback&id=$1");
Console.WriteLine(output);
}