Welcome to WebmasterWorld Guest from 18.205.176.85

Forum Moderators: Ocean10000 & phranque

Message Too Old, No Replies

Mod Rewrite breaking css on second level links

     
11:25 am on Mar 25, 2015 (gmt 0)

Preferred Member

10+ Year Member

joined:Aug 20, 2004
posts: 615
votes: 0


Hello all -

This problem (and the apparent solution of pre-pending a '/' to css and other site asset-related hrefs) is posted all over the place but after nearly a day of trial and all error, I've come back to the place where I always get straightened out.

Okay, here's the scenario:

I've got an .htaccess file with the following:

Options +FollowSymLinks
RewriteEngine on
RewriteBase /MySite
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ ./index.php

My directory structure for this site is as follows:

MySite
assets/css/(css files)
assets/favicon/(favicon file)
ETC.

This site has a number of nav bar items and some nav bar items have a drop-down menu containing various sub items. Pretty typical.

Now, when I fire up the site on my local dev. environment, everything is fine: css loads, favicon loads, etc. - great, no problem.

However, when I choose an item from one of the drop down menus - my fav icon disappears, as does my css styling.

From (all kinds) of other sites talking about this problem, they all say that this problem is due to relative links and prepending the css href path with a '/' will solve the problem.

Not so in my case.

When I test this solution...

From: <link rel="stylesheet" href="assets/css/01.structure.css">
To: <link rel="stylesheet" href="/assets/css/01.structure.css">

Not only does my styling still not show up on my drop-down menu pages, but now it also disappears from the top-level pages as well.

Of course, if I switch the href back to "assets/css/01.structure.css" top level pages are styled but not drop-down menu pages.

I suspect this problem may lie in my .htaccess rules but - after trying more than a dozen variations to the rewrite rules - I'm still coming up empty and just don't know what else to try.

I thought the problem may be in my RewriteBase /MySite rule, but if I comment that out, all I get is "The requested URL /MySite/index.php was not found on this server."

Can anyone please help guide me through this problem?
2:20 pm on Mar 25, 2015 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Aug 10, 2001
posts:1551
votes: 10


First, I personally consider it bad style to redirect 404s to an index page witout giving any indication to the visitor about what happened and why. Although it doesn't seem to have anything to do with your current problem, I would replace the rewrite shown with a custom 404 page (there are lots of things you can do on a custom 404 to help the visitor find the page they were really looking for).

To your actual question:
You keep talking about your menus, but I think that only confuses the issue. You need to look at the affected pages as such, not at the way you navigated there.

