I am using a rewriteRule to fix some urls from an old webshop so to make them available within a new webshop (relaunch). This is the regex.
#change period to dash
RewriteRule "^(.*)/([^.]*)\.+([^.]*\..*)$" $1/$2-$3 [L,NC]
RewriteRule "^(.*)/([^.]*)\.([^.]*)$" $1/$2-$3 [L,NC,R=302]
The idea is to convert periods in the url to a single dash.
/Biertischhussen/Dena-Biertischhusse-3tlg.-Set-Arcade-50x220cm-ecru-lang
/Biertischhussen/Dena-Biertischhusse-3tlg-Set-Arcade-50x220cm-ecru-lang
The rewriteRule only works 80% though, because it produces double dashes... How can I fix this?
/Biertischhussen/Dena-Biertischhusse-3tlg--Set-Arcade-50x220cm-ecru-lang/
If you add a consuming -* pattern after \.+, all existing - symbols will get matched, and thus will get removed as a result of the replacement (since they are not captured, i.e. they are not inside (...)).
Use
"^(.*)/([^.]*)\.+-*([^.]*\..*)$"
^^
and
"^(.*)/([^.]*)\.-*([^.]*)$"
^^
Related
I have a problem with .htaccess file, as I understand RewriteRule help to rewrite the URL. But when I try the following 2 cases it doesn't work.
#1 The first RewriteRule works but the second doesn't work
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?idcat=$1 [L] #working
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?idl=$1 [L] #not working
#2 The RewriteRule doesn't work with dash but works with slash and underscore.
RewriteRule ^([a-zA-Z0-9_-]+)-([a-zA-Z0-9_-]+)$ index.php?idl=$1&iddis=$2 [L] #not working
RewriteRule ^([a-zA-Z0-9_-]+)_([a-zA-Z0-9_-]+)$ index.php?idl=$1&iddis=$2 [L] #working
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)$ index.php?idl=$1&iddis=$2 [L] #working
So how to fix these problems? Does anyone have any suggestions for me?
#1 The first Rewriterule works but the second doesn't work
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?idcat=$1 [L] #working
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?idl=$1 [L] #not working
Because you are using the same pattern in both rules, the first rule always "wins" and the second rule is never triggered. This is essentially processed as follows (pseudo-code):
if (the URL matches the pattern "^([a-zA-Z0-9_-]+)$") {
rewrite the request to "index.php?idcat=<url>"
}
elseif (the URL matches the pattern "^([a-zA-Z0-9_-]+)$") {
rewrite the request to "index.php?idl=<url>"
}
As you can see, the second code block is never processed since the expressions are the same.
To put it another way, how would you determine whether a request of the form /foo should be rewritten to index.php?idcat=foo or to index.php?idl=foo? You can't rewrite the request to both.
In this particular case you could perhaps rewrite everything to index.php?id=<url> and let your script decide whether it should be idcat or idl. Otherwise, there needs to be something different about the two URLs (and consequently the patterns you are using to match the URLs) that allows you to determine how the URL should be rewritten.
#2 The Rewriterule doesn't work with dash but works with slash and underscore.
RewriteRule ^([a-zA-Z0-9_-]+)-([a-zA-Z0-9_-]+)$ index.php?idl=$1&iddis=$2 [L] #not working
RewriteRule ^([a-zA-Z0-9_-]+)_([a-zA-Z0-9_-]+)$ index.php?idl=$1&iddis=$2 [L] #working
Both these rules have the same problem, depending on the URLs being requested. This is because the patterns/regex you are using are "ambiguous". Each of the two subpatterns (either side of the delimiter), that are used to match the idl and iddis values, contain the same character as the expected delimiter, - or _. However, in the 3rd rule (not shown), you are using a / as the delimiter, which does not occur in the surrounding subpatterns, so there is no ambiguity,
For example, how should (or you would expect) a URL of the form /foo-bar-baz to be matched by the first rule? Since the first subpattern uses the greedy quantifier +, it will capture foo-bar and baz and rewrite the request to index.php?idl=foo-bar&iddis=baz.
To avoid this "ambiguity" you need to make sure the delimiter between the subpatterns (ie. between the values for idl and iddis) is different to the characters used in the subpatterns (or at least one of the two subpatterns).
This can often be resolved by making the regex as specific as possible. ie. Match only the valid characters in idl and iddis.
To begin resolving this issue, you need to first identify the precise URLs you are trying to match, before implementing the rules to match them.
I am doing a rewriterule inside of my .htacess folder in one of my htdocs folders.
The rewriterule looks something like this:
RewriteRule ^index/(blah)/(blah2)/(blah3)..../(blah20)
^^^The above code looks like bad practice--don't worry about that.
Anyways, I heard before that ${20} was the correct way to access the 20th match group in regex, but even though in regex101 my 20th match group is matching blah20, whenever I print out the 20th capture group, I just get ${20}.
Why is this? Am I correctly accessing two digit match groups?
Edit--real rewriterule:
RewriteRule ^a/([\d]*)/(b/([\d]{2}:[\d]{2}:[\d]{2})/?)?(c/(\w*)/?)?(d/([\w]
{6})/?)?(e/([\w]{6})/?)?(f/([\w]{6})/?)?(g/([\w]{6})/?)?(h/([\w]{6})/?)?
(i/([\w]{6})/?)?(j/([\w]{6})/?)?(k/([\w]{6})/?)?(l/([\w]{6})/?)?(m/([\w]
{6})/?)? /index.php?a=$1&b=$3&c=$5&d=$7&e=$9&f=${11}&g=${13}&h=${15}&i=${17}&
j=${19}&k=${21}&l=${23}&m=${25} [L]
You cannot use back-reference number greater than 9 as per official mod_rewrite documentation.
From Manual:
RewriteRule back-references: These are back-references of the form $N (0 <= N <= 9). $1 to $9 provide access to the grouped parts (in parentheses) of the pattern, from the RewriteRule which is subject to the current set of RewriteCond conditions. $0 provides access to the whole string matched by that pattern.
If you are dealing with so many back-references then it is better to pass full URI after index/ to index.php and use explode inside the php code:
RewriteRule ^index/(.+)$ index.php?q=$1 [L,QSA,NC]
For example like this:
RewriteRule \^index(?:\/\w+){5}\/(blah6)
Will match 6th folder in the url.
When using categories in ExpressionEngine, a Category URL Indicator trigger word can be set to load a category by its {category_url_title}.
I would like to remove the category "trigger word" from the URL.
Here is what I have so far, with the trigger word set to "category":
RewriteRule /products/(.+)$ /products/category/$1 [QSA,L]
I'm not an expert at writing regular expressions, but I do a little. I'm 99% sure my RegEx is fine, however when trying to use it as a RewriteRule in my .htaccess file, I'm getting a 500 error.
I'm sure it's something stupid, but for some reason I'm not seeing my mistake. What am I doing wrong?
Update: Adding a ^ to the beginning of the RewriteRule fixed the 500 error.
RewriteRule ^/products/(.+)$ /products/category/$1 [QSA,L]
This is not safe. Take:
/products/a
The regex group matches a.
It will be rewritten to:
/products/category/a
which the regex matches again (this time, the group matches category/a). Guess what will happen.
You want /products/ from the beginning of input if it is not followed by category/, which means you want a negative lookahead. Also, the QSA flag is of no use, you don't have a query string to rewrite (QSA stands for Query String Append):
RewriteRule ^/products/(?!category/)(.+) /products/category/$1 [L]
Another way to use it (and which I personally prefer) is to use a RewriteCond prior to the rule:
RewriteCond %{REQUEST_URI} ^/products/(?!category/)
RewriteRule ^/products/(.*) /products/category/$1 [L]
This Apache RewriteRule should do the job for you*:
RewriteCond %{REQUEST_URI} ^/products/(?!category/)
RewriteRule ^/products/(.*) /products/category/$1 [L]
With this in place, you'll need to hard code your category links manually:
{categories backspace="2"}
{category_name},
{/categories}
Which would output the new Category URLs you desire:
http://example.com/products/toys
Otherwise, if using the recommended path variable when building your category links:
{categories backspace="2"}
{category_name},
{/categories}
Would create links with the Category URL Indicator in the URI:
http://example.com/products/C1
http://example.com/products/category/toys
Which — while perfectly valid — would create canonicalization issues on your site since the different URLs would appear as duplicate content to search engines.
*Credit to fge for brilliant mod_write rule.
So, I have the following RegEx..
RewriteRule ^([-a-z0-9]*[A-Z\.]+.*)$ file.php?string=$1 [QSA]
The URL I want file.php to trigger for must either have capital letters or a period in it, then send the URL to the PHP script.
However, the problem I have is that this script is triggering on any URL, because of the not-truly-escaped Period.
I've tried escaping the period with a backslash, or two backslashes, or three... but none stop the generic interpretation.
What am I doing wrong?
Edit: As an example,
RewriteRule ^([-a-z0-9]*[A-Z\\.]+[-a-z0-9\/]*)$ file.php?string=$1 [QSA]
Doesn't work, but
RewriteRule ^([-a-z0-9]*\\.+[-a-z0-9\/]*)$ file.php?string=$1 [QSA]
does escape it.
Edit 2: Examples of URLs I want to redirect:
/some-page-goes-here.html
/heres-Robs/Old/Page/
And ones I don't:
/testing/one/two/
/an/actual-file.gif
EDIT 3: Old regex was:
RewriteRule ^([-a-z0-9]*[A-Z\.]+[-a-z0-9\/]*)$ file.php?string=$1 [QSA]
But while writing the post, I updated the question's regex to what you see above.
Try:
RewriteCond %{REQUEST_URI} [A-Z] [OR]
RewriteCond %{REQUEST_URI} \.html$
RewriteRule (.*) file.php?string=$1 [QSA]
When using mod_rewrite and you have several URLs to match, it is always better to use RewriteCond to filter and then apply your RewriteRule.
I don't think your problem can be what you think it is: periods in a character class are supposed to mean literal periods, not "any character". If this really is the problem, somehow, then you could change [A-Z\.]+ to ([A-Z]|\.)+; but I doubt it. Some things to try:
what happens if you comment out this line? does that successfully disable this redirect? if not, then obviously the problem isn't with this line. :-)
what happens if you make this a real HTTP redirect, by changing QSA to QSA,R? Does the destination URL look like what you expect? Maybe there are some unexpected periods or uppercase letters? (Warning: this will very likely trigger an infinite redirect loop if you try it in a browser; it'll probably be easier to try submitting the request via port-80 Telnet and seeing the actual HTTP response.)
Also, your rule doesn't quite match how you describe it. For example, your rule wouldn't match a URL like a.b.c, because you only uppercase letters and/or dots to occur in a single "clump"; if they're separated by lowercase letters, no match will occur. Is that just because you didn't want to overcomplicate the description?
I'm almost there with a mod_rewrite rule, but I've caved in :)
I need to rewrite
country/[countryname].php
to
country/[countryname]/
however, [countryname] may have an underscore like this: 'south_africa.php' and if it does I want to replace it with a hypen: 'south-africa/'
I also want to match if the country has numbers following it: 'france03.php' to 'france/'
Heres my rule, its almost there but its still adding a hyphen even if there is no second part after the underscore.
RewriteRule ^country/(.*)_(.*?)[0-9]*\.php$ country/$1-$2 [R=301,L]
so currently 'country/south_.php' becomes 'country/south-/'
Can someone please help me find the missing piece of the puzzle? Thanks.
Try this:
RewriteRule ^country/([^_]*)_([^_]*?)\d*\.php$ country/$1-$2 [R=301,L]
This rule will match urls with a single underscore - you'll need a different rule for more underscores or none.
If you want to make sure $2 contains only letter and isn't empty, change ([^_]*?) it to ([a-zA-Z]+).
Alternatively you could do it over several passes:
# If request is for something in "country/"
RewriteCond %{REQUEST_URI} ^country/.+\.php$
# Replace underscore and digits with (single) hyphen
RewriteRule [_0-9]+ \-
# Remove extension (and possible trailing hyphen)
RewriteRule ^(.*)-?\.php$ $1
# Final rewrite
RewriteRule ^country/(.*)$ country/$1 [R=301,L]
Untested ... and not necessarily "pretty" :)