How to redirect Query Strings with ISAPI Rewrite? - query-string

I'm using the following lines in my httpd.ini file to redirect users who access example.com to www.example.com:
RewriteCond Host: (?:www\.)?example.com
RewriteRule (.*) http\://www.example.com [RP,L]
I'd like to know how redirect Query Strings whether user access my site without www, for example:
my user access:
example.com?a=1&b=2
example.com/a/b
i'd like to redirect to:
www.example.com?a=1&b=2
www.example.com/a/b
Someone can help me, please?
Thanks a lot.

This looks like you're using isapi_rewrite v2, so I'll answer for that version. v3 syntax is slightly different.
In the first line, I think it needs a ! for a negative lookahead for the www. As shown, it's matching www instead of not-www.
The answer involves capturing the pieces of the url, then using them in the rewrite with the submatch $1, $2, etc.
RewriteCond Host: (?!www\.)example.com
RewriteRule (.*) http\://www.example.com$1 [I,RP]
You can make it more generic for any domain, just to copy it easily to other websites, by capturing instead of example.com. It becomes the first capture $1, while the rest of the url is now $2.
RewriteCond Host: (?!www\.)(.*)
RewriteRule (.*) http\://www.$1$2 [I,RP]
The rule above will always redirect to http, even if the page was https. If you want to keep http or https, as-is, e.g., https://example.com/a?b=1 to https://www.example.com/a?b=1, then look for https flag, and substitute the "s". This is tricky to describe in words: this looks for the HTTPS server variable value 'on', and keeps it if it's 'on' (this is now the 2nd capture), and doesn't keep it if it's anything else. Then, in the rule, the ?2 is testing if there is a second capture. If so, it adds an 's', otherwise (the colon), it adds nothing (nothing after the colon). In this set, the rest of the url is now the third substring.
RewriteCond Host: (?!www\.)(.*)
RewriteCond %HTTPS (on)|.*
RewriteRule (.*) http(?2s:)\://www.$1$3 [I,RP]
Finally (almost done!), this doesn't leave subdomains alone. Because of the (.*) instead of 'example.com', it will rewrite abc.example.com/whatever... to www.abc.example.com/whatever.... So if you have subdomains to leave alone, e.g., staging or localhost for developers, or say 'shop' for a hosted shopping domain, you can 'or' these with the 'www' (note localhost doesn't have a trailing dot, to handle just //localhost).
RewriteCond Host: (?!www\.|staging\.|shop\.|localhost)(.*)
RewriteCond %HTTPS (on)|.*
RewriteRule (.*) http(?2s:)\://www.$1$3 [I,RP]

Related

block hacked indexed pages of my Wordpress

Last month my WordPress site was hacked because of my theme, so many pages (300k ..) were indexed by Google.
The actual PHP files were removed and a WAF installed, but, here is my problem.
The indexed links are like this : https://example.com/?bkzlriry235916cdefgh, always the same pattern (random chars and numbers).
To get them removed from Google, I think a rewrite rule in Apache vHost or .htaccess can do the job to get a 404 or 410 HTTP Code.
Problem is that I can't match the question mark ? using regex, even if I escape it. So the rule is wrong and blocks all my site.
I did something like that and many other tests :
RewriteRule ^/\?(.*)$ https://%{HTTP_HOST}/ [NC]
Do you have an advice for me?
RewriteRule ^/\?(.*)$ https://%{HTTP_HOST}/ [NC]
There are several things wrong here:
The RewriteRule directive matches the URL-path only, not the query string (everything after the ?). You need a separate condition (RewriteCond directive) and match against the QUERY_STRING server variable.
The URL-path that the RewriteRule pattern matches against does not start with a slash.
This rule (if it did match) would trigger a 302 (temporary) redirect to the homepage and preserve the query string, resulting a redirect loop. As you stated, you need to issue a "410 Gone" to get these pages removed from Google.
Try the following instead at the top of the root .htaccess file. Importantly, this must go before the WordPress code block.
RewriteCond %{QUERY_STRING} ^\w+$
RewriteRule ^$ - [G]
This blocks (with a 410 Gone) any request to the homepage only (as per your example) that includes a query string consisting only of letters and numbers (ie. no actual URL parameter name=value pair).
If you are not expecting any query string on any URL then you can make it more generic:
RewriteCond %{QUERY_STRING} .
RewriteRule ^ - [G]

Redirecting a WP multisite URL to a subsite URL

