My .htaccess looks like this:
RewriteEngine on
RewriteCond %{REQUEST_URI} !(\.gif)|(\.jpg)|(\.png)|(\.css)|(\.js)|(\.php)|(\.swf)|(\.xpi)|(\.ico)|(\.src)$
RewriteCond %{REQUEST_URI} ^(.*)$
#RewriteCond %{REQUEST_FILENAME} ! -f
RewriteRule (.*)$ view.php?picid=$1 [L]
Problem is that when I visit www.example.com, it’s sending me to view.php. There is an index.php file in my root directory. How do I get .htaccess to ignore the index file?
Try this rule:
RewriteCond %{REQUEST_URI} !.*\.(gif|jpg|png|css|js|php|swf|xpi|ico|src)$ [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) view.php?picid=$1 [L]
The important changes I made:
The regular expression in your first RewriteCond is faulty. The $ anchor is only applied to the last option in the alteration.
The second RewriteCond directive is useless.
The third RewriteCond that’s commented out will do just what you want: Check if the requested URI path can be mapped to an existing file.
Altered the quantifier from zero or more to one or more characters. That will exclude the empty URI path when / is requested.
Remove the # from the fourth line and remove the space between the exclamation mark (!) and the -f
RewriteCond %{REQUEST_FILENAME} !-f
This line says that if the file doesn't already exist on the server, in this case, index.php, then continue and do the rewrite that follows.
Also check you've got both a DirectoryIndex as well as checking against any valid directories.
DirectoryIndex index.php
RewriteCond %{REQUEST_FILENAME} !-d
Which would leave you with this cleaner version:
DirectoryIndex index.php
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ view.php?picid=$1 [L]
This first sets up index.php as the default file. Then you run the Rewrite engine, and if the requested file does not already exist on the server as either a file or a directory, will pass things on to the view.php file and run its magic.
Related
It is quite popular question, but there is some distinction in my case that makes all more difficult.
Apache2 web server, Yii2 framework with prettyUrl turned on.
Here is initial .htaccess file, provided by Yii2:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
There is /docs web directory. And I would like to get files from it if they are exist and redirect to /docs-generator/create?file=<file_name> if the file doesn't exists.
So, I have added a rule:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/docs
RewriteRule ^docs/([\w-_.]+) http://kz_proj.test/docs-generator/create?file=$1 [L]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
It's works but quite strange... First of all, I can't remove my test hostname from http://kz_proj.test/docs-generator/create?file=$1. It doesn't work without full name. The second one is about ^/docs and ^docs/([\w-_.]+) without the leading character. Why first part of these rules can't be the same in my case?
I guess something wrong with the rules...
You can use:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^docs/([\w-_.]+) /docs-generator/create?file=$1 [L,R=301]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule ^ index.php
It works with the domain name because it is necessarily a redirect in this case, but not without. I added [R=301] to force the redirection.
No need to add RewriteCond %{REQUEST_URI} ^/docs
because the test is the same with RewriteRule ^docs
And why first part of these rules can't be the same in your case ?
REQUEST_URI always start with a /
and RewriteRule test path never start with a / in .htaccess (why????)
In my app, I have the srcs of many images like this:
path/other-path/my-image.jpg
This can get long and can expose some of my file structure to the outside world.
What can I do in .htaccess to redirect a given file extension to a directory?
i.e. my image src is simply "my-image.jpg", .htaccess sees that is a .jpg file and redirects to the folder "www.site.com/my-jpgs/" were "my-image.jpg" resides, thus loading the image.
Here is what I have at the moment:
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/importers
RewriteCond %{REQUEST_URI} !\.(gif|jpg|png)$
RewriteRule ^(.*)$ public_html/index.php
RewriteBase /
# Ignore rule if the real path exists, use that instead.
RewriteCond %{REQUEST_FILENAME} !-f
# Only use the filename and extension.
RewriteRule (.[^/]*)\.(gif|jpg|png) public_html/images$1.$2 [R,L]
I've sort of got it working, except the browser makes two requests that look like this:
Request URL:http://www.view.com/activity/enquiry/dropdown-btn.gif
Request URL:http://www.view.com/public_html/images/dropdown-btn.gif
The second being correct, how do I correct this so it doesn't make the first incorrect request?
Ordering of rewrite rules is very important in .htaccess. Your problem is incorrect ordering of your rule. You need to move last rule to the top just belowRewriteEngine Online to have external redirect before sending everything off toindex.php`:
Options +FollowSymLinks
IndexIgnore */*
RewriteEngine On
RewriteBase /
# Ignore rule if the real path exists, use that instead.
RewriteCond %{REQUEST_FILENAME} !-f
# Only use the filename and extension.
RewriteRule ^(?:[^/]+/)*([^.]+\.(?:gif|jpe?g|png))$ images/$1 [R,L,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/importers
RewriteCond %{REQUEST_URI} !\.(gif|jpe?g|png)$
RewriteRule ^ index.php [L]
My apps' urls are like this: http://domain.com/projects/project-name/
My app's file system is like this:
htdocs/projects/project-name/
L index.html
L img/image1.png
L img/image2.png
L img/...
I need to send requests like http://domain.com/projects/project-name/ to
htdocs/index.php?section=$1&item=$2
But they display the project-name/index.html file instead.
Here is what i tried:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule . - [L]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2&%{QUERY_STRING} [NC,L]
Obviously, the RewriteCond %{REQUEST_FILENAME} -frule is the culprit. But i need to let the server serve the static img files. How can I tell it to let all file requests but rewrite the project folder's default index.html?
It should work, I am providing a slightly modified version of your rule with complete .htaccess to be placed in DOCUMENT_ROOT/.htaccess:
DirectoryIndex index.php index.html
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?section=$1&item=$2 [L,QSA]
Edit: Misunderstood the question.
You want to rewrite /projects/project-name/ to index.php?... I am also assuming you'll want to be able to request files from within project-name:
RewriteEngine on
RewriteRule ^([^/]+)/([^/]+)(/(index[^/]+)?)?$ /index.php?section=$1&item=$2 [QSA,NC,L]
If being able to request files from the project-name subdir isn't important, just remove (/(index[^/]+)?) and replace it with /. The (/(index[^/]+)?) assumes your DirectoryIndex files start with "index".
Meh.
Consider enabling the mod_rewrite log to analyze how it is applying your conditions and patterns. Within the server or vhost scope (not htaccess) add:
LogLevel warn rewrite:trace6
The LogLevel directive can enable logging for mod_rewrite which will be written to your defined ErrorLog. trace6 is the highest mod_rewrite log level before you get into hex output. Be sure to comment out or remove LogLevel when you're done.
Original, unrelated answer (ignore):
You need to negate files, of which right now you are not, notice the use of !:
RewriteCond %{REQUEST_FILENAME} !-f
Most importantly, your RewriteCond will not affect your second RewriteRule. It is only applied to the first RewriteRule (in your case RewriteRule . - [L]):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2&%{QUERY_STRING} [NC,L]
And you may also choose to negate directories:
RewriteCond %{REQUEST_FILENAME} !-d
I'd also consider using the QSA (query string append) flag instead of appending QUERY_STRING:
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2 [QSA,NC,L]
In summary:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?section=$1&item=$2 [QSA,NC,L]
This is an extract of my .htaccess file:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ /a/?s=$1 [L,QSA]
I want it to apply only to directories in the site's root /something /whatever /example etc. not to /something/a or /whatever/b
How can I add this extra rule so it's more precise?
Try changing the expression from ^(.*)$ to ^([^/]+)/?$, which means: the entire thing must not contain a / unless it's at the end. Note that the URI is stripped of its leading slash when you match against it in htaccess files.
I have a install of SocialEngine currently and all urls are processed by .htaccess file that redirects through to the socialengine.php file and processes nice URLs etc.
I am wanting to stop example.com/ been redirected through to the script as I am wanting to put a different index page there. So I want my .htaccess file to process every other file it cant find through the socialengine.php script but keep the root file going to index.php.
So if it’s .com/ it goes to index.php and if it’s anything else it’s processed through the socialengine.php.
Below is my .htaccess file that requires alteration.
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
# Get rid of index.php
RewriteCond %{REQUEST_URI} /socialengine\.php
RewriteRule (.*) socialengine.php?rewrite=2 [L,QSA]
# Rewrite all directory-looking urls
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*) socialengine.php?rewrite=1 [L,QSA]
# Try to route missing files
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} public\/ [OR]
RewriteCond %{REQUEST_FILENAME} \.(jpg|gif|png|ico|flv|htm|html|php|css|js)$
RewriteRule . - [L]
# If the file doesn't exist, rewrite to index
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ socialengine.php?rewrite=1 [L,QSA]
</IfModule>
Thanks in advance for any replies.
Put the code below straight after RewriteEngine On.
RewriteCond %{REQUEST_URI} ^/$
RewriteRule .* - [L]
Explanation: The first line matches a request to http://example.com/ (REQUEST_URI contains / in this case). The second line passes the request untouched (note the -)
References:
http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule