So I rewrote my paths to something like: URL/really/nice/paths/ using mod_rewrite rules like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
</IfModule>
The question is how could I rewrite the paths for js/css/image files too, so when they are requested with a relative path from URL/really/nice/path/ to be served from URL/scripts/, URL/styles/ and URL/images/ folders instead? Can this be done without using RewriteBase?
When URLs are rewritten, the client doesn't know it. So when a client looks at a page at the URL "example.com/some/url/" and the page references an image in "images/image.jpg", the client looks for the image in "example.com/some/url/images/image.jpg" even though the page actually resides in "example.com/some/other/url/". That's the problem you're facing, right?
There are three main solutions to this problem:
Use absolute paths to resources instead of relative ones.
Use the <base> tag to ensure that the client knows the root upon which to build its relative URLs is different from the page's apparent URL.
Add a new rule for "some/url/images/" in your rewrite rules.
Option 1 is probably the best idea, and you'll find that most sites that use URL rewriting use it, including Stack Overflow itself. Option 2 is frowned upon, but works and is relatively easy. Option 3 is the most difficult to maintain, as URL rewriting exceptions and special cases can appear as you're defining new rules.
The most maintainable solution is to use absolute URLs.
Related
I've had a good look through all the other htaccess url rewrite questions, but all of them deal with the reverse of my problem.
The site I am working on takes content from child pages in WordPress and presents them as anchored sections on the parent page. The problem for the site now is that if Google (or the built in search, though that can probably be done in the templates) links to one of the child pages it will direct users to the single page rather than the correct section of the parent page.
I was hoping to come up with a URL rewrite pattern which would reformat the URL to what I need, but it doesn't seem to work... and I know that's because I have done it wrong!
The URL which needs to be rewritten is something like:
website.com/parent-page/child-page/
I need this to be rewritten to:
website.com/parent-page/?subpage=child-page
My initial stab at it looks like this, but I know I've misunderstood something about how to format the pattern.
RewriteRule ^/$1?subpage=$2 ^/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$
Can anyone help format this correctly or point out where I'm going wrong?
You can use:
RewriteEngine on
# If the request is not for a valid file/directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/([^/]+)/?$ /$1/?subpage=$2 [QSA,L]
No initial / in htaccess RewriteRule first uri
And optional final /
RewriteRule ^([^/]+)/([^/]+)/$ /$1/?subpage=$2 [L]
The htaccess rewrites didn't seem to work, so I've created a PHP redirect instead by taking the page slug, page parent permalink and mashing the two together.
Not the most elegant solution, I expect, but it works.
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]
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]
I have inherited a custom ColdFusion CMS app. The URL's that it creates are horrendous. Not at all suitable for SEO or readability for that matter. An example of a URL in this CMS is:
http://www.mysite.com/Index2.cfm?a=000003,000010,000019,001335
Basically, each level of hierarchy is stored in the database based upon that long string of comma separated values. So in the case of the example I used, that particular page is 4 levels deep in the CMS hierarchy.
Basically what I would like to see is a format similar to this
http://www.mysite.com/level-1/level-2/level-3/level-4
Is this possible? Any help would be greatly appreciated. For what it's worth we are using ColdFusion 6 at present time, but will be upgrading to 8 in the near future.
First of all, are you willing to have the index.cfm in the URL? Like: http://www.mysite.com/index.cfm/level-1/level-2/level-3/level-4 ? If not, then you'll need to be doing a rewrite to remove the index.cfm, but still allow CF to process the page. Your .htaccess would look something like this:
RewriteEngine On
# If it's a real path, just serve it
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]
# Redirect if no trailing slash
RewriteRule ^(.+[^/])$ $1/ [R=301,L]
# Rewrite URL paths
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^([a-zA-Z0-9/-]+)$ /index.cfm%{REQUEST_URI} [PT]
Next step, you'll need to "catch" the URLs and serve up the correct pages based on the SEO-friendly URLs. You can grab the incoming URL from the CGI.path_info variable. It's hard to know what your code should look like without knowing how it currently processes those URL variables, but essentially you'd have some kind of mapping function that grabbed the SEO-friendly names and substituted in the numbers to grab the content.
The third step is rewriting any URLs that are generated by your CMS to output the SEO-friendly URLs. Same mapping happens here, only in reverse.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(.*)\.(css|js|htc|pdf|jpg|jpeg|gif|png|ico)$ [NC]
RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
This .htaccess redirects everything to index.php?path=SOMETHING where I can pick it up (SOMETHING path) and show appropriate content (views).
The problem is with including .css/.js files.
If I use www.website.com/something everything works (css path is like /css/style.css and it's searching in the www.website.com/css/style.css). But if I use www.website.com/something/2 everything crashes because it's searching in www.website.com/something/css/style.css folder.
How to set root (?) everytime to www.website.com (whatever path is)? So I should still have acccess to my 'path' variable but everything should point to the website root and not /some/... path when including my files.
The problem is in the way how you write links to css/js/image files.
Instead of including css/js/images using relative URLs to the current page:
href="css/style.css"
you should use URLs relative to the root (notice the leading slash):
href="/css/style.css"
or use absolute URLs (that will include domain name -- much less preferred approach).
This is a typical mistake when designing website (html part) when site uses Nice URLs/URL Rewritting. This is -- it's now that rewrite engine breaks URLs -- it's browser that sends them like that (/something/css/style.css) in first place.