I've just started trying to figure out how to make clean URLs with .htaccess but it seems I've run into a wall straight away... I've got the following simple .htaccess:
RewriteEngine on
RewriteRule ^([a-zA-Z0-9-]+)$ index.php?id=$1 [L]
RewriteRule ^([a-zA-Z0-9-]+)/$ index.php?id=$1 [L]
It mostly works as expected: mysite.com/somepage goes to mysite.com/index.asp?id=somepage etc.
Except when the id is 'images'. When I try mysite.com/images it displays: mysite.com/images/?id=images (though the page still loads fine)
By the way mysite.com/images/ (with a slash) works ok. I've been searching for a solution for the last few days and that's the best I could get.
Since images is a directory Apache's mod_dir module adds a trailing slash after your rewrite rules. You can turn this feature off and add a trailing slash yourself:
DirectorySlash Off
RewriteEngine on
# add a trailing slash
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,R=302]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([a-zA-Z0-9-]+)/?$ index.php?id=$1 [L,QSA]
Related
I'm sorry if my question is unclear. I rewrite rule url by htaccess and it worked. So i have a problem when i try to link path of the existing folder.
My problem:
Redirect url: 'http://localhost/folders'
But it display: 'http://localhost/folders/?link=folder'
So, I don't want it show '?link=folder'. It not show '?link=folder' with Redirect url: 'http://localhost/folders'
My htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^$ index.php [L]
RewriteRule ^([^/]*)/$ index.php?link=$1&%{QUERY_STRING} [L]
RewriteRule ^([^/]*)/([^/]*)/$ index.php?link=$1&action=$2&%{QUERY_STRING} [L]
RewriteRule ^([^/]*)/([0-9]+)/([^/]*)/$ index.php?link=$1&id=$2&action=$3&%{QUERY_STRING} [L]
RewriteRule ^([^/]*)$ index.php?link=$1&%{QUERY_STRING} [L]
RewriteRule ^([^/]*)/([^/]*)$ index.php?link=$1&action=$2&%{QUERY_STRING} [L]
RewriteRule ^([^/]*)/([0-9]+)/([^/]*)$ index.php?link=$1&id=$2&action=$3&%{QUERY_STRING} [L]
RewriteRule !^(public/*|folder/*|index\.php) [NC,F]
Please, someone tell me how to fix. I'm sorry if my english is bad.
Your problem maybe to do with the DirectorySlash. If "folders" is a physical directory on the filesystem and you request http://localhost/folders (no trailing slash) then mod_dir "fixes" the URL by 301 redirecting to http://localhost/folders/ (with a trailing slash).
This mod_dir behaviour conflicts with the following rule that appends the ?link=folders quesy string.
RewriteRule ^([^/]*)$ index.php?link=$1&%{QUERY_STRING} [L]
This "rewrite" will be turned into an external "redirect" by mod_dir.
You can try preventing mod_dir from appending the trailing slash on directories with the following directive at the top of your .htaccess file:
DirectorySlash Off
However, you now need to manage all the trailing slashes yourself, which may not be trivial.
However, instead of the above, I would simply include a trailing slash on the URL to begin with and only match URLs that have the trailing slash, rather than both (you are duplicating your directives).
I consider myself reasonably competent with PHP. I am, however, completely and totally lost when it comes to mod_rewrite.
I have a URL structure that works like the following:
http://site/something/something-else/the-actual-page/
that redirects to:
http://site/index.php?page=the-actual-page
It's only ever the final 'folder' that is passed to the script. The preceding 'folders' (if any) are for SEO and structure purposes.
If there is a preceding folder "promotion" then it redirects to a separate file. This is along the lines of:
http://site/promotion/campaign-name/
redirecting to
http://site/promotion.php?campaign=campaign-name
I'm using the following code to achieve this:
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^promotion/(.*)/$ promotion.php?params=$1 [L]
RewriteRule ^(.*) index.php?page=$1 [L]
</IfModule>
This works as intended, with links redirecting properly EXCEPT when there is no trailing slash. For example
http://site/something/thepage/
will work, whilst
http://site/something/thepage
will not.
To solve this problem I'm attempting to set up a 301 that redirects any URI without a trailing slash to a URI with a trailing slash.
The code below (placed above the other rules) works to a degree, but I lose folder data.
Code:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1/ [L,R=301]
The problem?
http://site/something/thepage
redirects to
http://site/thepage/
I'm afraid all the googling in the world is not helping me, as I cannot wrap my brain around mod_rewrite at all!
Appreciate any help.
You'll be better off using this:
RewriteEngine On
RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
# ... your other rerites
If you'd like to reverse it and strip the trailing slash instead, then use this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
You'd then need to change your rewrite accordingly:
RewriteRule ^promotion/(.*)$ /promotion.php?params=$1 [L]
This is my current .htaccess file:
RewriteEngine on
# remove trailing slash
RewriteRule (.*)(/|\\)$ $1 [R]
# everything
RewriteRule ^(.*?)$ /handler.php?url=$1 [L,QSA]
However, this doesn't work, it throws a 500 Internal Server Error
My previous .htaccess file looked like this:
RewriteEngine on
# remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*)(/|\\)$ $1 [R]
# everything
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*?)$ /handler.php?url=$1 [L,QSA]
And it worked, except for specific files. However, now I'd like the specific files to redirect into the handler as well. Is there a way to use RewriteRules without the RewriteConds?
Without RewriteCond for file check you can tweak your regex like this:
RewriteEngine on
RewriteBase /
# remove trailing slash for non directories
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+?)/$ $1 [R,L]
# every request not for handler.php
RewriteRule ^((?!handler\.php$).*)$ handler.php?url=$1 [L,QSA]
With the help of CBroe and Sumurai8, I was able to fix the problem on my own. The problem was not that you can't have RewriteRules without RewriteConds, but that if you rewrite every url into a single file, it will rewrite requests to that specific file to itself once more, creating an infinite loop.
The new .htaccess:
RewriteEngine on
# remove trailing slash
RewriteRule (.*)(/|\\)$ $1 [R,L]
# everything
RewriteCond %{REQUEST_URI} !^/handler.php$
RewriteRule ^(.*?)$ /handler.php?url=$1 [L,QSA]
Relevant resource: Request exceeded the limit of 10 internal redirects
I'm trying to remove the trailing slash of all urls. Whatever htaccess script lines I try, it always redirects to what seems the full server directory.
example.com/XYZ/ weirdly redirects to example.com/customers/b/7/3/example.com/httpd.www/XYZ – Not found.
Basically, I'm not using any subdirectories but getting data out of a database according to what's the last string after the last slash. So the "Not found" error is ok, because there actually isn't an existing folder.
I'm new to htaccess, so I was just trying out whatever lines I found.
Rewrite so that anything opens index.php and not a folder (which works fine without trailing slash, Engine is on):
RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?$1
RewriteRule ^([a-zA-Z0-9_-]+)/$ index.php?$1
I failed by using this to remove the slash:
RewriteRule ^(.+)/$ /$1 [R=301,L]
So basically what I'm trying to do is:
Open any url as index.php. For example example.com/XY doesn't actually redirect but show/open index.php (I think I achieved that with above two lines)
While doing so, I'm trying to also remove the trailing slash from e.g. example.com/XY/, so example.com/XY and example.com/XY/ both show/open index.php
Thanks for your wisdom!
You can do:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s(.+?)/+[?\s]
RewriteRule ^(.+?)/$ /$1 [R=301,L]
RewriteRule ^([\w-]+)/?$ /index.php?$1 [L,QSA]
What I'm trying to achive is to have all urls on my page look like http://domain.com/page/, no extensions, but a trailing slash. If a user happends to write http://domain.com/page or http://domain.com/page.php it will redirect to the first url. After some googling i found this code, and it's close to working, but when you leave out the trailing slash in your request the url becomes something like http://domain.com/Users/"..."/page/ and therefor returns a 404.
My .htaccess looks like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ $1.php [L]
RewriteCond %{REQUEST_FILENAME} !(.*)/$
RewriteRule (.*)/$ $1.php [L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]
I've been trying to add an additional rule but I really don't get any of this and I haven't been able to find any answers.
For a scenario like this one, the .htaccess author has to consider both what the browser URL bar should display and what file the web server should return/execute. Note also that each external redirect starts the processing of the rewrite directives over.
With that in mind, start by taking care of which file is returned when the URL is in the correct format:
RewriteEngine on
RewriteRule ^/?$ /index.php [L]
RewriteRule ([^./]+)/$ /$1.php [L]
Then, deal with URLs with no trailing slash by redirecting them with [R=301]:
RewriteRule ^/(.*)\.[^.]*$ http://www.example.com/$1/ [R=301,L]
RewriteRule ^/(.*)$ http://www.example.com/$1/ [R=301,L]
Note that the first of these two rules should also take care of the case where there is a filename (like something.php) but also a trailing slash by eliminating the filename extension and re-adding the slash.
Keep in mind that, if your internal directory structure does not match what the web server is serving (as is often the case in shared hosting scenarios), you will likely need to add a RewriteBase directive immediately after the RewriteEngine directive. See the Apache docs for an explanation.