rewritecond, rewriterule and ignoring extra querystrings - .htaccess

I have an old url:
www.example.com/content.aspx?ID=227&ParentID=33&MicrositeID=0&Page=1
that I wish to rewrite to:
www.example.com/product/item
The only important bit is ID=227, everything after that can be stripped and is not required for the redirect. I need to not pass any querystrings to the new address, this is basically a hard rewrite from one address to another.
I have my rewrite rule:
RewriteCond %{QUERY_STRING} ^ID=227(.*)$ [NC]
RewriteRule ^content\.aspx$ http://www.example.com/product/item [R=301,L]
But as I'm a total noob at mod_rewrite I'm struggling - can any htaccess gurus out there help me out?

RewriteCond %{QUERY_STRING} (^|&)ID=(\d+)(&|$) [NC]
RewriteRule ^content\.aspx$ /product/item/%2? [R=301,L]
A few comments...
There's no need to add .* to match the whole string in this case. As long as you can pinpoint what you want to match, you'll be fine. (^|&) matches either the start of the string or & whereas (&|$) matches either the end of the string or &. This allows id=xxx to be anywhere in the query string, which is good practice. \d matches one digit whereas + is a repetition operator for "one or more".
Furthermore, you don't actually need to include the domain name so long as the resulting page is on the same domain. Just start the resulting string with a / to make it relative to the root level.
%2 means that you're inserting a submatch from the RewriteCond statement rather than the RewriteRule. The latter would be $1, $2, as you might know.
The trailing ? tells the rewrite engine not to append the querystring to the URL. (Don't worry, the question mark won't show up in the redirect URL)

Related

.htaccess - Heal malformed url

