Forum Moderators: phranque

Message Too Old, No Replies

htaccess internall and external redirection

internall and external redirection

         

crouser

2:54 pm on Jul 17, 2010 (gmt 0)

10+ Year Member



Hi all!

I'm having htaccess trouble.
The thing I'm trying to do is for example:

There is an existing file: a.txt in the root directory.

Now if a user requests "www.mydomain.com/sample.txt" I'd like it that the requested URL (all of it) is kept, but instead to display the contents of file "a.txt", as if the user requested "www.mydomain.com/a.txt".

Note, that the file "sample.txt" wouldn't actually exist it would just serve as an alternative "path" to reach "a.txt"

And ofcourse I would 301 redirect the actual "www.mydomain.com/a.txt" request to "www.mydomain.com/sample.txt" which would again have the result of displaying the contents of "a.txt".

Now I know it can be done via internal redirection by I don't know how :(

I hope it makes sense :)

BIG thanks in advance!
Regards!

g1smd

3:49 pm on Jul 17, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



# External 301 Redirect
RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /real-file-path/real-file-name\ HTTP/
RewriteRule ^real-file-path/real-file-name$ http://www.example.com/new-file-path/new-file-name [R=301,L]


# Internal Rewrite
RewriteRule ^new-file-path/new-file-name$ /real-file-path/real-file-name [L]


THE_REQUEST is tested to make sure it is a direct external client request. Omitting that would cause an infinite loop.

"new" is what you want users to see and use.

"real" is where it really is inside the server.

jdMorgan

4:13 am on Jul 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Or to make this even more-accurate:

# External 301 Redirect to fix the problem of the real filepath being used as a URL-path
RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /real-file-path/real-file-name\ HTTP/
RewriteRule ^real-file-path/real-file-name$ http://www.example.com/new-URL-path-path/new-resource-name [R=301,L]
#
# Internal Rewrite to serve the correct file when the new URL is requested by the client
RewriteRule ^new-URL-path/new-resource-name$ /real-file-path/real-file-name [L]

The intent here is to illustrate the difference between URLs and filepaths, and to point out that a server's fundamental job is to associate client-requested URLs with server-internal filepaths. URLs and filepaths are not the same thing, nor even necessarily 'related' or 'similar.' Understanding this distinction makes understanding mod_rewrite a whole lot easier... :)

Jim

crouser

11:42 am on Jul 18, 2010 (gmt 0)

10+ Year Member



Hi again!

Thanks for the help you two, The given rules worked great for a SPECIFIC "file" just as I wanted for the given so called problem. So BIG thanx again for that! :)

Now I came across another difficulty when I tried to modify the given solution to work a bit more dynamic, and when I say dynamic, I mean CMS like Joomla.

There are a few default Joomla htaccess rules in order to make the CMS work, which shouldn't interfere with the code that I tried (but FAILED to work for the most part). I'll write it bellow...



###### START of my htaccess code ######

Options +FollowSymlinks
RewriteEngine on

# External 301 Redirect
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /yyy/(.*)\ HTTP/
RewriteRule ^yyy/(.*)$ www.mydomain.com/$1 [R=301,L]

# Internal Rewrite
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteRule ^yyy/(.*)$ /$1 [L]

###### END of my htaccess code ######

###### START of Joomla default htaccess code ######

## Deny access to extension xml files (uncomment out to activate)
#<Files ~ "\.xml$">
#Order allow,deny
#Deny from all
#Satisfy all
#</Files>
## End of deny access to extension xml files
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
# Block out any script trying to base64_encode crap to send via URL
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
# Block out any script that includes a <script> tag in URL
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Send all blocked request to homepage with 403 Forbidden error!
RewriteRule ^(.*)$ index.php [F,L]
#
########## End - Rewrite rules to block out some common exploits

# Uncomment following line if your webserver's URL
# is not directly related to physical file paths.
# Update Your Joomla! Directory (just / for root)

# RewriteBase /


########## Begin - Joomla! core SEF Section
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
#
########## End - Joomla! core SEF Section


###### END of Joomla default htaccess code ######

