.htaccess two query string cannot link to original folder - apache

Here is the file structure of my web
css/
script/
images/
.htaccess
index.php
ajaxusername.php
.htaccess content
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(\w+)/(\w+)$ index.php?d=$1&t=$2 [QSA]
RewriteRule ^(\w+)/?$ index.php?d=$1
When input http://www.abc.com/peter/, it can translate into http://www.abc.com/index.php?d=peter successfully.
When i input http://www.abc.com/peter/password, it can translate into http://www.abc.com/index.php?d=peter&t=password successfully too.
The problem is:
/peter/ can get the resources listed in above folders successfully but,
/peter/password cannot get those resources.
When I checked in firebug, it shows me it points to http://www.abc.com/peter/css/user.css, which is an invalid URL.
The correct URL must point to http://www.abc.com/css/user.css instead the previous one.
Any suggestion? Thanks!!

Problem is that you're using relative paths for css, js and images and once you start using pretty URL scheme of /part1/part2 it messes up URLs of your resources. As you've noted that css URI becomes /peter/css/user.css instead of /css/user.css.
Here are some solutions for you to help.
Solution 1: To overcome your issue I recommend using absolute path in your css, js, images files rather than a relative one. Which means you have to make sure path of these files start either with http:// or a slash /.
Solution 2: It is no doubt better to use absolute path for static files (css, js, images etc). But if you have lots of those instances in several pages then consider using HTML base tag to specify a default URL for relative paths. eg:
<base href="http://www.abc.com/" />
Solution 3: mod_rewrite based solution. Use it when you can't implement above solutions.
Have you .htaccess like this:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# don't do anything for a real directory, file or link
RewriteCond %{REQUEST_FILENAME} !-d [OR]
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule - [L]
# your original rewrite rules
RewriteRule ^(\w+)/?$ /index.php?d=$1 [QSA,L]
RewriteRule ^(\w+)/(\w+)/?$ /index.php?d=$1&t=$2 [QSA,L]
# rules to fix wrong paths of css, js and images
RewriteRule ^[^/]+/((?:css|script|images)/.*)$ /$1 [L,R=301,NC]

It looks like you need to add exceptions to your rewrite rules for requests to files and directories that exist on the server, otherwise when the files are requests by the client's browser they won't be served since the url is rewritten.
Try adding these lines:
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? - [S=2]
into your htaccess file:
Options +FollowSymlinks
RewriteEngine on
...put them here...
RewriteRule ^(\w+)/(\w+)$ index.php?d=$1&t=$2 [QSA]
RewriteRule ^(\w+)/?$ index.php?d=$1
And your resources should be accessible.

Related

.htaccess redirect only specific types of static content?

I'm looking to redirect any .php file requests to index.php or any requests to directories or static content that dosnt exist should also go to index.php.
This is what I have so far. I'm just not sure how to redirect only .php files and not redirect things like images, css, js
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
Based on your shown samples, could you please try following. Please make sure you clear your browser cache before testing your URLs.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
RewriteCond %{REQUEST_URI} \.php [NC]
RewriteRule ^ index.php [QSA,L]
JS/CS rewrite/redirect:
You may need to use base tag to fix your js and other relative resources. If you are linking js files using a relative path then the file will obviously get a 404 because its looking for URL path. for example if the URL path is /file/ instead of file.html then your relative resources are loading from /file/ which is not a directory but rewritten html file. To fix this make your links absolute or use base tag. In the header of your webpage add this <base href="/"> so that your relative links can load from the correct location.

RewriteRule doesn't exclude existing files/directories

So for a website I have an index.php file in my root directory that expects url parameters to determine which contents to echo:
example.com/?p=home
example.com/?p=blog
However, for aesthetical purposes, I wrote a RewriteRule in the .htaccess file in the root directory that redirect the following requests to the index.php in the root directory with URL parameters:
example.com/home → example.com/?p=home
example.com/blog/ → example.com/?p=blog
The rule looks like this:
RewriteEngine On
# This is my rule
RewriteCond %{REQUEST_URI} !^(bootstrap|cms|php|pics|project|install)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([a-zA-Z]*)/?$ index.php?p=$1 [NC]
# The following rules are used by the CMS I'm using, so I don't want to change those
RewriteRule ^(cms)($|/) - [L]
RewriteRule ^(install)($|/) - [L]
RewriteCond %{REQUEST_URI} !^(\.png|\.jpg|\.gif|\.jpeg|\.bmp)/$
RewriteRule (.*.html|.*.php|.*.htm) cms_worker.php?page=$1 [QSA]
However, using this all CSS and JS files that I included in the index.php using relative links (e.g. <link href="/project/style.css" rel="stylesheet">) aren't loaded as the rule seems to effect those requests as well.
Why is this happening? And how can I solve it? I thought the Rewrite Conditions above the rule should prevent the Rule from being applied when the requested directory or file exists ... I tried adding the first RewriteCond to exclude requests to the specified directories from the Rule, but that didn't work as well.
Edit: It works fine if I access a page without the trailing slash (i.e. example.com/blog). However, when I access the page with the trailing slash (i.e. example.com/blog/), the CSS and JS files aren't being loaded. The network tab of the Chrome dev tools doesn't show anything, but when I open the source code and click on the relative link to the css file, it redirects to example.com/blog/project/style.css instead of example.com/project/style.css
I believe this is due to regex pattern used in your rules. Try these rules:
RewriteEngine On
# This is my rule
RewriteCond %{REQUEST_URI} !^(bootstrap|cms|php|pics|project|install)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-z]+)/?$ index.php?p=$1 [NC,L,QSA]
# The following rules are used by the CMS I'm using, so I don't want to change those
RewriteRule ^cms($|/) - [L,NC]
RewriteRule ^install($|/) - [L,NC]
RewriteRule ^(.+?\.(?:html?|php))$ cms_worker.php?page=$1 [QSA,L,NC]
To resolve relative links add <base href="/"> in <head> section of your HTML.