I need a solution. For some reason in the past seems that I generate some "bad" links for bots only.
Resume: There is a fake "page" parameter when malformed url is present. When there are 2 "page" parameters then the first one is fake, must be removed.
X is random
Remove the parameter page only when "?/?page" is detected
Good: search?pagepage=496
Bad: search?/?page=X
Good: https://example.com/search?page=496
Good: https://example.com/search?page=496&orderBy=oldest
Bad: https://example.com/search?/?page=X&page=496&orderBy=oldest
RewriteCond %{QUERY_STRING} ^(.*)&?^XXX[^&]+&?(.*)$ [NC]
RewriteRule...
Thank you guys!
UPDATE
At final, I found a solution by myself:
RewriteCond %{QUERY_STRING} ^(.*)&?^/\?page=[^&]+&?(.*)$ [NC]
RewriteRule ^/?(.*)$ /search$1?%1%2 [R=301,L]
RewriteCond %{QUERY_STRING} ^/\?page=.+&(page=.*)
RewriteRule ^(search)$ $1?%1 [R=301]
This will do the rewrite for all your URLs that have the extra page parameter you want to keep.
To make the last part optional, we would have to wrap &(page=.*) into another set of braces, and add a ? as quantifier - (&(page=.*))?.
Then the back reference would need to be changed from %1 to %2 (because we only need that inner part, we don't want the &) - but then for your URL without any real page parameter to keep, there would be no match in this place, and therefor the %2 would not be substituted with anything, but added to the URL literally.
So better to leave the above as-is, and simply add
RewriteCond %{QUERY_STRING} ^/\?page=.+
RewriteRule ^(search)$ $1 [QSD,R=301]
below those two existing lines. The pattern does not need to be any more specific (because the URLs that have a genuine page parameter at the end, have already been handled by those previous two lines.) And the QSD makes it simply drop the existing query string, so that https://example.com/search?/?page=20 results in https://example.com/search (which I assume is what you wanted here, because there is no actual page parameter to keep, correct?)

Htaccess - Redirect if URL does not contain at least three numbers

I'm struggling to get this htaccess redirect to work. I want to redirect any URL that does not contain at least three numbers in a row. I started with the following and it worked perfectly for redirecting any URL that DID have three numbers in a row:
RewriteCond %{REQUEST_URI} [0-9]{3,20} [NC]
RewriteRule (.*) "https\:\/\/info\.mywebsite\.com\/" [R=301,L]
However, I tried to modify that with the exclamation mark to make the condition NOT match three numbers in a row:
RewriteCond %{REQUEST_URI} !([0-9]{3,20}) [NC]
RewriteRule (.*) "https\:\/\/info\.mywebsite\.com\/" [R=301,L]
But that doesn't seem to work as expected. Am I missing something with turning this expression into a not match?
Having previously experimented with the opposite 301 (permanent) redirect then the results are most probably cached (by the browser) from the earlier redirect. It is a good idea to test with 302 (temporary) redirects to avoid caching issues.
Note also that the REQUEST_URI server variable contains the URL-path only, so if the digits are contained in the query string part of the URL-path then your condition will fail.
The quantifier {3,20} matches from 3 to 20 characters, if you want "at least three" then use the quantifier {3,} (no upper bound).
You don't need the capturing subpatterns, ie. surrounding parentheses (...) on the regex since you are not using backreferences anywhere. Incidentally, you can't capture subpattern on a negated regex.
You don't need the additional condition (RewriteCond directive) - this can all be done with the RewriteRule directive only.
The NC flag is not required here - you are checking digits only.
For example:
RewriteRule !\d{3,} https://info.mywebsite.com/" [R=302,L]
As noted in comments, the RewriteRule substitution string is a regular string, not a regex, so does not require any special backslash escaping (although colons and slashes don't need escaping anyway in Apache regex).

URL rewrite more precise match, not URLs that just start with the same string

Let's say I have phpbb3 forums software and I want to prettify some URLs. I put this in my htaccess:
RewriteRule ^cake viewforum.php?f=5&%{QUERY_STRING} [L]
which works for domain.tld/cake and domain.tld/cake/ but it also catches domain.tld/cake-recipes and domain.tld/cake-recipes/ for instance, and so rewrites them.
How can I write this so that it only matches that exact URL, not URLs that begin with that string?
You need to add $ in order to delimit your rule pattern.
RewriteRule ^cake/?$ viewforum.php?f=5 [L,QSA]
The above rule will now only match domain.tld/cake or domain.tld/cake/.
Also, you can avoid using %{QUERY_STRING} by adding QSA flag (which does the same, but in a more elegant way)

Is possible to rewrite /mystring_value/ to ?parameter=value?

Is possible to rewrite this URL:
http://wwww.mywebsite.com/number_one/
to this URL:
http://www.mywebsite.com/?n=one
in .htaccess?
I'm going to guess that you want to do this using mod_rewrite. In that case, what you need is a RewriteCond to match the query string:
RewriteCond %{QUERY_STRING} ^n=([^&]+)
RewriteRule ^$ number_%1?
(The ? at the end of the RewriteRule tells mod_rewrite to discard the old query string.)
Also note that, as written, this is an internal rewrite. If you want the change to be visible to the user, append the flag [R] (or [R=301] if you want a permanent redirect) to the RewriteRule.
Edit: If you want to go the other way, from site.com/number_one to site.com/?n=one as your question now reads, it's even easier:
RewriteRule ^number_([^/]+) ?n=$1
(As written, this rewrite rule will throw away anything after the first slash following the number, as well as any existing query string parameters. You can keep the original query string by adding the [QSA] flag to the rule if you want.)

mod_rewrite - check for string

I want to check if a URL contains the sting "-EN.htm", if so apply the rewrite.
That should be done with ^-EN.htm as follows, but the rule is not working:
RewriteCond %{REQUEST_URI} ^/(.*?)/([-_0-9a-zA-Z./=]*)^-EN.htm
RewriteRule ^(.*)$ /indexEN.php?folder=%1&follow=%2 [L]
What am I doing wrong?
Thank you for every help,
Scott
Your regular expression doesn't look right. You can also lose the condition and just move the pattern to the rewrite rule instead. Something along the lines of
RewriteRule ^/?(.*?)/([-_0-9a-zA-Z./=]*)^-EN.htm /indexEN.php?folder=$1&follow=$2 [L]
You need to make the leading slash optional (in htaccess this is stripped off) and instead of using % backreferences, use the $ ones.
Now on to your pattern, it's not valid. The ^ matches the beginning of the string (the URI), so if you have two of them and you're not trying to literally match the ^ character (which you'd need to escape), then the expression will never match anything. Without any examples of URLs that you're having to deal with, I assume you probably just want to ditch the second ^:
RewriteRule ^/?(.*?)/([-_0-9a-zA-Z./=]*)-EN.htm /indexEN.php?folder=$1&follow=$2 [L]

Resources