I have a WordPress multisite installation with a base URL of https://example.com. Subsites have an initial URL of https://example.com/forinstance, which can be changed in WordPress to an alias of https://forinstance.com.
But I want to redirect all URLs from https://example.com/caseinpoint ALSO to https://forinstance.com. There's not a way to do that in WordPress, so I'm trying to do it in my .htaccess file. I can't get it to work though.
I've tried variants of:
RewriteCond %{HTTPS_HOST} ^example.com/caseinpoint$
RewriteRule (.*)$ https://forinstance.com [R=301,L]
But it always just goes to a 404 on example.com.
However, this DOES work for other subsites:
RewriteCond %{HTTPS_HOST} ^ejemplo.com$
RewriteRule (.*)$ https://perinstanza.com [R=301,L]
So it seems to be something to do with the multisite. How can I redirect example.com/forinstance, please?!
Neither of the rules you posted will actually do anything since HTTPS_HOST is not a valid server variable. It should be HTTP_HOST, which represents the Host HTTP request header (hence the HTTP_ prefix). ie. the hostname (or domain) being requested.
The Host header does not include the URL-path, which you are trying to match in the first rule.
Presumably you want to redirect the remaining URL-path to the same on the new domain. eg. https://example.com/caseinpoint/<url> should redirect to https://forinstance.com/<url>? You aren't literally just redirecting https://example.com/caseinpoint (missing trailing slash) to https://forinstance.com/ (there is always a slash after the hostname) as you've stated?
In which case you can do something like the following at the top of the root .htaccess file, before any existing WordPress directives.
RewriteCond %{HTTP_HOST} ^(www\.)example\.com [NC]
RewriteRule ^caseinpoint(?:$|/(.*)) https://forinstance/$1 [R=302,L]
This also allows for an optional www subdomain.
The $1 backreference contains the value of the first capturing subpattern in the RewriteRule pattern, ie. the URL-path after "caseinpoint/" (not including the slash).
Test first with a 302 (temporary) redirect to avoid any potential caching issues. Only change to a 301 (permanent) redirect - if that is the intention - once you have confirmed it works as intended. You will likely need to clear your browser cache before testing.

Wordpress/Apache rewrite/redirect rule and regex

I need to do some apache rewrite/redirect rules to external webservice in case of 404 error for specific file extensions: .jpg, .png, etc. Wordpress is used here.
So, if 404 occurs at:
https://test.com/folder/subfolder/year/month/filename.jpg
I want to redirect it to:
https://test1.com/folder/subfolder/year/month/filename.jpg (external webservice, not the same phisical server)
I've tried such a configuration in htaccess, didn't work as expected:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) test1.com/folder/subfolder//$year$\/$month$\/([^\s]+(\.(?i)(png | jpg | gif | svg))$)/
Do you have any ideas how to do it right way?
Any suggestions appreciated.
With your shown samples, attempts; please try following htaccess rules file. These rules are written as per shown domain names which are samples/tests, so you need to change values as per your actual values when you use them in your system. We also need to make sure that both (test.com and test1.com) are sharing same directory structure in your actual apache server.
Also make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
RewriteCond %{HTTP_HOST} ^(?:www\.)?test\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/?$ https://test1.com/$1 [R=301,L]
To "redirect" URLs of the form /folder/subfolder/<year>/<month>/<file>.<png|jpg|gif|svg> where /folder/subfolder/ is static and the other elements are variable and which do not exist on the filesystem you would need to do something like the following before the WordPress code block. ie. before the # BEGIN WordPress section.
# Redirect certain non-existent image files to another server
RewriteRule ^folder/subfolder/\d{4}/\d\d/[\w-]\.(png|jpg|gif|svg)$ https://test1.com/$0 [R=302,L]
# BEGIN WordPress
:
The <year> is a 4-digit number and <month> is a 2-digit number. The filename can consist of the characters 0-9, a-z, A-Z, _ (underscore) and - (hyphen).
This should presumably be a 302 (temporary) redirect, not a 301 (permanent), otherwise if the resource should become available at the source domain then it won't be accessible to those users who have visited the URL before (they will be redirected from cache).
To avoid the external redirect it may be preferable to "proxy" the request to the other domain. (This is invisible to the end user.) Although this potentially involves additional configuration server-side, as you would need to configure the source server as a "reverse proxy". You can then replace the R=302 flag in the above rule with P (proxy).

Redirecting URL with paramter to top-level domain

