Using mod_rewrite, I want to look for all requested files in an assets directory, and otherwise fallback to index.php for API calls. This is my .htaccess.
RewriteEngine on
RewriteRule ^.+\.[^/]+$ assets/$1 [L]
RewriteRule .* index.php
Asset files are determined by whether the last last url segment has a file extension, which means a dot without following slashes. I already tested the regex at regexpal and it seems to work fine.
Unfortunately, all request result in a 500 Internal Server Error using these rewrite rules. I know that mod_rewrite is set up correctly, since omitting the second line works as expected.
Try these rules:
RewriteEngine on
# rewrite to assets/file if file exists in assets dir
RewriteCond %{DOCUMENT_ROOT}/assets/$1 -f
RewriteRule ^(.+?\.[^/]+)/?$ assets/$1 [L]
# otherwise rewrite to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^assets/ index.php [NC,L]
You need to add a condition to prevent the rewrite engine from looping:
RewriteEngine on
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule ^.+\.[^/]+$ assets/$1 [L]
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule .* index.php
The rewrite engine loops until the URI stops changing, and since .* matches index.php as well, it'll continue to loop through that rule until the internal recursion limit is reached you get a 500 error.
Additionally, you can add conditions that won't reroute existing files or directories:
RewriteEngine on
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule ^.+\.[^/]+$ assets/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php
Related
I am trying to use Apache mod_rewrite. The first thing I did was to rewrite my url to an index.php file which was working fine. But I thought I should remove the trailing slash(es) too because I would prefer this to be handled by Apache instead of my PHP router.
Here's the whole content of my .htaccess file:
RewriteEngine on
# one of the attempts to remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.*)/+$
RewriteRule ^(.*)/+$ $1 [R=301,L]
# This is the rewriting to my index.php (working)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [L]
The issue:
I read several questions about trailing slash removal but I could not find a working answer for me:
For every answer I tried, I was able to reach my PHP router index.php (located in Phunder\public\) without trailing slash:
// Requested URL | No redirection
http://localhost/projects/Phunder/public/home | http://localhost/projects/Phunder/public/home
But when requesting the same page with a trailing slash I get redirected with the absolute path included:
// Requested URL | Wrong redirection
http://localhost/projects/Phunder/public/home/ | http://localhost/C:/xampp/htdocs/projects/Phunder/public/home
Other informations:
I always clear my cache while testing
Changing my last RewriteRule to RewriteRule ^(.*)/?$ index.php?/$1 [L] results in a 404 Error with URL having a trailing slash.
The actual wrong redirection results in a 403 Error
I'm a beginner with mod_rewrite I'm not always understanding what I try (sadly). Is there something I missed or misused ? What should I do to get the expected behaviour ?
Redirect rules need either absolute URL or a RewriteBase. You can extract full URI from %{REQUEST_URI} as well like this:
RewriteEngine on
# one of the attempts to remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.+)/+$
RewriteRule ^ %1 [R=301,NE,L]
# This is the rewriting to my index.php (working)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [L,QSA]
I want to 'catch' an URL with .htaccess rewriterule. How can I add backslashes to the rewriterule?
For example:
http://www.example.com/page1 -> index.php?page=page1
http://www.example.com/page1/subpage1 -> index.php?page=page1/subpage1
As you can see, I want the backslash between 'page1' and 'subpage1' IN the rewriterule, because the path can be variable (more subpages).
I tried this:
RewriteRule ^(.*)$ /index.php?page=$1 [NC,L,QSA]
But then I get an Internal Server Error.
Thanks in advance!
You get an Internal Server Error because your rule introduces an infinite redirect loop.
Here is what you want
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?page=$1 [NC,L,QSA]
It checks if the url is not a physical folder/file before rewriting it internally
I want URL like this: localhost/dir/images/pic1.jpg
to be rewriten to: localhost/dir/subdir/index.php?folder=images&picture=pic1.jpg
So i put really simple .htaccess file in localhost/dir/:
RewriteEngine On
RewriteRule ^(.*)/(.*)$ subdir/index.php?folder=$1&picture=$2 [L]
and expect to get folder='images' and picture='pic1.jpg' in localhost/dir/subdir/index.php but instead I have folder='subdir' and picture='index.php'
Strange thing is that when i modify .htaccess file to call index.php from the same directory (not from 'subdir') it works well:
RewriteEngine On
RewriteRule ^(.*)/(.*)$ index.php?folder=$1&picture=$2 [L]
I get folder='images' and picture='pic1.jpg' in localhost/dir/index.php script
That is happening because your rewrite rule is looping and matching target string subdir/index.php with the pattern .*/.*.
Use this condition to stop the loop:
RewriteEngine On
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/(.*)$ subdir/index.php?folder=$1&picture=$2 [L]
I need to create rewrite in nginx as is done in my .htaccess and there are some lines which I don't completely understand.
DirectoryIndex index.php
RewriteEngine on
RewriteCond % !-f
RewriteRule ^(.*)/$ ?path=$1 [QSA,L]
Can someone explain it to me?
RewriteCond % !-f seems incorrect rule condition and is always evaluating to true.
This rule:
RewriteRule ^(.*)/$ ?path=$1 [QSA,L]
Is matching any URI with trailing slash and internally rewriting to /?path=uri-without-slash
So for ex: an URI /foo/ will be rewritten to /?path=foo
QSA - Query String Append
L = Last rule
Reference: Apache mod_rewrite Introduction
UPDATE: Change that incorrect condition to:
# request is not for a file
RewriteCond %{REQUEST_FILENAME} !-f
# request is not for a directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ ?path=$1 [QSA,L]
It means if the request isn't to a file, then rewrite everything before a trailing / into index.php?path= followed by what was previously matched.
It should be the last rule (L) and it should append the query string (QSA), as opposed to discarding it because of the replacement's query string.
I never want index.php to show up in my URL, even if the user inputs it. Is this possible?
This is variation whatever after several tries. I've come close a few times but this is where it's at for now.
RewriteEngine On
RewriteBase /sub-dir/
RewriteCond %{REQUEST_URI} index\.php$ //If URL ends in index.php
RewriteRule (.*)index\.php $1 //Somehow remove index.php from the url
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
Currently I have permalink set up where if the user enters domain.com/sub-dir/my-perma-lin/ it generates a string on the page based on my-perma-link to look like My Perma Link. What I'd like is if the user submits any URL ending in index.php it just removes that from the URL but leaves everything else as is.
domain.com/sub-dir/index.php --> domain.com/sub-dir/
domain.com/sub-dir/my-perma-link/index.php --> domain.com/sub-dir/my-perma-link
I've written quite a few rules in http://htaccess.madewithlove.be/ that work perfectly but when I upload it (to Dreamhost) nothing works.
This for example should work according to the the tester
RewriteEngine On
RewriteBase /sub-dir/
RewriteCond %{REQUEST_URI} \.php //Not needed but thought it would/should help
RewriteRule (.*)(index\.php)+ $1 [L,R=301,NC]
But it just removes everything after /sub-dir/
I'm either missing something super obvious or it's not possible ...
You need to add some flags to your rule:
RewriteEngine On
RewriteBase /sub-dir/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php(\?|\ )
RewriteRule ^ /%1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
You can ditch the RewriteCond %{REQUEST_URI} index\.php$ condition, as that's being checked by the regex in the RewriteRule. You need to include a $ at the end of the regex, and include the flags L to stop rewriting and R=301 to redirect.