htaccess Rewrite rule from "example.com/de/foo" to "example.de/foo" - apache

RewriteRules can be such a pain for me, I cannot get this one to work.
I have to redirect urls like example.com/de/anypath to example.de/anypath.
[anypath] can be really any path, as I have to get it work for
example.com/de/articles/programming/hello-world (would be redirected to example.de/articles/programming/hello-world)
as well as for example.com/de/events/pic-nic (would be redirected to example.de/events/pic-nic).
This is what I wrote so far :
RewriteRule "^/de/(.*)$" "http://example.de/$1" [R=301,NC,L]
I also tried with RewriteCond with no more luck
RewriteCond %{HTTP_HOST} http://example.com/de
I am working with xampp, but tested on my web server with same
result.
I know this .htaccess file is working (get error if I enter a
typo)
I got some result when testing with something like :
RewriteRule "^(.*)$" "https://google.com" [R=301,NC,L]
Any help would be appreciated !

RewriteRule "^/de/(.*)$" "http://example.de/$1" [R=301,NC,L]
In .htaccess, the URL-path matched by the RewriteRule pattern does not start with a slash. ie. It should be "^de/(.*)$", not "^/de/(.*)$".
You don't need the double quotes and the NC flag is probably redundant, unless you also need to match dE, Ed or DE.
For example (near the top of the root .htaccess file):
RewriteRule ^de/(.*) http://example.de/$1 [R=301,L]
(HTTP, not HTTPS?!)
The trailing $ on the RewriteRule pattern was also redundant.
Test first with 302 (temp) redirect to avoid potential caching issues.
RewriteCond %{HTTP_HOST} http://example.com/de
The Host HTTP request header (ie. the value of the HTTP_HOST server variable) contains the hostname only. eg. example.com only in your example.
Any server variable that is prefixed with HTTP_ refers to the HTTP request header of the same name.
I got some result when testing with something like :
RewriteRule "^(.*)$" "https://google.com" [R=301,NC,L]
Careful with testing 301s since they are cached persistently by the browser. You will need to clear your browser cache before testing!

I added two conditions (the first is to apply according to local or live site, the second to leave the node paths unchanged) :
RewriteCond %{HTTP_HOST} local.example.com
RewriteCond %{REQUEST_URI} !^.*/de/node/.*$
And it is working as expected. Thanks again.

Related

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

htaccess: Can match one slash, but not double slashes