htaccess rewrite rules to remove multiple subfolders from a URL

Due file system sub-directory constraints I will most likely reach I want to separate the /users folder into /users/a/username, /users/b/username, /users/c/username, etc.
So the data on the server for a user would be in:
www.domain.com/users/a/username/, www.domain.com/users/b/username/, etc
I want the URL to be:
www.domain.com/users/username/
Optionally to avoid duplicate content a 301 redirect from www.domain.com/users/a/username/ to www.domain.com/users/username/ would also be good.
Currently I have a rewrite for a single sub-directory (see below) but I'm confused how this can be done efficiently for all of the alphabetical sub-directories.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^users/(.*)$ users/a/$1 [L,NC]
I have checked this site and all seem to hide the first sub-directory e.g. domain.com/folder1/filename.html => domain.com/filename.html but nothing in more depth.
Put this code in your htaccess (which has to be in root folder)
Options -Indexes -MultiViews
RewriteMap lowercase int:tolower # this line in your apache file configuration
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/users/[a-z]/([^/\s]+)\s
RewriteRule . /users/%1/? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^users/([A-Za-z])([^/]+)/$ /users/${lowercase:$1}/$1$2/ [L]

RewriteCond Being Ignored?

I am trying to use mod_rewrite on a Ubuntu 12.04 server to make my URLs more readable, however I want to add an exception for images and css files.
My input URLs are in the format \controller\action which is then re-written to index.php?controller=controller&action=action. I want to add an exception so that if an image or css file is specified, the URL is not re-written, e.g. \images\image.jpg would not be re-written.
My .htaccess code is as follows:
RewriteEngine on
RewriteCond %{REQUEST_URI} !(\.gif|\.jpg|\.png|\.css)$ [NC]
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)$ test.php?controller=$1&action=$2 [L]
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)/([^/]*)$ test.php?controller=$1&action=$2&$3 [L]
My re-write code is working fine and the URLs are coming out as intended, however even if I request an image, the URL is still being re-written. It appears that my RewriteCond is being ignored, anyone any suggestions as to why this might be?
The RewriteCond only applies to your first RewriteRule, it should be reproduced for the second rule. However, I think that is better to add a non-rewriting rule, before, to exclude existing stuffs.
# Do nothing for files which physically exist
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
# your MVC rules
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)$ test.php?controller=$1&action=$2 [L]
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)/([^/]*)$ test.php?controller=$1&action=$2&$3 [L]
The rewriteCond rule is only applied for the next RewriteRule.
So you need to at least repeat the rewriteCond for your seconde RewriteRule.
No there is certainly better things to do.
For example a usual way of doing it is to test that the url is matching a real static ressource. If all your php code is outside the web directory (in libraries directory, except for index.php) then all styatic ressources available directly on the the document root can only be js files, css files, or image files.
So this is the usual way of doing it:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)$ test.php?controller=$1&action=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-z]+)/([a-zA-z]+)/([^/]*)$ test.php?controller=$1&action=$2&$3 [L]
But this is a starting point. We could certainly find something to avoid doing 2 rules for this (maybe I'll have a look later)

.htaccess on specific filetypes

I have some magic stuff in my htaccess. It works very well but I don't know how
RewriteRule ^[^_+/]. index.php
I think it says that all requests should go through index.php no matter which directory the visitor ask for. So far so good. However images, css files, js files etc should of course not be parsed in index.php. Can I exclude certain directories from the above rule? Like /img, /css and /js
Other suggestions?
Thanks in advance
you can exclude existing files and directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
by placing this before your rule
You can avoid requests to certain paths by using a simple RewriteCond...
RewriteCond ${REQUEST_URI} !^css
RewriteCond %{REQUEST_URI} !^img
RewriteCond %{REQUEST_URI} !^js
# or alternatively just
RewriteCond ${REQUEST_URI} !^(css|img|js)