Your description doesn't really explain the structure of the site very clearly (maybe a post formatting issue).
The most natural assumption would be a structure like this:
$DOCUMENT_ROOT/assets/...
$DOCUMENT_ROOT/index.php (the page that sees the assets)
$DOCUMENT_ROOT/subdir/otherpage.php (the page that doesn't)

Your symptoms and your use of RewriteBase indicate that this isn't really the case, and the actual structure may rather look like this:
$DOCUMENT_ROOT/MySite/assets/...
$DOCUMENT_ROOT/MySite/index.php
$DOCUMENT_ROOT/MySite/subdir/otherpage.php

This will confuse both absolute and relative asset links, because they are not usually designed for a site residing in a subdirectory. You might want to reconfigure your staging server, so that the site gets its own DOCUMENT_ROOT like it most likely has on the live server.
A made up domain name, an extra apache config entry and a new line in /etc/hosts should do the trick.

If that isn't possible, then something like this (and absolute links) might serve as a stop-gap measure (untested):
RewriteCond %{REQUEST_URI} !^MySite/
RewriteRule assets/(.*) /MySite/assets/$1 [L]

If your site structure is still different yet, you will need to adapt the concept accordingly.
7:15 pm on Mar 25, 2015 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15944
votes: 890


I smell a CMS.
RewriteRule ^(.*)$ ./index.php

Please say that something got left out in posting. If this crucial rule has no [L] flag, you can be pretty confident that everything will break. In any case, conditions based on
%{REQUEST_FILENAME} !-f
should be treated as an absolute last resort. At a minimum, change the rule so it only applies to requests for pages. Otherwise the server has to do an extra lookup on every request for a supporting file, even though you can be pretty confident they do physically exist. And if they don't exist, the server is perfectly capable of sending out its own 404.

If the same links are used throughout the site, they absolutely must begin with / slash for the root. Otherwise the server will be sending in requests for nonexistent files, which will be routed to index.php (see above), which will not know what to do with them.

I personally consider it bad style to redirect 404s to an index page witout giving any indication to the visitor about what happened and why

I agree completely, but I don't think that's what's going on here. I think it's the standard CMS thing where nothing physically exists-- at least no page-- and everything is sent to an "index.php" file that builds the page.
11:58 pm on Apr 9, 2015 (gmt 0)

Preferred Member

10+ Year Member

joined:Aug 20, 2004
posts: 615
votes: 0


Hello Bird and Lucy24 -

Thank you both VERY MUCH for your input and apologize for the late reply - out of town for 2 weeks.

Finally got it working... problem was not pre-pending my links with "/MySite/assets/..."

Thanks for being my seeing-eye dog on this.

What I've now got in my WORKING .htaccess is the following:

+++++++++++++++++++++++++
Options +FollowSymLinks

RewriteEngine on

RewriteBase /mySite

# Don't Rewrite For Existing Files
RewriteCond %{REQUEST_FILENAME} !-f [NC]

# Don't Rewrite For Existing Directories Except for the root directory
RewriteCond %{REQUEST_FILENAME} !-d [NC,OR]
RewriteCond %{REQUEST_URI} ^/$

RewriteRule ^(.*)$ ./index.php [L]
+++++++++++++++++++++++++

Two quick follow-on questions:

#1
While I'm still trying to learn some of the intricacies of Mod Rewrite, I keep coming across posts that show the following hdaccess example:

RewriteCond %{REQUEST_URI} !\.(bmp|css|gif|ico|jpg|jpeg|js|png|shtml|zip)$ [NC]

I can't quite understand what this is suppose to do... ignore the files types and files listed?

#2
Is there anything else either of you could recommend that I include to increase performance (i.e. that the re-write engine isn't working overtime on stuff it shouldn't'?).

Thanks again to you both for your previous assistance and looking forward to your replies on the above.
2:46 am on Apr 10, 2015 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15944
votes: 890


RewriteCond %{REQUEST_URI} !\.(bmp|css|gif|ico|jpg|jpeg|js|png|shtml|zip)$ [NC]

I can't quite understand what this is suppose to do... ignore the files types and files listed?

Yes, except that it's an utterly ridiculous way to do it. What you ought to do, instead, is put your page extensions in the body of the rule, so the server never even has to look at conditions when it's a request for a supporting file. The exact wording of the rule will depend on your URL structure; for example when I make access-control rules for my hardcoded html site, it will say
RewriteRule (^|/|\.html)$ blahblah
and then the conditions, whatever they happen to be, only need to be evaluated on page requests.

Never use [NC] unless the string you're evaluating can actually occur in all possible casings. For example "jpe?g" [NC] won't just match jpg, JPEG and Jpeg; it will also match JpeG and jPg and lots of other things that I'm quite certain you do not have. The form [NC] is really a shorthand notation for, in this case, [Jj][Pp][Ee]?[Gg]. It makes my fingers tired just typing it.


My #1 recommedation at all times is: Never put anything in a condition that can go in the body of the rule. mod_rewrite works on a "two steps forward, one step back" system, where it doesn't even look at a RewriteCond unless the RewriteRule itself can potentially match.

Edit: OK, there's an exception. If the rule involves a complicated capture that will only end up being used if a whole string of conditions are met, then save the capture for the very last condition and express the rule target with %1 instead of $1.