HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Review URL-prettifying .htaccess file

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
filehtaccessprettifyingreviewurl

Problem

Can anyone please review the following .htaccess file and let me if it is correctly put together?

What I think it does:

  • So it direct to a custom 404 page



  • Remove the extensions from the end of the urls (example .php)



  • Remove /index



  • I don't really understand what the final rule does, can anyone please explain it if could?



DirectoryIndex index.html index.php 
ErrorDocument 404 /404 

RewriteEngine On 
RewriteBase / 

# Remove enter code here.php; use THE_REQUEST to prevent infinite loops 
# By puting the L-flag here, the request gets redirected immediately 
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP 
RewriteRule (.*)\.php$ $1 [R=301,L] 

# Remove /index 
# By puting the L-flag here, the request gets redirected immediately 
# The trailing slash is removed in a next request, so be efficient and dont put it on there at all 
RewriteRule (.*)/index$ $1 [R=301,L] 

# Remove slash if not directory 
# By puting the L-flag here, the request gets redirected immediately 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_URI} /$ 
RewriteRule (.*)/ $1 [R=301,L] 

# Add .php to access file, but don't redirect 
# On some hosts RewriteCond %{REQUEST_FILENAME}.php -f will be true, even if 
# no such file exists. Be safe and add an extra condition 
# There is no point in escaping a dot in a string 
RewriteCond %{REQUEST_FILENAME}.php -f 
RewriteCond %{REQUEST_URI} !(/|\.php)$ 
RewriteRule (.*) $1.php [L]

Solution

This is basically a canonicalizing URL prettifier that redirects clients to a shorter URL.

The RewriteCond operating on %{THE_REQUEST} is weird, since it works directly at the HTTP protocol level. I understand that you want to avoid redirecting POSTs, since a redirect would convert POSTs into GETs, and such breakage would be an unacceptable consequence for having nicer-looking URLs. However, it would be better to test %{REQUEST_METHOD} instead.

In the worst case, you could end up redirecting the client three times:

  • GET /path/to/directory/index.php/:



  • GET /path/to/something/index.php



  • GET /path/to/something/index



  • GET /path/to/something



By combining the first two rules, you could eliminate the third request.

# Strip off /index.php or /index or .php
RewriteCond %{REQUEST_METHOD} =GET
RewriteRule (.*)(/index\.php|/index|\.php)$ $1 [R=301,L]


In the trailing slash cleanup, you have a superfluous RewriteCond:

# Remove slash if not directory 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule (.*)/$ $1 [R=301,L]


I would tweak your last rule a bit. Do the string analysis check before the filesystem check. Use $0 instead of %{REQUEST_URI} and $1.

RewriteCond $0 !(/|\.php)$
RewriteCond %{REQUEST_FILENAME}.php -f 
RewriteRule .* $0.php

Code Snippets

# Strip off /index.php or /index or .php
RewriteCond %{REQUEST_METHOD} =GET
RewriteRule (.*)(/index\.php|/index|\.php)$ $1 [R=301,L]
# Remove slash if not directory 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule (.*)/$ $1 [R=301,L]
RewriteCond $0 !(/|\.php)$
RewriteCond %{REQUEST_FILENAME}.php -f 
RewriteRule .* $0.php

Context

StackExchange Code Review Q#40669, answer score: 6

Revisions (0)

No revisions yet.