I am unable to write a rule that matches double slashes.
In my .htacess file:
#RULE 1:
RewriteCond %{REQUEST_URI} ^.*hi1.*$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
#RULE 2:
RewriteCond %{REQUEST_URI} ^.*hi2/.*$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
#RULE 3:
RewriteCond %{REQUEST_URI} ^.*hi3//.*$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
RESULTS:
https://www.example.com/hi1//
successfully redirects to google
https://www.example.com/hi2//
successfully redirects to google
https://www.example.com/hi3//
fails to redirect to google
Third url yields the following:
Sorry, this page doesn't exist.
Please check the URL or go back a page.
404 Error. Page Not Found.
EDIT # 1:
Interestingly:
#RULE 4:
RewriteCond %{REQUEST_URI} ^.*hi4/.*/.*$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
RESULTS:
https://www.example.com/hi4/abc/
successfully redirects to google
https://www.example.com/hi4//
fails to redirect to google
EDIT # 2:
My original post seems to have created confusion. I will try to be clearer: I need a rule that will match a url ending in double slash, and will not match a url that does not end in double slash. Currently, my .htaccess file contains only the following:
RewriteEngine on
RewriteRule yoyo https://www.cnn.com/ [R=301,L]
RewriteCond %{THE_REQUEST} //$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
Results:
https://www.example.com/about-us//
fails to redirect to google, and yields 404 error
(The first rule (yoyo) is only to ensure no caching.)
EDIT # 3:
I see that the confusion continues. So, my .htaccess file contains only:
RewriteEngine on
RewriteCond %{THE_REQUEST} //$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
Results:
https://www.example.com/about-us//
fails to redirect to google, and yields 404 error
This time, I think we can rule out caching, because I used the .htaccss on a website of mine that previously had no .htaccess file.
Simply, my efforts to match a url ending with double-slash are failing.
You need not to write 3 rules when you could catch similar kind of URIs with regex patterns so that we need not to write multiple patterns, this also takes cares of multiple occurrences of / coming in the end. Could you please try following, please make sure you clear your browser cache after placing these rules into your htaccess file.
RewriteEngine ON
RewriteCond %{REQUEST_URI} ^/hi[0-9]+/{2,}?$ [NC]
RewriteRule ^(.*)$ https://www.google.com/ [R=301,L]
EDIT:
OK now I get it. Only match paths ending with two slashes.
I updated the answer. The request URI inside THE_REQUEST is not on the end, but is followed by a space and more after that, so matching //\s should work for you
AmitVerma mentioned the correct answer in his comment, but it is being snowed in by other comments. For all the other people like me who did not know about the THE_REQUEST parameter (thank you Amit) a more complete answer here.
The problem with the original rule is the use of the REQUEST_URI parameter. The value of this parameter will probably already have been cleaned by the webserver or other modules. Double slashes would have been removed.
The THE_REQUEST parameter contains the original unmodified request. Therefore the following will work as requested:
RewriteCond %{THE_REQUEST} //\s.*$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
Regarding your updated question:
... I need a rule that will match a url ending in double slash
RewriteCond %{THE_REQUEST} //$
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
Aside: Your previous rules matched a URL containing a double slash anywhere in the URL-path (which would naturally catch a double slash at the end as well).
However, the above will not match a URL that ends with a double slash. In fact, it will never match anything because THE_REQUEST does not only contain the URL. THE_REQUEST server variable contains the first line of the HTTP request headers. For example, when you request https://example.com/about-us//, THE_REQUEST will contain a string of the form:
GET /about-us// HTTP/1.1
So, you can see from the above that a regex like //$ will never match. You will need to use a condition of the form:
RewriteCond %{THE_REQUEST} //\s
To match two slashes followed by a space. Which could only occur at the end of URL. (Although it could also occur at the end of the query string, but cross that bridge when we come to it.)
However, since the other suggestions (eg. ^.*hi3//.*$) don't appear to have worked, then this is not going to work either.
You need to clear your browser cache before testing and please test with 302 (temporary) redirects, otherwise, you can easily go round in circles chasing caching issues. You should also test this with the Browser "Inspector" open on the "Network" tab and check the "Disable cache" option. For example, in Chrome:
(UPDATE) Debugging...
This does not seem to be a question about regex, as the earlier answers/comments (and code snippets in the question itself) should already have produced the desired results. So "something else" would seem to be going on here.
To debug and see the value of THE_REQUEST, you can do something like the following (at the very top of your .htaccess file):
RewriteCond %{QUERY_STRING} !^the-request=
RewriteRule ^ /?the-request=%{THE_REQUEST} [R,L]
And then request /about-us//. You should then be redirected to a URL of the form:
/?the-request=GET%20/about-us//%20HTTP/1.1
(Where the %20 are naturally the URL encoded spaces.)
Please report back exactly what you are seeing.
Here's what finally worked to match double slashes (nothing else worked for me):
RewriteEngine on
RewriteCond %{THE_REQUEST} //
RewriteRule ^.*$ https://www.google.com/ [R=301,L]
(And, as I wrote, I was careful to prevent caching, so caching never was an issue.)
PLOT TWIST:
Even this solution, which is the only solution that works on one of my websites, does not work on the website I have been testing on for most of this discussion. In other words, there is not one single solution for matching double-slash on that server!

Force SSL redirect - Apache/IHS RewriteCond and RewriteRule

I'm trying to set up a rewrite rule which will force all requests coming in on port 80 to use HTTPS by force.
I'm only getting my head around mod_rewrite but this is what i currently have;
RewriteCond ${lowercase:%{REQUEST_URI}} /securePath$
RewriteRule ^(.*)$ https://www.mydomain.com/$1
In the RewriteCond securePath is the requested path (not including my domain).The full URI would be www.mydoamin.com/securePath
In the ReWriteRule $1 is supposed to be the output from ${lowercase:%{REQUEST_URI}} in the RewriteCond
However when i restart my IHS server and attempt to hit the URL it isint forcing access through HTTPS. Any suggestions on what is wrong with these two lines?
Thanks
RewriteRule ^securePath/(.*)$ https://www.mydomain.com/$1 [NC,R=301,L]
Probably it's just you example being broken, but you are explicitly lowercasing the incoming request path and try to match that to "/securePath" which includes a capital letter. -That is never going to match.

Redirecting all traffic based on Host name

An external server (I'll call it "sub.origin.edu") redirects all traffic to my webpage. I want to take all traffic from this host, and redirect it to a different site (which I'll call "http://foo.target.edu/board/").
My .htaccess file is:
RewriteEngine On
RewriteCond ${HTTP_HOST} sub\.origin\.edu [NC]
RewriteRule ^(.*)$ http://foo.target.edu/board/ [R=302]
This doesn't seem to be working. I've confirmed (using PHP) that the host is indeed sub.origin.edu, and the .htaccess file is in the right directory, but this rule just doesn't come into effect. Any suggestions? Thanks.
(If I remove the RewriteCond, the redirect happens, so I can confirm that everything but the rewrite condition is working.)
Use this:
RewriteEngine On
RewriteCond %{HTTP_HOST} sub\.origin\.edu [NC]
RewriteRule ^(.*)$ http://foo.target.edu/board$1 [R=302]
You used the wrong substition character ($ instead of %)
I found this question while trying to complete a re-derict for specific hostnames.
This link was of great help to understand how RewriteCond and RewriteRule work.
http://httpd.apache.org/docs/2.4/rewrite/intro.html
If sub.origin.edu is doing a 3xx redirect, then the browser will issue a new request to your server using your.server.edu as the host name. So this rule will never match that. If this is the case, there's no easy way to tell where the request was redirected from.
If they're using a CNAME, Femi has the correct answer.

How do I redirect a specific URL pattern when Drupal Clean URLs are on?

I have a Drupal 5.23 installation using clean URLs with Apache and the mod_rewrite module. I am using an .htaccess file for the clean URLs functionality with the following configuration:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
</IfModule>
I am going to be disabling the Localization/Internationalization plugins on the website, which is going to change every single page's URL on the website from http://www.example.com/en/url-to-a-page to http://www.example.com/url-to-a-page (the /en portion is being stripped out).
I would like to add a mod_rewrite rule to give an HTTP 301 Redirect response for any incoming URLs with the /en portion in the URL so they are directed to the correct page.
I've tried adding the following lines to my .htaccess file both above and below the existing rules, but in both cases visiting a page with /en results in an HTTP 404 Not Found response:
RewriteRule ^en/(.+)$ http://www.example.com/$1 [R=301]
If I comment out the existing rules, my rule works just fine. I've also tried to add a condition to the rule, but this doesn't appear to have an effect either:
RewriteCond %{REQUEST_URI} =/en/*
This came up for me when writing all of my custom redirects, and it turns out the solution was to add an "L" to the redirect line. Give the following at try:
RewriteRule ^en/(.+)$ http://www.example.com/$1 [L,R=301]
Note the "L" near the end of the line. That, according to the Apache RewriteRule docs, means "Stop the rewriting process here and don't apply any more rewrite rules".
In addition to what sillygwailo suggest, I'd recommend you to make sure that your RewriteCond (needed, I think) actually matches..
from the apache docs:
=CondPattern' (lexicographically equal)
Treats the CondPattern as a plain string and compares it lexicographically to TestString. True if TestString is lexicographically equal to CondPattern (the two strings are exactly equal, character for character). If CondPattern is "" (two quotation marks) this compares TestString to the empty string.
So, It could possibly match only an URL containing an actual '*'..? Not sure, but you could also try this:
RewriteCond %{REQUEST_URI} ^/en/.*