mod_rewrite trouble - php

So I'm using a simple rewrite rule like:
RewriteEngine On
RewriteRule ^foo/?$ foo.php [NC,L]
It redirects perfectly to foo.php, but it seems like all links and images in foo.php are being taken from folder foo on the server which doesn't exist. For instance, 1.png will now be foo/1.png or index.html will now be foo/index.html. So my question is: is there any way to make thing right without changing paths to the files in foo.php?

Your visitors' browsers see the current page as being at /foo/, thus all relative URLs will be resolved under /foo/. You will need to set the base URL, or update all your relative URLs to point to your site root (e.g. do not use relative/path/url.jpg but /relative/path/url.jpg).

In your code you should provide a rewrite rule for your resources (images, css, etc...) or add conditions for real files / folders like...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
The two RewriteCond lines test to see if the requested URL points to an actual real directory (the !-d part), and the second one tests if it's a real file (!-f)
In the future, you can easily debug your mod_rewrite stuff by adding this two lines to your .htaccess file:
RewriteLogLevel 3
RewriteLog "/path/to/a/file.log"

2 simple ways
absolutize the references as suggest by Ianzz
remove the foo path for referenced object still using htaccess
RewriteRule ^foo(/.*.(jpg|html|gif|css))$ $1 [L]
I prefer the 2nd solution because the htaccess do the mess and htaccess fix the situation, and no changes to your code are needed.

Related

htaccess friendly URL rewrite rule

I have recently change my hosting and i need a htaccess rewrite rule for my files. I tried many examples but no one really works for my case. I have never been really good in htaccess and on my older hosting i didn't really need anything it just worked but here is not. Basically i want that my PHP files are without extensions and treated like a directory. So for example i have a URLs like these:
www.domain.com/file1/{id}/{nick}
So for example:
www.domain.com/myfile1/104/username
www.domain.com/myotherfile/455/nick
File1 in this case is a PHP file and {id} and {nick} are changable. I have this structure on my entire site for many other PHP files etc. So if possible i want one universal rule for all files. I tried with htaccess to remove php extenstion etc but all I got is 404 error. Also URL in browser should stay friendly without PHP extension. So in my case if i rewrite my URL manually in:
www.domain.com/file1.php/{id}/{nick} it worked but i don't want to change all the links etc on my website. So all i want is to hide PHP extension and treat PHP files as directory.
Thanks
You can use this single and generic front controller rule in site root .htaccess:
AcceptPathInfo On
DirectoryIndex index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([\w-]+)/(.*)$ $1.php/$2 [L]

.htaccess -- hide dir name in url while keeping folder structure

