Is my rewrite code correct? - apache

I am trying to write rewrite code for my customer's site. I have no way of verifying if it's correct because I don't have access to the server yet. I know that sounds strange but it's what I have to accept and work around.
I plan to put this in the root htaccess file on the server. Bottom line is this URL does not work:
http://www.regions.noaa.gov/gulf-mexico/index.php/highlights/restore-act-passed/
So when the above fires, I want it to permanently redirect to:
http://www.regions.noaa.gov/gulf-mexico/highlights/restore-act-passed/
Here is what I have
RewriteEngine on
RewriteCond %{HTTP_HOST} ^regions\.noaa\.gov$ [OR]
RewriteCond %{HTTP_HOST} ^www\.regions\.noaa\.gov$
RewriteRule ^gulf\-mexico\/index\.php\/highlights\/restore\-act\-passed\/$ "http\:\/\/www\.regions\.noaa\.gov\/gulf\-mexico\/highlights\/restore\-act\-passed\/" [R=301,L]
I'd appreciate any feedback on this. Thanks.
UPDATE - thanks to all who replied. Here's what I don't understand. I found this code on my web hosting company's code generator. It seems to work:
RewriteCond %{HTTP_HOST} ^designerandpublisher.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.designerandpublisher.com$
RewriteRule ^services.html$ "http\://www.regions.noaa.gov/gulf-mexico/highlights/restore-act-passed/" [R=301,L]

I usually do like this and works fine.
IF user enter in the URL with highlights/restore-act-passed/ THEN will display contents from index.php/highlights/restore-act-passed/ in the browser.
# [NC] Means “No Case”, so it doesn’t matter whether the domain name was written in upper case, lower case or a mixture of the two.
RewriteEngine on
RewriteRule ^highlights/restore-act-passed/?$ index.php/highlights/restore-act-passed/ [NC]
IF the user enter in the URL with index.php/highlights/restore-act-passed/ THEN will display contents from _http://%{HTTP_HOST}/gulf-mexico/highlights/restore-act-passed/
RewriteRule ^index.php/highlights/restore-act-passed/?$ _http://%{HTTP_HOST}/gulf-mexico/highlights/restore-act-passed/ [NC]

You don't need to specify the HTTP_HOST, unless you will have multiple domains coming through here (add-ons, subdomains, parked domains, etc.). If you do want to specify it, it can be simplified to one line:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?regions\.noaa\.gov$
RewriteRule ^gulf\-mexico\/index\.php\/highlights\/restore\-act\-passed\/$ "http\:\/\/www\.regions\.noaa\.gov\/gulf\-mexico\/highlights\/restore\-act\-passed\/" [R=301,L]
Actually, a subdomain doesn't even need the www, but it doesn't hurt. Then, in the rewrite rule, you only need to escape specific metacharacters in the pattern, and none in the replacement string:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?regions\.noaa\.gov$
RewriteRule ^gulf-mexico/index\.php/highlights/restore-act-passed(/)?$ http://www.regions.noaa.gov/gulf-mexico/highlights/restore-act-passed/ [R=301,L]
I also made the last (trailing) / optional. Since you're going to the same domain, there is no need to repeat it:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?regions\.noaa\.gov$
RewriteRule ^gulf-mexico/index\.php/highlights/restore-act-passed(/)?$ /gulf-mexico/highlights/restore-act-passed/ [R=301,L]
The 301 code says to alert search engines that this URL or URI has permanently moved (it will show up changed in a browser address bar, too, so human visitors can choose to rebookmark it).
As this appears to be an SEO URI, presumably it will be translated into a dynamic format (/gulf-mexico/index.php?area=highlights&item=restore-act-passed). That means that the above rewrite has to be done before any SEO-to-dynamic translation. An alternative would be to directly translate it to dynamic format right here, but since you're giving a 301, presumably you want the SEO format to show in a browser or search engine result.

Related

I changed domains and post slug structure at the same time for my WP site. Can I use 1 redirect to do so with htaccess?

