.htaccess RewriteRule not redirecting from real folder - .htaccess

I'm still a bit fuzzy on the working of .htaccess, and I've looked around but I can't find anything to help this specific issue.
EDIT: I realize there are other questions that seem like they cover this issue, but I checked some and they didn't seem to offer any help I could understand, and I didn't want to hijack them with my own issues.
This is what I have:
Options +FollowSymLinks
#RewriteBase /
RewriteEngine on
RewriteRule /mp3/(.*) http://old.domain.com/mp3/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)$ /index.php?p=$1 [L]
As you can see from the last line, the string typed after the server name is actually a URL parameter and depending on that parameter, different content is pulled from the database and that page is displayed on the site.
The problem I'm having is that the client has a content page called "podcast", so they would go to site.com/podcast which should quietly redirect to site.com/index.php?=podcast and load the content for that page. Unfortunately, the client also has a real site.com/podcast/ folder on their server. Because of this, the rewrite is ignored and the browser attempts to load that folder. It either shows a file listing or a forbidden error if I disable the listing.
After some research (I'm still new to htaccess), I learned that the two lines prior disable the rewrite if the path points to an actual file or folder. Unfortunately, commenting out the one with !-d doesn't seem to have any effect, and commenting out both gives me a server error.
Admittedly, part of the problem here was lack of foresight. URL rewrites should have been planned before everything else was put together, but it wasn't until the site was basically completed that I was notified that the client wants "Friendly URLs" that don't include the ?p= part. Regardless, perhaps there is a way to fix this.
Is there some .htaccess trickery I can use that will force the rewrite even if the URL entered points to a folder (not a specific file) that actually exists? As stated before, removing the !-d doesn't seem to help, although I'm not sure why. Perhaps I misunderstand its purpose.
Thank you for any help, and please be lenient with me if I overlooked something obvious. This is an issue presenting itself on the client's live site right now so I feel a little rushed in solving it. Thanks again.
OH YEAH, and the solution can't be specific to /podcast. The way the client's site is set up, when they want to create a new subpage for the site, a new name is saved for that content based on their title for the page and it is possible (unlikely, but still possible) that another page can be created with a name that matches an existing folder on the server.

Here is a note from mod_rewrite documentation:
By default, mod_rewrite will ignore URLs that map to a directory on
disk but lack a trailing slash, in the expectation that the mod_dir
module will issue the client with a redirect to the canonical URL with
a trailing slash.
This explains why mod_rewrite ignores the URL /podcast. I would suggest that you rename physical directories so that do do not (accidentally) match article names.
Another option would be to disable the DirectorySlash setting. This will prevent Apache from redirecting /podcast to /podcast/.
DirectorySlash Off
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)$ /index.php?p=$1 [L]
Be warned that disabling this setting has side effects. Read through the documentation first.

Change the following line of code:
RewriteRule ^([^/]*)$ /index.php?p=$1 [L]
to
RewriteRule ^(podcast([^?]*)) index.php?p=$1 [L,NC]

Related

.htaccess redirect whole website structure but leave some of the old structure intact

I have searched but can't quite find the answer to this exact situation:
My website structure is as follows
www.example.co.uk/old-folder1/old-folder2/old-page-name
I needed to redirect the whole structure to:
www.example.co.uk/new-folder1/old-folder2/old-page-name
I successfully did this with:
RewriteRule ^old-folder1/(.*)$ /new-folder1/$1 [R=302,L]
However, if possible for the moment I still want to serve images from the old structure ie.
www.example.co.uk/old-folder1/old-images-folder/old-image.jpg
At the moment the above is being rewritten as:
www.example.co.uk/new-folder1/old-images-folder/old-image.jpg
Which makes sense but this leads me to my question, is there any way of excluding some of the sub directories in 'old-folder1' from the RewriteRule above so that for example www.example.co.uk/old-folder1/old-images-folder/old-image.jpg is still accessible?
I don't have much experience with this but from research I came up with the following but it doesn't work.
RewriteCond %{REQUEST_URI} !^/old-folder1/old-images-folder/.*$
I am beginning to think this might not even be possible with the approach I have taken with:
RewriteRule ^old-folder1/(.*)$ /new-folder1/$1 [R=302,L]
Thanks
Entire contents of the .htaccess file at the moment is:
Options +SymLinksIfOwnerMatch
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^/old-folder1/old-images-folder/.*$
RewriteRule ^old-folder1/(.*)$ /new-folder1/$1 [R=302,L]
Try:
RewriteRule ^old-folder1/(?!old-images-folder)(.*)$ /new-folder1/$1 [R=302,L]
HOwever, what's probably happening is that your images are linked using relative URLs, so they may be relatively linked to the "new" images folder.
You should check your links and make sure they're linked correctly to the old path.

