Redirecting URL with paramter to top-level domain - wordpress

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.

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]

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).

htaccess: If the requested URL doesn't contain a specific string, redirect user to different domain while maintaining the slug

I have looked through quite a few different posts on here without any luck.
I have two sites (for example): exampledomain.com and mb.exampledomain.com
If a user accesses mb.exampledomain.com and the URL doesn't contain the string "retreat", then I want to redirect them to exampledomain.com while maintaining the slug.
So:
mb.exampledomain.com/retreat (or) mb.exampledomain.com/retreat_sunday should be accessible to the user as normal
mb.exampledomain.com/ (or) mb.exampledomain.com/about-us should redirect to exampledomain.com/ (or) exampledomain.com/about-us respectively.
I need to achieve this by using rules in a .htaccess file at the root of the directory.
Additionally, the htaccess rule shouldn't impact the accessibility of asset files on the mb.exampledomain.com/retreat page(s).
Thanks for any help you can provide!
Sounds pretty straight forward:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/retreat
RewriteRule ^ https://exampledomain.com%{REQUEST_URI} [QSA,R=301,END]
That catches all requests to URLs not starting with the literal string "retreat". Which is what you examples demonstrate. If you only want to check for the string itself, regardless of where in the path it occurs, then that should do what you ask:
RewriteEngine on
RewriteCond %{REQUEST_URI} !retreat
RewriteRule ^ https://exampledomain.com%{REQUEST_URI} [QSA,R=301,END]
It is a good idea to start out with a 302 temporary redirect and to only change it into a 301 permanent redirect once you are certain everything works as expected.

I cant seem to find how to redirect a trailing url

I cant seem to find how to redirect a trailing url from:
www.domain.com/index.php?option=com_k2&view=itemlist&task=user&id=*
To:
www.domain.com/
Any suggestions?
You can use a RewriteRule in apache configuration. Enable mod_rewrite and .htaccess through httpd.conf. Then, in .htaccess file in root directory place the following
RewriteEngin On
RewriteBase /
RewriteCond %{QUERY_STRING} ^option=com_k2&view=itemlist&task=user&id=.*$
RewriteRule ^index\.php.*$ '' [R,L,QSD]
You have to use RewriteCond to parse the query string, then the RewriteRule uses the flag R to redirect, L to stop processing additional rules, and QSD avoids appending the query string onto the URI. Since you are in web root, you can probably get away without using RewriteBase, but I used it for testing this code because I tested it with .htaccess in a subdirectory. So for someone who wants to do something similar in a subdirectory, you would change the RewriteBase to /sub1/sub2/ to rewrite the url
www.domain.com/sub1/sub2/index.php?option=com_k2&view=itemlist&task=user&id=*
to
www.domain.com/sub1/sub2/
If you do not want the browser to report the change, then use the passthrough flag PT instead of redirect R. There are other helpful flags for case-insensitve matching and more; you can view those in apache docs.

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