I am planning a domain change from example1.com to example2.com. To add a twist to it, I also want to change my permalinks at the same time. My current permalinks for posts have the date and I want to remove it.
I'm a bit hesitant to test and lose SEO so I was hoping someone could confirm this would work before.
Here is what I was thinking:
after changing domains I use this code in my htaccess
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^\d{4}/\d{2}/(.*) https://example2.com/$1 [R=301,L]
then I found this rule to change dates:
RewriteRule ^[0-9]{4}/[0-9]{2}/(.*)$ https://example2.com/$1
I saw this one as well:
RewriteRule ^/(\d*)/(\d*)/([A-Za-z0-9-]*)$ https://example2.com/$4
I'm not sure what these rules specifically mean but I THINK I should be able to combine them like this?
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^[0-9]{4}/[0-9]{2}/(.*)$ http://example2.com/$1 [L,R=301,NC]
It doesn't seem quite right.
Or would simply changing the permalink structure in WordPress affect the change so that
https://www.example1.com/2019/01/how-to-write-about-cars/
redirects to
https://www.example2.com/how-to-write-about-cars/
UPDATE
Using MrWhite's answer below. I added this code:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^/(\d*)/(\d*)/([A-Za-z0-9-]*)$ https://example2.com/$4
This is working now in the case of
https://www.example1.com/2019/01/how-to-write-about-cars/
which redirects to
https://www.example2.com/how-to-write-about-cars/
However
https://www.example2.com/2019/01/how-to-write-about-cars/
does NOT redirect to
https://www.example2.com/how-to-write-about-cars/
It just returns a 404. This likely isn’t an issue as nothing should be bookmarked but just in case, is there a way to fix that?
Or would simply changing the permalink structure in WordPress affect the change
I don't believe this would implement the redirect from the old to new URL structure, if that is what you are thinking. (At least not by default.)
RewriteCond %{HTTP_HOST} ^example1.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www.example1.com [NC]
RewriteRule ^[0-9]{4}/[0-9]{2}/(.*)$ http://example2.com/$1 [L,R=301,NC]
This looks OK. Although if the new URLs at example2.com don't contain the date (ie. /YYYY/MM/ prefix) then there wouldn't seem to be any need to check the requested hostname.
This rule must also go at the top of the .htaccess file, before any of the existing WordPress directives (ie. before the # BEGIN WordPress comment marker).
You should first test with a 302 (temporary) redirect to avoid potential caching issues.
Final Solution
This can, however, be tidied a bit. The following one-liner should be sufficient:
RewriteRule ^\d{4}/\d{2}/(.*) https://example2.com/$1 [R=301,L]
You do not need any of the RewriteCond directives. (Just the RewriteEngine On directive, if it doesn't already appear elsewhere in the .htaccess file.)
Note the https on the target URL. \d (shorthand character class) is the same as [0-9]. The trailing $ on the regex is not required since regex is greedy by default. The NC flag is not required either, since there is nothing case specific in this regex.
Aside: (Don't use this!)
I saw this one as well:
RewriteRule ^/(\d*)/(\d*)/([A-Za-z0-9-]*)$ https://example2.com/$4
This rule, however, is very wrong! Due to the slash prefix on the RewriteRule pattern this will never match in .htaccess and the rule will do nothing. But there are only 3 capturing groups in the regex, so the $4 backreference would always be empty (everything would be redirected to the homepage, which would likely be treated as a soft-404 by search engines).

.htaccess RewriteRule from long url to show short url

Im trying to rewrite url from long to short but cant wrap my head around this.
My survey rewrite works wonderfully but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
but I would like to show url like www.example.com/thank_you
Im not even sure if this is possible.
Im new with .htaccess and i have tried almost everthing
.htaccess
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
Any help or directions will be highly appreciated.
Solution:
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_id=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/thank_you [R,L,QSD]
RewriteRule ^([0-9a-zA-Z]+)/thank_you$ survey_thank_you.php?survey_id=$1 [L,NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA]
but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
You need to "correct" the URL that PHP is redirecting you to after the survey. If the desired URL is /thank_you (or /Thank_you?) then PHP should be redirecting to that URL.
You then use mod_rewrite in .htaccess to internally rewrite /thank_you back into the URL that your application understands. ie. /survey_thank_you.php?survey_id=1. However, therein lies another problem, where does the 1 (survey_id) come from in the query string? Presumably you don't want to hardcode this? So this would need to passed in the requested URL. eg. /1/thank_you or perhaps /thank_you/1?
However, is this really necessary? The resulting "thank you" page is not a page that should be indexed or a page that is normally navigated to by the user, so implementing a user-friendly URL here doesn't seem to be a worthwhile exercise?
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
You are using a survey_name URL parameter (referencing an alphanumeric value) in your directives, but a survey_id ("numeric"?) URL parameter in your earlier example? So, which is it? Or are these rules unrelated?
You state that the second rule "works like charm", but how? What URL are you requesting? That would seem to rewrite /Thank_you to survey_form.php?survey_name=Thank_you - but that does not look correct?
As mentioned in comments, the RewriteRule pattern matches against the URL-path only. To match against the query string you need an additional condition that matches against the QUERY_STRING server variable. This would also need to be an external 3xx redirect, not an internal rewrite (in order to change the URL that the user sees). Therein lies another problem... if you don't change the URL that your PHP script is redirecting to then users will experience two redirects after submitting the form.
You also need to be careful to avoid a redirect loop, since you are internally rewriting the request in the opposite direction. You need to prevent the redirect being triggered after the request is rewritten. ie. Only redirect direct requests from the user should be redirected.
So, to answer your specific question, it should be rewritten something like this instead:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=[0-9a-zA-Z]+/?$
RewriteRule ^survey_thank_you\.php$ /Thank_you [QSD,R,L]
The check against the REDIRECT_STATUS environment variable ensures that only direct requests are processed, not internally rewritten requests by the later rewrite. REDIRECT_STATUS is empty on the initial request and set to the string 200 (as in 200 OK status) after the first successful rewrite.
The QSD flag (Apache 2.4) is necessary to discard the original query string from the redirect response.
So the above would redirect /survey_thank_you.php?survey_name=<something> to /Thank_you.
But this is losing the "survey_name" (or survey_id?), so should perhaps be more like the following, in order to preserve the "survey_name":
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/Thank_you [QSD,R,L]
Where %1 is a backreference to the value of the survey_name URL parameter captured in the preceding CondPattern.
However, you would then need to modify your rewrite that turns this back into an understandable URL.
(But you should probably not be doing this in the first place without first changing the actual URLs in the application.)

What is the correct syntax for "if host is not foo, redirect to bar" in a .htaccess file?

This website has a ton of extra domains (note: these are not subdomains; one of them, for instance, is http://eduard.fi) that the owner (or the SEO people, rather) wants to redirect to the main domain. Instead of listing them one by one, this is what I tried:
RewriteCond %{HTTPS_HOST} !^masetti\.fi$
RewriteRule ^(.*)$ https://masetti.fi/$1 [R=301,L]
However this creates a redirect loop. Why is that? This does not produce a server error, so for that part the syntax is correct, but it does not do what I want.
You were close, but made a logical mistake. Take a look at this:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^masetti\.fi$
RewriteRule ^(.*)$ https://masetti.fi/$1 [R=301]
An alternative would be that:
RewriteEngine on
RewriteCond %{HTTP_HOST} !^masetti\.fi$
RewriteRule ^ https://masetti.fi%{REQUEST_URI} [R=301]
The RewriteCond has been slightly altered: It is the variable %{HTTP_HOST} you want to check, not %{HTTPS_HOST}which does not exist.
PS: it is a good idea to start out with a 302 redirection and only change that to a 301 once everything works as intended. That prevents issues with client side caching.

htaccess redirect to a specific url on same domain (without looping)

I really hope you can help me out (it is driving me crazy).
I've tried dozens of setups and nothing seems to work, Googled myself dizzy and tried numerous different setups, but it all seems to result in a loop or a server error.
This is what needs to happen:
I have a site with multiple domains attached to it. What I need is that when someone visits the website via the "domain.co.uk"-domain, a redirect to the correct language parameters (among others) takes place.
To be very specific: when visiting via "www.domain.co.uk" the visitor must be redirected to "www.domain.co.uk?lang=en&noredir=1&currency=3"
I've made sure that the www is present with this:
RewriteCond %{HTTP_HOST} !^www.domain.co.uk$ [NC]
RewriteRule ^(.*)$ http://www.domain.co.uk/$1 [L,R=301]
The trouble is (I think) the redirect within the same domain without causing a loop.
I've tried stuff like this, but with no result:
RewriteCond %{HTTP_HOST} ^www.domain.co.uk$
RewriteRule ^$ http://www.domain.co.uk/?lang=en&noredir=1&currency=3 [L,R=301]
Hope you can help,
Cheers!
This will cause a loop:
RewriteCond %{HTTP_HOST} ^www.domain.co.uk$
RewriteRule ^$ http://www.domain.co.uk/?lang=en&noredir=1&currency=3 [L,R=301]
Because you're only checking the host header. Every time the redirect fires it will arrive back at the server with a host header of www.domain.co.uk and redirect again. You need to also check the query string and only redirect if it doesn't already match what you sent:
RewriteCond %{HTTP_HOST} ^www.domain.co.uk$
RewrteCond %{QUERY_STRING} !lang=en&noredir=1&currency=3
RewriteRule ^$ http://www.domain.co.uk/?lang=en&noredir=1&currency=3 [L,R=301]

How to redirect direct hits

I'm sure this has been asked before, but I have no idea what it would be called.
I have done a quick Google and search here on SO.
Perhaps it would be better asked, how do I redirect http://site.com/shop to a specified URL like http://othersite.com/page without it affecting http://site.com/shop/?q=test or any other $_GET's.
RewriteRule ^shop http://othersite.com/page [R=301,L]
Works fine apart from it also affects links like http://site.com/shop/?q=test which I want to work.
Cheers.
You can use mod_rewrite to match against the query string (or to see if there is no query string):
RewriteEngine On
# blank query string
RewriteCond %{QUERY_STRING} ^$
# check host
RewriteCond %{HTTP_HOST} site\.com$ [NC]
RewriteRule ^shop/?$ http://othersite.com/page [R=301,L]