htacces - need to fix broken links coming from other sites to mine

I am having an issue where Google Webmaster Tools is reporting a ton of 404 links to my site which are coming from ask.com.
I have tried to get ask.com to fix their side but of course they are not, so now I am stuck with over 11k of bad links to my site which I am suspecting is effecting my ranks right now.
Anyways I have a possible way to 301 them, but not sure how to do it with .htaccess.
Here is the bad link pointing to my site
http://www.freescrabbledictionary.com/sentence-examples/fere-film/feverous/about.php
It should be
http://www.freescrabbledictionary.com/sentence-examples/fere-film/feverous/
Besides the about.php there are other variations of endings as well, I basically need to be able to remove the ending.
Problem is that the URL after /sentence-examples/ can change. The beginning is always:
http://www.freescrabbledictionary.com/sentence-examples/
So basically:
http://www.freescrabbledictionary.com/sentence-examples/<-keep but can change->/<-keep but can change->/<-remove this->
This .htaccess should be placed on the folder before sentence-examples:
RewriteEngine on
# Redirect /sentence-examples/anything/anything/remove to /sentence-examples/anything/anything/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+(sentence-examples/[^/]+/[^/]+)/.* [NC]
RewriteRule ^ /%1/? [R=302,PT,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/(.*)$ /sentence-examples/examplesentence.php?havethis=$1&word=$2 [L]
Change 302 to 301 once you confirm it's working as expected.
If you have a CMS installed you might need a different rule to work along with it without conflicting.
Keep in mind that if you had previously tried different redirects using 301 aka permanent redirect its recommended that you use a different browser to test this rule to avoid the caching.
This is possibly quick and dirty but I've done a simple test on localhost and here just to make sure it works.
RewriteEngine On
RewriteRule ^sentence-examples/(.*)/(.*)/(.*)\.php http://www.freescrabbledictionary.com/sentence-examples/$1/$2/ [R=301,L]
You can see that I've added wildcard groups (.*) to the RewriteRule so that we can pick up the elements of the URL that we need to aid in proper redirection i.e. $1 and $2. You can also use the third one ($3) to get which destinations are being targeted alot for your SEO needs.
NB: The rule above assumes that that the redirected URL will always be from a .php target and to ensure that you can redirect regardless of whatever comes after the 3rd URL segment replace the RewriteRule with this
RewriteRule ^sentence-examples/(.*)/(.*)/(.*)$ http://www.freescrabbledictionary.com/sentence-examples/$1/$2/ [R=301,L]

htaccess: Rewrite - but keep site resources?

I know this is likely a question that is being asked often, I've searched for answers but couldn't come up with anything that answers my case. I'm assuming it's because I'm not figuring out the correct search terms, so I'm sorry If this is redundant... Thank you for your time!
I use .htaccess to rewrite my URLs to a more user friendly format. That's really all I want to do so if there's an entirely better way to do it, I'd be grateful to learn!
Anyway; I rewrite localhost/room/2 to index.php?p=room&id=2. That works like a charm.
RewriteRule ^room/([0-9]*)$ /index.php?p=room&id=$1 [L]
You can probably already tell my problem: I'm creating a virtual folder using room/room_number. So when I - for example - include a picture using an IMG-Tag, that src-Attribute is being rewritten as well to fit the working directory the server assumes to be in. Instead of requesting
localhost/img/image.jpg
It requests
localhost/room/img/image.jpg
which obviously isn't the right location. So my question is; How do I rewrite the URL to something nice and user friendly while simoultaneously re-REdirecting the page's resources to their original path?
Use paths relative to the root directory by prepending the paths with a leading slash:
<img src="/img/image.jpg" />
Another (and fairly standard) solution to this problem is to add a RewriteCond so that the rule is never applied when a resource is requested that really exists.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^room/([0-9]*)$ /index.php?p=room&id=$1 [L]

CodeIgniter + mod_rewrite URI shortening

I am building a blog-ish site using CI. I am using the HMVC plugin. The module that I am working in is "/journal".
The individual articles are accessed at /journal/article/ID/SLUG. This works fine, but I would like to shorten the URI to /journal/ID/SLUG using mod_rewrite.
Here are my rules:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^journal/([0-9]+)(.*)$ index.php?/journal/article/$1$2 [L,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1
For testing I am using /journal/2.
I know that the rules is matching. If, for instance, I change the redirect to http://google.com, I will indeed get redirected to Google. However, when using the rule as written it seems to be ignored and I get a 404 no matter what I put in.
Am I making some obvious (or arcane) error?
Edit: I figured this out shortly after posting the question. My rules are indeed correct but I need to change the following line in config/config.php:
$config['uri_protocol'] = 'AUTO';
to
$config['uri_protocol'] = 'PATH_INFO';
I won't claim to know exactly what that change does or why it fixes the issue. Perhaps someone can follow up with an explanation.
The $config['uri_protocol'] tells CI which $_SERVER superglobal to use to determine your apps URI. The 'PATH_INFO' option uses $_SERVER['PATH_INFO'] which is the URL request (without host portion), see php manual.
The 'AUTO' option is a CI thing to make suitable for different environments without config tweaks.
Personally, I have written a few PHP SEF controllers, I find it better to do all the processing with the PHP controller(s) scripts.
htaccess and rewrites can be tricky, harder to debug and one typo can kill the whole site (ouch). I am sure there are small performance gains, but one would need some pretty heavy demands. You are heading to your index.php controller anyway. I find happier code when it is all in one place ;-)
good luck with it...and hopefully I provided some insight to your issue.

.htaccess rewrite rule for /

I have a website where if I go to the URL http://mysite.com/community it shows page not found. But, the URL http://mysite.com/community/ correctly displays the page. How can I set up a rewrite for that "/" after community?
This is my present .htaccess:
Options +FollowSymLinks
Options +Indexes
RewriteEngine On
RewriteRule ^admin$ Admin/index.php?qstr=$1 [L]
RewriteRule ^(.*)/$ index.php?qstr=$1 [L]
These were the ones tried by me, but failed
First,
RewriteRule ^(.*)/community $1/community/ [L]
second,
RewriteRule /community /community/ [L]
All with different combinations of with and without [L].
From the Apache URL Rewrite Guide:
Trailing Slash Problem
Description:
Every webmaster can sing a song about the problem of the trailing slash on URLs referencing directories. If they are missing, the server dumps an error, because if you say /~quux/foo instead of /~quux/foo/ then the server searches for a file named foo. And because this file is a directory it complains. Actually it tries to fix it itself in most of the cases, but sometimes this mechanism need to be emulated by you. For instance after you have done a lot of complicated URL rewritings to CGI scripts etc.
Solution:
The solution to this subtle problem is to let the server add the trailing slash automatically. To do this correctly we have to use an external redirect, so the browser correctly requests subsequent images etc. If we only did a internal rewrite, this would only work for the directory page, but would go wrong when any images are included into this page with relative URLs, because the browser would request an in-lined object. For instance, a request for image.gif in /~quux/foo/index.html would become /~quux/image.gif without the external redirect!
So, to do this trick we write:
RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo$ foo/ [R]
The crazy and lazy can even do the following in the top-level .htaccess file of their homedir. But notice that this creates some processing overhead.
RewriteEngine on
RewriteBase /~quux/
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]
Well, after trying out all the above solutions as well as some of my own, I finally solved this. I'm definitely sure that this is NOT a complete solution but it sure solved it for the time being.
Solution: Just created an empty directory named "community" in the root folder. That's it!
But I'm still on the lookout for the actual solution to this.

Resources