htaccess rewrite, how to negate sub directory files - .htaccess

I have htaccess file performing URL rewrite. It basically removes the .php extension.
The rules work fine, e.g. they successfully rewrite http://example.com/contact.php into http://example.com/contact
However the rewrite also changes sub directory files, such as /includes/check-form-input.php.
So when, for example, a form at contact.php attempts to submit to /includes/check-form-input.php the htaccess rewrite strips the .php from the end and I get 404 headers.
i.e. /includes/check-form-input is not found.
At least that's what appears to happen, using HTTP_REFERER seems to confirm this as the referer was /includes/check-form-input without the ext .php
Is there a way to add a rule to negate all sub dirs?
I have the following htaccess - which is copied from another answer here on SO, as I don't 100% grasp the rewrite structure.
(I've left in the www to non-www redirect in case it's the cause)
## Rewrite on
RewriteEngine on
## Redirect all pages from non-www to www
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
## URL rewrite
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ http://example.com/$1 [R=301,L]
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ http://example.com/$1 [R=301,L]
# Resolve .php file for extensionless php urls
RewriteRule ^([^/.]+)$ $1.php [L]

You can either exclude all subdirectories,
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^([^/]+)\.php$ http://example.com/$1 [R=301,L]
or limit it to only GET requests:
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ (.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ http://example.com/$1 [R=301,L]
or just exclude the includes subdirectory
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteCond %{REQUEST_URI} !^/includes/
RewriteRule ^([^/]+)\.php$ http://example.com/$1 [R=301,L]

Related

.htaccess problems with https redirect

I have just upgraded my website from HTTP to HTTPS and my .htaccess, which worked perfectly before, is now behaving strangely. I have the following in there:
Remove trailing slash
Remove php extension
...plus others, but I guess these are the problematic ones.
The behaviors I'm getting, on an example page, are:
http://www.navanter.com/e-tips - no problem
https://www.navanter.com/e-tips.php - no problem
http://www.navanter.com/e-tips.php - seems to double the URL in the address bar
Am I missing something obvious? Code is:
Order Deny,Allow
DirectoryIndex index.php
# Secure text files
<Files ~ "\.txt$">
Order allow,deny
Deny from all
</Files>
# Redirect non-www to www:
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
ErrorDocument 404 /404.php
RewriteEngine On
# All calls go to SSL
RewriteEngine On
RewriteCond %{ENV:HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ https://www.navanter.com/$1 [R=301,L]
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ https://www.navanter.com/$1 [R=301,L]
# Resolve .php file for extensionless php urls
RewriteRule ^([^/.]+)$ $1.php [L]
For this specific problem, your rewrite rules for removing the trailing / and the .php extension shouldn't need the full URL in the substitution. You might also consider reordering some of those rules.
Updated Example:
Require all granted
DirectoryIndex index.php
# Secure text files
<Files ~ "\.txt$">
Require all denied
</Files>
ErrorDocument 404 /404.php
RewriteEngine On
# Redirect HTTP to HTTPS and non-www to www
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteRule ^ /%1 [NC,R=301,L]
# Resolve .php file for extensionless php urls
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ /$1.php [NC,L]
A couple things to note here:
The directives above were modified to use the updated apache 2.4 syntax
The RewriteEngine on directive should come before the other rewrite rules
The HTTP -> HTTPS and non-www -> www redirect logic can be done in a single operation
The PHP extension stripping, and subsequent remapping, should be done without the full URL to avoid the duplication behavior you observed. This last bit should fix the problem.
If you need further info on some of the syntax employed here, you can check the mod_rewrite documentation.

Remove .php extension for a generic site

This is my code:
RewriteEngine On
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ http://example.com/folder/$1 [R=301,L]
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ http://example.com/folder/$1 [R=301,L]
# Resolve .php file for extensionless php urls
RewriteRule ^([^/.]+)$ $1.php [L]
But it only work for the site example.com
How can I edit it to work for any site ?
If you want it to work for multiple hosts just use the variable HTTP_HOST instead of the actual site name.
RewriteEngine On
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ http://%{HTTP_HOST}/$1 [R=301,L]
# Resolve .php file for extensionless php urls
RewriteRule ^([^/.]+)$ $1.php [L]

Remove subdirectory from URL using htaccess

I have the following URL:
http://example.org/search/search
Using htaccess, I need to remove the first /search from the URL so that the URL is:
http://example.org/search
For the life of me I can't figure out how.
Here's the relevant section of my htaccess file
# Remove www from URL
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.org/$1 [R=301,L]
# Remove the need for the php file extension
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ http://example.org/$1 [R=302,L]
# Resolve .php file for extensionless php urls
RewriteRule ^([^/.]+)$ $1.php [L]
# Remove index from home URL
RewriteRule ^(.*)index\.php$ http://%{HTTP_HOST}/$1 [R=301,L]
Thanks
Not sure how the rules that you have ever worked. You have some duplicate rules and redirects that interfere with routing. Put all your redirects in the same place, and make sure you use the -f check before you add the php extension:
# Remove www from URL
RewriteCond %{HTTP_HOST} ^www\.example\.org$ [NC]
RewriteRule ^(.*)$ http://example.org/$1 [R=301,L]
# Redirect external .php requests to extensionless url
RewriteCond %{THE_REQUEST} \ /+(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ http://example.org/$1 [R=302,L]
# Remove index from home URL
RewriteCond %{THE_REQUEST} \ /+(.*)index\.php
RewriteRule ^(.*)index\.php$ http://%{HTTP_HOST}/$1 [R=301,L]
# Remove the search folder:
RewriteCond %{THE_REQUEST} \ /+search/search
RewriteRule ^search/search(.*)$ /search$1 [L,R=301]
# Add the search folder back
RewriteCond $1 !^/search
RewriteRule ^search(.*)$ /search/search$1 [L]
# Add the extension back on if it exists
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]

.htaccess infinite loop for non existent urls

I'm working on my .htaccess to obtain an extensionless site. I've searched online and implemented some rules that are working, but when I type in a url that doesn't exist (e.g. mysite.com/dsfadfasdf ) it starts to go in an infinite loop.
If anyone would be so kind as to help me get rid of the loop and perhaps redirect to a page of my choosing (where I'll say the page doesn't exist) I'd really appreciate it!
Options +FollowSymLinks
Options +Indexes
RewriteEngine On
RewriteBase /
# Redirect www to non www
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
# Home page language
RewriteRule ^(en|ro)/?$ index.php?lang=$1 [L]
# For the profile page
RewriteRule ^(.+)\/accommodation-(.+)\/([0-9]+)\/(.+)$ location.php?id=$3&town=$2&hname=$4&lang=$1 [NC,L]
# Internally rewrite extensionless URL to corresponding .php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)$ $1.php?%1 [NC,L,QSA]
# Externally redirect (only) direct client requests for .php URLs to extensionless URLs:
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+/)*[^.]+)\.php http://mysite.com/$1 [R=301,L]
I believe the issue is in the last rule. Any suggestions?
.htaccess keeps rewriting if the url changes. Force it to stop rewriting after you've rewritten your url internally with the END flag:
# Internally rewrite extensionless URL to corresponding .php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)$ $1.php?%1 [NC,END,QSA]
Documentation is here.