NOTE: note above that the "yyy" refers to a non-existing folder which represents the language of the site (since it's a multilingual site) which I would like to get rid of, Also notice that the order in the "Internal Rewrite" is reverse, since I don't know how to specify it any other way.

Now all that said, the given code works for let's say this URL "www.mydomain.com/yyy/something" it will result in user being redirected to "www.mydomain.com/something" as I would want...

So the problem comes in to place when I would for example request "www.mydomain.com/yyy/something1/something2" then I get an error, the page can't open. Probably because of the incorrect redirection, which I don't know how to fix :(

So if there are MORE THAN ONE "something-s" after the "yyy" that I would like to get rid of it doesn't work ?!

P.S sorry for being so discreet with all the "somethings" and so on, but I hope you got what I'm aiming at.


ONCE AGAIN THANKS FOR THE HELP!
Regards!

jdMorgan

8:51 pm on Jul 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You cannot expect this to work if you 'reverse' the internal rewrite. Be very sure that you understand the distinction between URL-paths and filepaths here.

An external redirect is a URL-to-URL translation. When the client requests an old, bad, or incorrect URL, the server sends a reply saying, "That resource has been moved. Please ask for it again at this new correct URL." and it provides a "Location" header with the new URL in it. This terminates the HTTP transaction, and the client must start a new one by asking for the new/correct URL provided by the host.

An internal rewrite is a URL-to-filepath translation, where the server receives a client request for a URL, and changes the filepath that would normally be used to fetch (or generate) the content to a different, non-default filepath. This occurs entirely within the context of the client-initiated HTTP transaction, and the client is completely unaware of it.

URLs are used 'out on the Web' and filepaths are used inside the server. They are not the same thing, and need not even resemble each other. The server's primary job in fact is to translate URLs to filepaths, so that the correct content can be served.

I would also suggest disabling MultiViews if your site does not need content-negotiation.
Change "Options +FollowSymlinks" to "Options +FollowSymLinks -MultiViews"

Jim

crouser

12:19 am on Jul 29, 2010 (gmt 0)

10+ Year Member



Understood! :)

It's been pretty busy last few day so couldn't reply earlier.

Now if you guys can help out with the following:

The following code doesn't work it's the same as you posted apart from that it has query string in it?!

# External 301 Redirect
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /directory/index.php?option=com_xmap&sitemap=1&view=xml\ HTTP/
RewriteRule ^directory/index.php?option=com_xmap&sitemap=1&view=xml$ "www.mydomain.com/file.xml" [R=301,L]

# Internal Rewrite
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteRule ^file.xml$ "www.mydomain.com/directory/index.php?option=com_xmap&sitemap=1&view=xml" [L]



Actually the above code works partially, the part with the internal redirect works, while the external part is skipped as it somehow doesn't match the requested address.

So i tried to fix the problem like so:

# External 301 Redirect
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /directory/index.php\?option=com_xmap&sitemap=1&view=xml\ HTTP/
RewriteRule ^directory/index.php$ "www.mydomain.com/file.xml?" [R=301,L]

# Internal Rewrite
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteRule ^file.xml$ "www.mydomain.com/directory/index.php?option=com_xmap&sitemap=1&view=xml" [L]


And that ended up being a infinite loop, I checked with "Live HTTP headers" add-on, the loop goes like this:

www.mydomain.com/directory/index.php?option=com_xmap&sitemap=1&view=xml -> www.mydomain.com/file.xml

www.mydomain.com/file.xml -> www.mydomain.com/directory/index.php?option=com_xmap&sitemap=1&view=xml
...and so on...

If you could help me with this one I would much appreciate!? :)

I would like the following result:

if user requests: www.mydomain.com/file.xml -> the URL in the browser stays the same but he gets served with the content of www.mydomain.com/directory/index.php?option=com_xmap&sitemap=1&view=xml

if user requests: www.mydomain.com/directory/index.php?option=com_xmap&sitemap=1&view=xml -> he gets redirected to www.mydomain.com/file.xml and than sees the content of the initially requested address.

Hopefully I didn't make it to complicated to figure out what I tried to do, and what would like as a result.

BIG THANX!

Regards! :)

jdMorgan

2:44 am on Jul 29, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



RewriteRule cannot see query strings. It only looks at the local URL-path, not any queries appended to the URL. That is why we use a RewriteCond examining %{QUERY_STRING} or %{THE_REQUEST} when we want to deal with query strings.

It appears you're copying and pasting and trying to 'guess' a solution. That's dangerous, and will take far more time that just a few hours studying the documentation and understanding it. I commend the resources cited in our Apache Forum Charter to you as worthy of attention and time...

Jim

g1smd

7:14 am on Jul 29, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



In the redirect, the RewriteRule can only see the path part of the URL. It cannot be used to look at the requested query string.

In the "internal rewrite", by including a domain name in the target, you have instead coded a 302 redirect.

Additionally, http: is required on the target and the quote marks should be deleted.

crouser

11:44 am on Jul 29, 2010 (gmt 0)

10+ Year Member



A few things I forgot to mention in the post before (because it seamed too long anyway...) :)

1. I did try also using

# External 301 Redirect
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
[b]RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /dir/index.php\?option=com_xmap&sitemap=1&view=xml\ HTTP/
RewriteRule ^dir/index.php$ "www.mydomain.com/newfile.xml?" [R=301,L]

# Internal Rewrite
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteRule ^newfile.xml$ "www.mydomain.com/dir/index.php?option=com_xmap&sitemap=1&view=xml" [L]


but I guess that didn't work because of the domain name in the target in INTERNAL rewrite, and I also wrote it with "".


2. I know it should have http:// as well, my htaccess file did, but didn't wrote it here because this forum considers it as an outside link and rewrites it as so [onlyanexample.com...] :)


Now I finally got it to work like this:
# External 301 Redirect
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /dir/index.php\?option=com_xmap&sitemap=1&view=xml\ HTTP/
RewriteRule ^dir/index.php$ /newfile.xml? [R=301,L]

# Internal Rewrite
RewriteCond %{HTTP_HOST} ^www.mydomain.com$ [OR]
RewriteCond %{HTTP_HOST} ^mydomain.com$
RewriteRule ^newfile.xml$ /dir/index.php?option=com_xmap&sitemap=1&view=xml [L]



The reason why I needed RewriteCond %{HTTP_HOST} in both Internal and external is because I'm running two add-on domains for which the content of the file being displayed is different for each domain.

So finally thanx for the help again, I'm glad this works now!

If you thing there is a better way write this please do tell me, if not I'll be satisfied with the code so far which also does the job :)


Regards!

jdMorgan

1:05 am on Jul 31, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'd suggest:

# Externally 301 redirect requests for /dir/index/php?option=com_xmap&sitemap=1&view=xml
# in example.com domain to /newfile.xml and remove query string
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,8}\ /dir/index\.php\?option=com_xmap&sitemap=1&view=xml\ HTTP/
RewriteRule ^dir/index.php$ http://www.example.com/newfile.xml? [R=301,L]
#
# Externally redirect non-canonical example.com hostname variants to www.example.com
RewriteCond %{HTTP_HOST} ^example\.com [NC,OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com(\.|\.?:[0-9]+)$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
#
# Internally rewrite requests for /newfile.xml in example.com domain back to script path
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule ^newfile\.xml$ /dir/index.php?option=com_xmap&sitemap=1&view=xml [L]

Jim