I have a site with files contained in a /pages/ dir.
I'm trying to hide the /pages/ directory from URLs but still have them in the directory, so basically I am trying to achieve this:
www.example.com/sub/
should load:
www.example.com/pages/sub/
or
www.example.com/sub/file.php
should load:
www.example.com/pages/sub/file.php
-- the aim here is to remove /pages/ from all urls
thanks in advance
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ pages/$1 [QSA,L]
If file or directory doesn't exist, then try in pages folder.
QSA adds url parameters if any (like ?param1=val1&param2=val2)
Apache Re-write: http://httpd.apache.org/docs/2.0/misc/rewriteguide.html
Learn it.
Live it.
Hate it?
edit: its a first in first evaluated, last in last evaluated process, so be considerate when specifying rules, as even if one is established correctly, a broader, more general one which also meets the same pattern (depending on wildcards) has the chance to usurp the prior ( think CSS declaration squashing, if you're familiar with that )

.htaccess mod_rewrite does not work with two parameters on localhost

I would like to have clean URLs in my projects. So I've written these codes in a .htaccess file.
RewriteEngine On
Options +FollowSymLinks
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ index.php?page=$1&id=$2 [NC,QSA,L]
RewriteRule ^([^/\.]+)/?$ index.php?page=$1 [NC,QSA,L]
But it does not work completely when I'm trying to work with it locally.
Imagine that I have a directory myproject in htdocs (www) in my local web server path and other files are stored in this folder. Now I can see the project if I go to localhost/project.
Now I want to work with URLs.
It works well if I have only one parameter in URI like localhost/myproject/tours. But if I have 2 parameters like localhost/myprojects/tours/inside, it seems that all css, js and images files go away. I've also added RewriteBase /myproject to .htaccess file, but nothing solved.
What is my mistake? I need a solution that works on both remote and local server.
First of all, see my response on your other question about your code: Why .htaccess mod_rewrite does not show a real directory
Now, RewriteBase won't solve your problem about css/js/images etc. It's only for htaccess and it defines the base path when a rule is rewritten.
One common way to avoid this problem is to add in all your files a base url right after <head> html tag.
For you, it would be: <base href="http://localhost/myproject/" />
Otherwise, if you reach localhost/myprojects/tours/inside then your css/js/images links will be resolved as localhost/myprojects/tours/inside/__here__ because the default base path here is the current directory (/myproject/tours/inside/) and this is not what you want
Edit: if that's the case, don't forget to remove leading slashes from your css/images/javascript html links
The browser will build absolute URL paths out of your relative URL paths by looking at your made up context of /myprojects/tours. You may need to strip one or two levels of that prefix off to find the real path.
The access log will show you plain as day what relative URL's come in when you use the old and new URLs.

How to redirect subfolders to read all codes from the main directory? similar source codes in subfolders but different contents

I'm developing a website which has three sub folders in the main directory as /a/, /b/ and /c/. Contents in main directory like site.com, site.com/a/, site.com/b/ and site.com/c/ are different; however, the codes and files are completely similar. In order to reduce the volume of the codes, I want to find a way to delete all code files in my sub folders and so all requests to be responded by the main directory files while I keep the sub folders. Could you please give me your opinion about changing the index.php, .htaccess or etc to solve this problem?
You can do this, for example:
RewriteEngine On
RewriteRule ^(a|b|c)/(.*) $2?folder=$1 [L,QSA]
This will make all requests to a/smth, b/smth, c/smth be rewritten to smth (in the root directory) and a/b/c passed as query-string parameter 'folder'.
However, when you access static files like this, a/image.png, b/image.png (for instance) are still considered different uris - and as such will be downloaded separately by the browsers (instead of caching). So you should consider treating resources in a different way. for example, make a separate folder for static resources and address it directly from each subfolder.
For more information, read mod_rewrite manual
Make sure sure there is not .htaccess in /a/ OR /b/ OR /c/ directories
Place this rule in root .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1 -f
RewriteRule ^[abc]/(.+)$ /$1 [L,NC]

RewriteRule trigger 404 when given too many arguments

The site I'm building at the moment is made of two main parts: The side which the general public can access, and the admin side which only authorised people can access.
It's built with basic templating such that the different sections are accessed as follow (Using RewriteRules).
Public:
http://localhost/about should be rewritten to http://localhost/index.php?page=about
Admin:
http://localhost/admin/manage-users should be rewritten to http://localhost/admin/index.php?page=manage-users
All URLs only ever have one argument. That is, public will always be localhost/PAGE and admin will always be localhost/admin/PAGE.
At the moment, I have the following .htaccess file:
RewriteEngine on
RewriteRule ^admin/([^/.]+)/?$ /admin/index.php?page=$1 [L,NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?page=$1 [L,NC]
This seems to work properly when you construct the URL correctly. For example, if I navigate to localhost/about or localhost/admin/manage-users both pages load correctly. But if I go to localhost/about/blah or localhost/admin/manage-users/blah, the pages load, however the CSS is non-existant. Looking at the developer tools in Chrome, it appears that this is because it's trying to load the CSS file from the directories localhost/about/css/ and localhost/admin/css/ respectively, due to the style sheet being linked to the page with a relative path. (In reality, localhost/css/ is the directory it is actually located in.)
So even though the RedirectRule ignores any extra arguments in the URL, it is trying to load relative paths with respect to the last "directory" provided in the URL.
Is there any way to completely ignore any extra ../.. arguments? Or, even better, trigger a 404 when too many arguments are provided?
UPDATE: I have just discovered that the problem is actually a lot more complex than I previously thought. As my pages only had dummy data to test out the templating files, I didn't notice it until now.
It appears than when you navigate to localhost/admin or localhost/admin/manage-users it is loading from the http://localhost/admin/index.php file, but when you navigate to localhost/admin/manage-users/blah is reverts back to loading the http://localhost/index.php file. This makes me think that there is something I need to change in the RewriteRule, though I have no idea what.
It is better in long term to use 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 /.
But in order to avoid making changes to your website in-mass you can use these rules to fix your css/js/images links:
RewriteEngine on
# fix CSS/js/images links
RewriteRule (?:^|/)((?:css|js|images)/.+)$ /$1 [L,R=301]
RewriteRule ^admin/([^.]+)/?$ /admin/index.php?page=$1 [L,NC,QSA]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /index.php?page=$1 [L,QSA]
Don't forget to replace first rule with your actual css/js/images directories.
You need to either make all of your links absolute URLs (e.g. href="/css/style.css") or add a relative URL base to the header of your page:
<base href="/" />

Categories