Rewrite a dynamic url after extension removed

I've been working on my HTAccess for a couple days now, and I've hit a dead end.
I've rewritten and redirected the files to be extensionless, now I need to rewrite the url to be SEO Friendly.
Previously, the URL was: http://www.example.com/member.php?playername=encodedName
I removed the extension: http://www.example.com/member?playername=encodedName
I can't quite get it to: http://www.example.com/member/encodedName
Here's what I've gotten so far:
Code trying to redirect to SEO Friendly URL. Does NOT work.
RewriteRule ^member/([^/]*)$ /member.php?playername=$1 [L]
RewriteRule ^squad/([^/]*)$ /squad.php?squadname=$1 [L]
RewriteRule ^article/([^/]*)$ /article.php?articlename=$1 [L]
Unless directory, remove trailing slash. Works.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
Resolve .php file for extensionless php urls. Works.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]
Redirect external .php requests to extensionless url. Works.
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(([^/]+/)*[^.]+)\.php $1 [R=301,L]
Does anyone have an idea as to what I am doing wrong? It's probably a very newbie problem that I just haven't encountered yet.
The "Code trying to redirect to SEO Friendly URL" part looks fine. And while you're redirecting requests made directly to php files to remove the extension, you're not doing anything specifically about the 3 SEO friendly URLs that you are rewriting back.
If when you go to http://www.example.com/member/encodedName, and you're not being served the content at http://www.example.com/member.php?playername=encodedName, then this looks like a Multiviews problem. You'll need to turn off Multiviews either in your server/vhost config or add this to the top of the htaccess file (or in the appropriate already existing Options statement):
Options -Multiviews
In order to do the redirecting to the SEO friendly URLs, add this before the "Redirect external .php requests to extensionless url." rules:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /member\.php\?playername=([^&\ ]+)([^\ ]*)
RewriteRule ^ /member/%1?%2 [L,R=301]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /squad\.php\?squadname=([^&\ ]+)([^\ ]*)
RewriteRule ^ /squad/%1?%2 [L,R=301]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /artcile\.php\?articlename=([^&\ ]+)([^\ ]*)
RewriteRule ^ /article/%1?%2 [L,R=301]

Resources