I have been trying to search but no luck yet. Found different options about redirecting but nothing like what I'm looking for.
So currently the website URLs contain lang parameter like ?lang=en, ?lang=ru, ?lang=fi. Parameters are on the very end of the URL.
Idea is to move languages to top level domain. So basically I'm looking for a way to redirect all URLs that contain parameter ?lang=ru to top-level .ru domain. Same with other languages.
Can I do it via .htaccess or it shouldn't be done at all? Moving site to different domains should need redirection to pass the link juice and authority to new domains.
Hopefully, someone can lead me to the correct way of doing it.
Much appreciated!
If there are no other URL parameters that need to be preserved then you can do it like the following using mod_rewrite near the top of your .htaccess file:
RewriteEngine On
# Redirect "/foo?lang=xx" to "example.xx/foo"
RewriteCond %{QUERY_STRING} ^lang=([a-z]{2})$
RewriteRule ^ https://example.%1%{REQUEST_URI} [QSD,R=302,L]
The above matches any language code that consists of 2 lowercase letters. To match specific language codes then use alternation in the regex and change the RewriteCond directive to read:
RewriteCond %{QUERY_STRING} ^lang=(en|ru|fi|abc|etc)$
The QSD flag discards the original lang=xx query string from the redirect response (Apache 2.4). Otherwise this will be copied onto the target URL by default.
The %1 backreference contains the value of the lang URL parameter captured in the preceding condition. The REQUEST_URI server variable contains the full URL-path (no query string) from the request.
This does assume that the language specific TLD domains are hosted elsewhere. In other words, we do not need to check whether we are already at the required TLD domain.
Test with a 302 (temporary) redirect and only change to a 301 (permanent) redirect - if that is the intention - once you have confirmed that this works OK.
UPDATE: Any specific redirects, eg. lang=en to .com will need to appear first. For example:
# Redirect languages to .com
RewriteCond %{QUERY_STRING} ^lang=(en)$
RewriteRule ^ https://example.com%{REQUEST_URI} [QSD,R=302,L]
# All other language codes...
# Redirect "/foo?lang=xx" to "example.xx/foo"
RewriteCond %{QUERY_STRING} ^lang=([a-z]{2})$
RewriteRule ^ https://example.%1%{REQUEST_URI} [QSD,R=302,L]
Use alternation (as mentioned above) if there are more language codes. eg. (en|gb).
You should be able to do this via .hataccess. You can use the code below in your .htaccess
RewriteEngine on
RewriteCond %{REQUEST_URI} lang=en
RewriteRule ^ https//wwww.yourwebsite.ext [L,R]
I think it should work fine if you write same for all the others. DO give it a try and let me know.

mod rewrite exploding %{HTTP_HOST}

I have a situation I've not come across before that calls for some interesting mod_rewrite rules and I cant find any examples of someone trying to achieve the same thing in a similar configuration.
Currently I have two domain names which are configured to share the same document root, in said document root is a dynamic php application which, based on the incoming hostname, displays content specific to the that domain.
The domains for example purposes are:
www.example1.com
and
www.example2.co.uk
(one being a TLD the other not)
In addition to this application there are two wordpress installations one for each of the two domain names. As we are not using wordpress MU here I need some fancy rewrites to firstly hide the wordrpess folder, and secondly present the request to the correct folders based on the HTTP_HOST.
Currently I have the following:
RewriteRule ^wp-content(.*) wordpress/example1$1 [L]
RewriteRule ^wp-admin(.*) wordpress/example1/wp-admin$1 [L]
RewriteRule ^wp-login.php$ wordpress/example1/wp-login.php [L,R=301]
And similar rules for content specific pages.
This works well for the single wordpress installation, but obviously not for the second, what I was hoping to do here was something like the following:
RewriteRule ^wp-admin(.*) wordpress/${HTTP_HOST}/wp-admin$1 [L]
However I need to remove the www. and .com from the ${HTTP_HOST} variable (or the www. and .co.uk )
Any suggestions on a way to achieve this or a better approach would be appreciated.
You can use RewriteCond to check for a pattern in HTTP_HOST and then capture part of that pattern.
For instance:
RewriteCond %{HTTP_HOST} ^(?:www\.)?([a-zA-Z0-9_-]+)\.(?:com|co\.uk)$
RewriteRule ^wp-admin(.*) wordpress/%1/wp-admin$1 [L]
The RewriteCond directive above checks to see whether HTTP_HOST fits a domain pattern ending ".com" or ".co.uk" and optionally beginning with "www.". If it does, it captures the interesting part of the domain name.
Then the RewriteRule (which only fires if the RewriteCond does match) is able to refer to the captured part of the RewriteCond pattern by using the %1 back-reference.
The pattern I've used in the RewriteCond above might not suit your needs perfectly, but once you know you can use a back-reference to a pattern captured by RewriteCond, it should be easy for you to use this to get the effect you need.

Resources