Forum Moderators: phranque
I want this to be rewritten to
[one.domain.com...]
[one.domain.com...]
[one.domain.com...]
yet not shown in the address bar.
I have created this .htaccess file:
Options +FollowSymlinks
RewriteEngine on
RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTP_HOST} ^one.domain.com$ [NC]
RewriteRule ^(.*)$ /show.php?w=$1 [L]
However, there is a problem when the URLs don't end with a slash, like this:
[one.domain.com...]
[one.domain.com...] displays in the address bar correctly, however
[one.domain.com...] does redirect properly, but displays as [one.domain.com...] in the address bar.
This happens with any level of subdirectories, i.e.
[one.domain.com...]
becomes
[one.domain.com...]
I have noticed that this only happens when the URL is handling real directories.
Let's say dir1 exists. [one.domain.com...] displays [one.domain.com...]
but if dir2 doesn't exist, [one.domain.com...] remains unchanged in the address bar.
My subdomain is also accessible as a subdirectory of the main domain: [domain.com...]
Could there be the problem?
I searched high and low but haven't found a way to fix that.
Hope somebody could help. Thanks!
I want this to be rewritten to
[one.domain.com...]Let's get the terminology right to ensure we fully understand the question.
If you code you want is for a rewrite, then the target will be an internal filepath (just a filepath) not a URL. You are showing a URL as the target in your question.
If you really are targetting a URL, then you'll be wanting a redirect from the old URL to the new URL. In this case that would expose the parameter-based URLs to the user.
http://one.domain.com/dir1 does redirect properly, but displays as [one.domain.com...] in the address bar.Now you are saying "does redirect properly", but your original question asks for a rewrite, not a redirect.
Because the terminology does not match your code it is unclear what it is you want to do.
Yes, you're right. As seen in my code, I want an 'internal redirect', i.e. [one.domain.com...] to internally redirect to show.php?w=dir1, making the URL [one.domain.com...] remain unchanged in the address bar of the browser.
What I meant with "redirect properly". For testing purposes my 'show.php' file is a simple script that outputs the w parameter in the URL show.php?w=something. So with the .htaccess code provided above, if I open [one.domain.com...] I get:
1. the URL in the address bar changes to [one.domain.com...]
2. the page displays 'dir1/', meaning the redirect properly got to show.php and the php script correctly output the paramter.
Note, this only happens if /dir1 is an actual directory. If there isn't such a directory the URL remains unchanged.
So the big problem really is that the URL unwontedly changes in the address bar and I want it to remain as it is.
One thing that's dangerously unclear here (dangerous because it can hurt your search engine rankings) is "What is your precise (single, unique) URL?"
You mention "dir1" (a file), and "dir1/" (a directory or directory index) as if they are the same URL, but they are not. This appears to be contributory to your problem -- Any single character difference makes it a different URL, and you may be flirting with a duplicate-content problem here.
Pick the slashed or non-slashed format as your preferred canonical URL, rewrite only URLs matching that exact format to your script, and redirect all non-canonical variations to the correct canonical URLs.
Also, if you don't use content-negotiation, then disable MultiViews using your Options directive; MultiViews is a common cause of "exists vs. doesn't exist" problems. Another one is the action of Apache's mod_dir, and that can be addressed by referring (i.e. both thinking and linking) to your resources properly as files or directories, and not expecting them to be "the same thing."
A couple of points to clarify this discussion:
/dir1 = URL-path to a file (test -f in RewriteCond)
/dir1/ = URL-path to a directory (test -d in RewriteCond)
Internal rewrite: For requested URL=X, serve content from server filepath=Y
External redirect: For requested URL=X, respond with 30x redirect telling client to issue a new HTTP request for URL=Y, and terminate this current HTTP transaction.
Finally, it's a good idea to make absolutely sure that direct access to your script via HTTP is not possible, and that any client attempt to directly access the script URL will result in a redirect back to the SEO-friendly URL.
Putting all of that together, you'll end up with something like:
Options +FollowSymlinks -MultiViews
RewriteEngine on
RewriteBase /
#
# Externally redirect to remove trailing slashes from SEO-friendly URLs
RewriteCond %{HTTP_HOST} ^one\.example\.com
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ http://one.example.com/$1 [R=301,L]
#
# Externally redirect to SEO-friendly URL to prevent direct access to script filepath as a URL
RewriteCond %{HTTP_HOST} ^one\.example\.com
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /show\.php\?w=([^&\ ]+)[^\ ]*\ HTTP/
RewriteRule ^show\.php$ http://one.example.com/%1 [R=301,L]
#
# Internally rewrite SEO-friendly slashless URLs to "show.php" script with w=<local-URL-path> as parameter
RewriteCond %{HTTP_HOST} ^one\.example\.com [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /show.php?w=$1 [L]
Jim
However, I didn't explain one thing. I want real directories to be 'overwritten'. Don't know if that's the correct term here. I have many directories and subdirectories which contain pictures. My php script is supposed to get the 'w' parameter and return a page containing on-the-fly thumbnails of those image files. And I don't want the real directories to be accessible from a direct request like [one.domain.com...] or [one.domain.com...] So I don't want the default apache directory listing to be shown, but instead the output of the show.php.
So, when I use your code now, everything works just fine. I get rid of the trailing slash if such a slash exists in the URL and show.php outputs the correct parameter. That's only the case if I'm not 'accessing' directories that exist.
When I enter a URL that leads to a real directory, things get REAL weird.
Here is a simple structure of the subdomain:
[one.domain.com...]
-/dir1/
-/dir2/
--/subdir-of-dir2/
-/dir3/
Along with many many other directories and subdirectories and so on.
So using your suggested .htaccess code, if I enter:
[one.domain.com...] the browser displays the actual content of the directory. In my case since there's no index file, apache displays Index of dir/ as a list of the files and directories inside. If I enter the URL without a slash, in the address bar it changes to:
[one.domain.com...] and again the webpage is a list of the files and dirs in that directory shown by Apache.
Did I mention I have a hosting provider using cPanel and that the subdomain is set thru the cPanel? So the subdomain is a directory within the main domain.
Does that have any significance at all.
Thanks!
Defining exactly what you want to do, in terms of both URLs 'used on the web' and server filepaths 'inside the server' is crucial.
Only when that is clear should coding be started. Starting the coding before fully defining what has to be done often leads to giving a technically correct solution to the wrong problem.
Options +FollowSymlinks -MultiViews [b]-Indexes[/b]
RewriteEngine on
RewriteBase /
#
# Externally redirect to remove trailing slashes from SEO-friendly URLs
RewriteCond %{HTTP_HOST} ^one\.example\.com
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ http://one.example.com/$1 [R=301,L]
#
# Externally redirect to SEO-friendly URL to prevent direct access to script filepath as a URL
RewriteCond %{HTTP_HOST} ^one\.example\.com
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /show\.php\?w=([^&\ ]+)[^\ ]*\ HTTP/
RewriteRule ^show\.php$ http://one.example.com/%1 [R=301,L]
#
# Internally rewrite SEO-friendly slashless URLs to "show.php" script with w=<local-URL-path> as parameter
RewriteCond %{HTTP_HOST} ^one\.example\.com [NC]
RewriteCond %{REQUEST_FILENAME} !-f
[b]RewriteCond %{REQUEST_FILENAME} !-d[/b]
RewriteRule ^(.*[^/])$ /show.php?w=$1 [L]
I decided to go for URLs with slashes. Because I'm handling directories and slashes get automatically added by the server, so why get rid of them. So what actually did it for me, was so simple. I have to check if the reqested filename is a directory and only then rewrite/redirect it.
I want to handle URLs only leading to existing directories, so that was logical and it worked.
Here's how I changed the code:
RewriteCond %{HTTP_HOST} ^one\.domain\.com [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ /show.php?w=$1 [L]
That does exactly what I want it to do. I have to confess I would have never thought of this if I didn't ask for help here. I did read some of the documentation and it was all clear to me.
Now, g1smd, I call you "the big Scolder". I'm sure you know a lot of things and are good in what you do, but when you're asked for help next time, you might actually try to help and not rebuke. Nobody's perfect. Nobody knows everything. Just like you wouldn't possibly understand what I do, I don't understand what you do. In this case, the mod_rewrite logic. And no offence, Yoda, your style I really like.
jdMorgan, you helped me out with what's been bugging me for a week. Thank you very much indeed! Not only did I solve my problem, but learned a lot of things and I'm sure this all will come in handy.