I have created a php framework that works well on an IIS server and the RewriteRules work perfectly well with web.config.
But the same rules don't work on an apache server with .htaccess and I don't understand why... here they are:
Options +FollowSymlinks
RewriteEngine On
RewriteRule picture/([a-zA-Z0-9]+)/([a-zA-Z\-0-9/]+).(jpg|png|gif) app/Src/$1Bundle/public/img/$2.$3 [L]
RewriteRule picture/([a-zA-Z\-0-9/]+).(jpg|png|gif) public/$1.$2 [L]
RewriteRule scripts/([a-zA-Z0-9]+)/(js|css|typo)/([a-zA-Z\-0-9=\./]+).(js|css) app/Src/$1Bundle/public/$2/$3.$4 [L]
RewriteRule scripts/(js|css|typo)/([a-zA-Z\-0-9=\./]+).(js|css) public/$1/$2.$3 [L]
RewriteRule scripts/(fonts)/([a-zA-Z\-0-9=\./]+).(eot|svg|ttf|woff) public/$1/$2.$3 [L]
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
I have tried this solution (and many others)(RewriteRule Last [L] flag not working?), but it hasn't worked.
RewriteCond %{ENV:REDIRECT_STATUS} != 200
I have run out of ideas...
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
Your last rule (that rewrites everything) runs unconditionally, so this is going to result in a rewrite loop (500 error response).
At the very least you need to prevent requests for index.php being further rewritten. For example:
RewriteRule ^index\.php$ - [L]
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
But you presumably also want your static resources to remain directly accessible as well? So, excluding requests that map to physical files and directories is a common requirement. For example:
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
RewriteRule picture/([a-zA-Z0-9]+)/([a-zA-Z\-0-9/]+).(jpg|png|gif) app/Src/$1Bundle/public/img/$2.$3 [L]
You have also omitted any start-of-string anchors (^) and end-of-string anchors ($) from your RewriteRule patterns. This could potentially result in matching too much - even matching the rewritten URL - another loop. You need to be more specific in your pattern matching.
Related
I'm trying to get all my vlogs in a folder to run off a single PHP vlog page inside it. I'm using a simple redirect after I do all my strip/force housekeeping. But it 404's. What am I missing?
RewriteEngine on
# Follow symbolic links
Options +FollowSymLinks
# Strip www.
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule .* http://%1%{REQUEST_URI} [R=302]
# Force HTTPS:
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule .* https://%1%{REQUEST_URI} [R=302]
# Strip php extension
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([^.]+)$ $1.php [NC]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\ ]+)\.php
RewriteRule ^/?(.*)\.php$ /$1 [R=302]
# Strip trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=302]
#manage vlogs
RewriteRule ^/fol-der-name/(.+)$ /fol-der-name/vlog?url=$1
I tried these and they all fail
RewriteRule ^/fol-der-name/(.*)$ /fol-der-name/vlog?url=$1
RewriteRule ^/fol-der-name/(.+)$ /fol-der-name/vlog?url=%1
RewriteRule ^/fol-der-name/(.*)$ /fol-der-name/vlog?url=%1
The fix was simple. Escape the hyphens on the LEFT SIDE in the last line:
RewriteCond %{QUERY_STRING} ^$ [NC]
RewriteRule ^fol\-der\-name/(.+)$ /fol-der-name/vlog.php?url=$1 [L,NC]
I finally fixed my own error, after a painful day and half, I kid you not, into the minutiae of .htaccess, learning things I didn't want to learn, and frankly don't feel any the wiser for knowing (eg did you know that Apache processes the RewriteCon conditions you write AFTER it processes the RewriteRule's you write?)
Anyway, I commend to all who have drowned in mod_rewrite or htaccess rewrite these 2 stunning pieces from my journey:
a) https://www.301-redirect.online/htaccess-rewrite-generator (this corrected the last line in my code in the question, and actually produced the fix - oh and it's the best .htaccess generator I've come across, and I looked at around 6)
b) https://www.danielmorell.com/guides/htaccess-seo/redirects/introduction-to-redirects (this explains a lot of how redirects should be coded, especially with queries - why use % v $ v slash - the final diagram on the page is worthy of a Nobel prize)
I have two RewriteRules that couldn't work together, each will individually work but when placed together only the toppermost work.
My directory structure: http://localhost/project/sitepages
The pages:
http://localhost/project/sitepages/page1.php?name=pagename
http://localhost/project/sitepages/page2.php?name=pagename&id=pageid&name2=pagename2
How I want the pages to be accessed:
http://localhost/project/pagename
http://localhost/project/pagename/pageid/pagename2
The RewriteRule I use:
RewriteRule ^(.*)$ sitepages/page1.php?name=$1 [QSA]
RewriteRule ^(.*)$ sitepages/page2.php?name=$1&id=$2&name2=$3 [QSA]
.* matches anything to it is obvious only 1st rule works.
You can use these 2 rules:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([\w-]+)/?$ sitepages/page1.php?name=$1 [QSA,L]
RewriteRule ^([\w-]+)/([\w-]+)/([\w-]+)/?$ sitepages/page2.php?name=$1&id=$2&name2=$3 [QSA,L]
I have a page on my website that is getting generated dynamically to list all outlets based on cityf parameter and below is rewrite rule to convert it into SEO friendly URL and it is working pretty well.
RewriteRule ^([^/.]+)/?$ /cityres?cityf=$1 [L]
I have a blog page on my website and .htaccess is as below to convert SEO Friendly URL (http://example.com/title-of-blog)
RewriteRule ^([^/.]+)/?$ /blogdetail?prmn=$1 [L]
Now the problem here i am facing that when someone visits blog page then the link http://example.com/title-of-blog instead of displaying blog detail on the page, displays my Error message that No outlets near title-of-blog.
I got the issue that Apache is not able to identify when to rewrite cityres page and when to rewrite blogdetail page.
Someone suggested that Make sure that each rule has a common prefix (e.g. /blog/page1 and /news/page2). but i did not get that.
Any suggestions here please?
EDIT:
Whole htaccess is as below
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php
RewriteRule ^index\.php$ / [L,R=301]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index
RewriteRule ^index\.php$ / [L,R=301]
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]
# remove .php from URL
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
# remove .html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/.]+)\.html$ /$1 [L,R=301]
ErrorDocument 404 /error-page
ErrorDocument 403 /error-page
RewriteRule ^food-([^-]*)-([^-]*)\.html$ /pdetail?res_id=$1&location=$2 [L]
RewriteRule ^foodies-([^-]*)-([^-]*)$ /pdetail_new?res_id=$1&location=$2 [L]
RewriteRule ^([^/.]+)/([^/.]+)/([^/.]+)/?$ /pdetail_ne?location=$1&res_id=$2&name=$3 [L]
RewriteRule ^blog/([^/.]+)/?$ /blogdetail_fm?prmn=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !cityres
RewriteRule ^([^/.]+)/?$ /cityres?cityf=$1 [L]
Both your rules match the exact same pattern. Therefore, the first rule will always match and the second rule does nothing.
Looking at the first rule:
RewriteRule ^([^/.]+)/?$ /blogdetail?prmn=$1 [L]
This matches http://example.com/title-of-blog as well as http://example.com/city-name
When you look at it, you can tell which needs to be handled by blogdetail and which needs to be handled by cityres, but the regex ([^/.]+) sees them both as exactly the same, and matches both. Your regex doesn't know the difference, so whatever the first rule is, both URL's will get matched by it.
Like you said, someone suggested using a prefix. That way, the regex knows which is which:
RewriteRule ^city/([^/.]+)/?$ /cityres?cityf=$1 [L]
RewriteRule ^blog/([^/.]+)/?$ /blogdetail?prmn=$1 [L]
ANd your URLs will look like:
http://example.com/city/city-name
http://example.com/blog/title-of-blog
If you're really hung up about not adding prefixes, you can remove the second prefix:
RewriteRule ^city/([^/.]+)/?$ /cityres?cityf=$1 [L]
RewriteRule ^([^/.]+)/?$ /blogdetail?prmn=$1 [L]
So that you have:
http://example.com/city/city-name
http://example.com/title-of-blog
EDIT:
Your 500 server error is caused by the rules looping. You need to add a condition so that they won't keep matching:
RewriteRule ^blog/([^/.]+)/?$ /blogdetail?prmn=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !cityres
RewriteRule ^([^/.]+)/?$ /cityres?cityf=$1 [L]
I am redirecting this type of url
http://www.site.com/windows/games/ or http://www.site.com/windows/games
http://www.site.com/windows/software/ or http://www.site.com/windows/software
to
http://www.site.com/windows/ct.php?ct=games
http://www.site.com/windows/ct.php?ct=software
Site structure
wamp/www/Site/windows/ct.php
I am trying this way its redirecting properly but when url has trailing slash at end its rewriting css, js files too.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^windows/([^/]*)/?$ /Site/windows/ct.php?ct=$1 [L]
i.e
this type of url has css and javascript applied.
http://www.site.com/windows/games
but this type of url has no css and javascript applied. (not working with trailing slash).
http://www.site.com/windows/games/
I have tried several syntax like
RewriteRule ^windows/([^/]+)/?$ /windows/ct.php?ct=$1 [L]
RewriteRule ^windows/(^(.[^/]*)/?)$ /windows/ct.php?ct=$1 [L]
RewriteRule ^windows/([^/]*)/? /windows/ct.php?ct=$1 [L]
RewriteRule ^windows/([^/]+)/? /windows/ct.php?ct=$1 [L]
but it didn't work.
Complete .htaccess
Options +FollowSymlinks -MultiViews
RewriteEngine on
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^windows/([^/]*)/?$ /Site/windows/ct.php?ct=$1 [L]
RewriteRule ^[^/]*/[^/]*/(.*\.html) /Site/error/400/ [L]
RewriteRule ^(error) - [L]
RewriteRule ^sitemap\.xml$ sitemap.php [L]
RewriteRule ^rss/(.*?)\.xml$ rss/$1.php [L]
</IfModule>
ErrorDocument 404 /Site/error/404/
Please see and suggest any possible way to do it.
Thanks.
The issue here is that your relative paths break when you add a trailing slash as it introduces two-levels of directory structure while the CSS/JS file paths come out only once ... So, your RewriteRule is actually firing for CSS/JS files as well when resolving 404s for paths like /windows/global/js/js.js. But, the scripts still fail to work because they aren't under /Site and that's where your rule is serving the request from.
So, to fix things without touching the relative URLs or resource locations; add another rule as follows:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^windows/([^/]*)/?$ /Site/windows/ct.php?ct=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^windows/(global/.*)$ /$1 [L] # handles css|js files
The rest of your .htaccess (of course) remains the same.
I use the following rule in .htaccess, but this may be too general:
RewriteRule ^q/([^/]+)/([^/]+)(\/?)$ /path/to/q.php?type=$1&q=$2&{QUERY_STRING} [NC]
This may be better for you:
RewriteRule ^windows(\/?)$ /path/to/windows.php?{QUERY_STRING} [NC]
RewriteRule ^windows/([^/]+)(\/?)$ /path/to/windows.php?type=$1&{QUERY_STRING} [NC]
You will have to change this according to your situation. I haven't tested this, but I hope it is good enough for you to get where you want.
I have an index file that builds content based on n PATH_INFO variables.
Example:
site.com/A/B/n/
should use index.php at either:
site.com/index.php?var1=A&var2=B&varN=n
- or -
site.com/index.php/A/B/n/
instead of:
site.com/A/B/n/index.php || which doesn't exist ||
So far I've tried a number of variations of:
RedirectMatch ^/.+/.*$ /
with no success.
I have an inelegant and unscalable solution here:
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)/?$ index.php?p1=$1 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [NC,L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [NC,L]
Problems with this solution:
Inelegant and unscalable, requires manual line for each subdirectory
Fails with non alphanumeric characters (primarily +,= and &) ex. site.com/ab&c/de+f/
(note, even changing the regex to ^([a-zA-Z0-9_-\+\=\&]+)/?$ does little to help and actually makes it error out entirely)
Can you help?
Option 1: (site.com/index.php?var1=A&var2=B&varN=n):
Options +FollowSymLinks -MultiViews
RewriteEngine On
# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
RewriteRule ^([^/]+)/?$ index.php?p1=$1 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3 [QSA,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ index.php?p1=$1&p2=$2&p3=$3&p4=$4 [QSA,L]
1. You had [NC] flag ... so there were no need to have A-Z in your pattern.
2. Instead of [a-zA-Z0-9_-\+\=\&] or [a-zA-Z0-9_-] I use [^/] which means any character except slash /.
3. [QSA] flag was added to preserve existing query string.
Option 2: (site.com/index.php/A/B/n/):
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php/$1 [L]
In reality, if you do not plan to show that URL anywhere (like, 301 redirect etc), the last line can easily be replaced by RewriteRule .* index.php [L] -- you will look for original URL using $_SERVER['REQUEST_URI'] in your PHP code anyway.
Adding the following will redirect all traffic (for files that do not exist) to the index page:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.php [NC]
Then, you can make your decision in index.php by parsing the 'REQUEST_URI'
RewriteRule ^/.+ / [R=301,L]
any url with any kind of path beyond root will be redirected to root.
^ = start of url
/ = a slash
.+ = 1 or more characters