I keep getting a 500 internal server error when trying to rewrite these one specific URLs/files (item.php & purchase.php), the rest works.
I have tried many ways to fix this but nothing seemed to work, which is weird because all other URLs do work, but these 2 just seem to not want to work for some reason.
.htaccess file
Options -Indexes RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}.php -f RewriteRule ^(.*)$ $1.php ErrorDocument 500 "500" ErrorDocument 404 "404" ErrorDocument 403 "403" RewriteRule ^users/([^/]*)$ /user/profile.php?username=$1 RewriteRule ^users/([^/]*)/inventory$ /user/GetUserInventory.php?username=$1 RewriteRule ^market/item/([^/]*)$ /market/item.php?id=$1 RewriteRule ^market/item/([^/]*)/purchase$ /market/purchase.php?id=$1 RewriteRule ^community/([^/]*)$ /communities/view.php?id=$1 RewriteRule ^community/([^/]*)/join$ /communities/join.php?id=$1 RewriteRule ^community/([^/]*)/manage$ /communities/manage.php?id=$1 RewriteRule ^game/([^/]*)$ /games/view.php?id=$1
item.php
<?php include_once('../private/header.php'); $item = $handler->query("SELECT * FROM items WHERE id=" . $_GET['id']); $gB = $item->fetch(PDO::FETCH_OBJ); echo ' <div class="col s12 m9 l8"> <div class="container" style="width:100%;"> <div class="content-box" style="border-radius:0;"> <div class="left-align"> </div> <div class="row"> <div class="col s12 m6 l3 center-align"> <img src="'.$cdnServer.'/items/thumbnails/'.$gB->image.'.png" class="responsive-img"> </div> <div class="col s12 m6 l6"> <div style="padding-left:25px;overflow:hidden;"> <div style="font-size:26px;font-weight:300;">'.$gB->name.' <b style="text-transform:uppercase;font-size:12px;">'.$gB->type.'</b> </div> <div style="color:#777;font-size:14px;">'.$gB->description.'</div> </div> </div> <div class="col s12 m3 l3 center-align" style="padding-top:15px;"> <center> '; if ($gB->onsale == 1){ echo '<a href="'.$serverUrl.'/market/item/'.$gB->id.'/purchase" class="modal-trigger waves-effect waves-light btn green">Purchase</a>'; } else { echo '<a class="modal-trigger waves-effect waves-light btn grey darken-2">Offsale</a>'; } echo ' </center> <div style="height:15px;"></div> <center><b style="text-transform:uppercase">Creator</b></center> <center><a href="'.$serverUrl.'/users/'.$gB->creator.'" style="padding-top:12px;font-size:16px;display:inline-block;">'.$gB->creator.'</a></center> '; if($gB->collectable == 'true'){ if($gB->amount == 0) echo ' <center><span style="color:red">Sold Out</span></center> '; }else{ echo ' <center><span style="color:red">'.$gB->amount.' Remaining</span></center> '; } echo ' <div style="height:25px;"></div> </div> </div> <div style="padding-top:25px;"> <div class="row" style="margin-bottom:0;"> <div class="col s12 m12 l3 center-align"> <div style="font-size:20px;">'.$gB->created.'</div> <div style="color:#999;font-size:14px;">Time Created</div> </div> <div class="col s12 m12 l3 center-align"> <div style="font-size:20px;">'.$gB->created.'</div> <div style="color:#999;font-size:14px;">Last Updated</div> </div> <div class="col s12 m12 l3 center-align"> <div style="font-size:20px;">???</div> <div style="color:#999;font-size:14px;">Owners</div> </div> </div> </div> </div> '; include_once('../private/footer.php');
purchase.php
<?php include_once('../private/config.php'); if ($user){ $money=$myu->CurrencyCoins; $id=$_GET['id']; $item = $handler->query("SELECT * FROM items WHERE id=" . $id); $gB = $item->fetch(PDO::FETCH_OBJ); $amount=$gB->amount; if ($gB->onsale == 1){ if ($money >= $gB->price){ if ($gB->collectable != "true"){ if ($amount != 0){ $new = ($money - $gB->price); $handler->query("UPDATE `users` SET `CurrencyCoins`='".$new."' WHERE `id`='".$myu->id."'"); $handler->query("INSERT INTO inventory (item,user) VALUES (".$id.",".$myu->id.")"); } } else { if ($amount >= 1){ $amount1=($amount - 1); $new = ($money - $gB->price); $handler->query("UPDATE `users` SET `CurrencyCoins`='".$new."' WHERE `id`='".$myu->id."'"); $handler->query("UPDATE `items` SET `amount`='".$amount1."' WHERE `id`='".$gB->id."'"); $handler->query("INSERT INTO inventory (item,user) VALUES (".$id.",".$myu->id.")"); } else { echo '<center><h2>Item is sold out!</h2></center>'; } } } } else { echo '<center><h2>Item not on sale!</h2></center>'; } } echo '<head><meta http-equiv="refresh" content="1; url='.$serverUrl.'/account/character"></head>';
Advertisement
Answer
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}.php -f RewriteRule ^(.*)$ $1.php
These directives should be at the end of your .htaccess
file, after the other rewrites. They are also incorrect – although by placing them at the end of the file it will avoid the immediate issue, but could still cause problems with other URLs.
In its current state, when you request example.com/market/item/1
(where it would seem, /market
is a physical directory, and /item.php
is a file in that directory) then…
In brief… it results in an endless rewrite loop:
/market/item/1.php /market/item/1.php.php /market/item/1.php.php.php /market/item/1.php.php.php.php etc.
Which breaks (after 10 iterations) with a 500 response being sent to the browser.
A very similar process happens when requesting /market/item/1/purchase
:
/market/item/1/purchase.php /market/item/1/purchase.php.php /market/item/1/purchase.php.php.php /market/item/1/purchase.php.php.php.php etc.
In detail…
REQUEST_FILENAME
is/market/item
(ignoring the directory-prefix) andPATH_INFO
is/1
(important for later)./market/item
is not a directory (1st condition), but/market/item.php
is a file (2nd condition) – so both conditions are successfully met.The
RewriteRule
directive then rewrites/market/item/1
to/market/item/1.php
(clearly incorrect and not the intention). Since there is noL
flag on this rule, processing continues… for the sake of the remaining rules, thePATH_INFO
(from the initial request,/1
) is appended to the resulting URL to become/market/item/1.php/1
(theDPI
flag – discard path info – was created to prevent this specific behaviour)./market/item/1.php/1
does not match any further rules in the current pass, so the rewrite engine starts over at the top with/market/item/1.php
.REQUEST_FILENAME
is again/market/item
andPATH_INFO
is now/1.php
./market/item
is not a directory (1st condition), but/market/item.php
is a file (2nd condition) – so both conditions are successfully met a second time.The
RewriteRule
directive then rewrites/market/item/1.php
to/market/item/1.php.php
. Since there is noL
flag on this rule, processing continues… for the sake of the remaining rules, thePATH_INFO
(from the request,/1.php
this time) is appended to the resulting URL to become/market/item/1.php.php/1.php
./market/item/1.php.php/1.php
does not match any further rules in the current pass, so the rewrite engine starts over at the top with/market/item/1.php.php
.GOTO #4 (with updated URL-path) etc. etc. etc. rewrite loop, 500 error.
And a very similar process happens when requesting /market/item/1/purchase
. The REQUEST_FILENAME
is the same /market/item
(so it again checks that /market/item.php
exists, not purchase.php
), except that the PATH_INFO
is /1/purchase
(not /1
). And the initial URL-path that the .php
extension is appended to is naturaly /market/item/1/purchase
(not /market/item/1
).
Fix
If you’ve followed that “confusing muddle”, you’ll see that the condition that checks for the existence of the “path/to/file” + “.php” is not necessarily the same as the rule that actually rewrites the request to “URL-path” + “.php”. (“path/to/file” is not the same as the “URL-path”). To fix this, it should be written as:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f RewriteRule (.*) $1.php [L]
No real need for the directory check here, since if it was a directory, the file check that follows must fail (unless you have directory names that end in .php
). The %{DOCUMENT_ROOT}/$1.php
check is now effectively “the same” as $1.php
(the file being rewritten to).
The literal dot does not need to be backslash escaped in the RewriteCond
TestString – this is an “ordinary” string, not a regex.
Don’t forget the L
flag(s). And this rule block should now go at the end of the .htaccess
file.
Summary
Options -Indexes RewriteEngine on ErrorDocument 500 "500" ErrorDocument 404 "404" ErrorDocument 403 "403" RewriteRule ^users/([^/]*)$ /user/profile.php?username=$1 [L] RewriteRule ^users/([^/]*)/inventory$ /user/GetUserInventory.php?username=$1 [L] RewriteRule ^market/item/([^/]*)$ /market/item.php?id=$1 [L] RewriteRule ^market/item/([^/]*)/purchase$ /market/purchase.php?id=$1 [L] RewriteRule ^community/([^/]*)$ /communities/view.php?id=$1 [L] RewriteRule ^community/([^/]*)/join$ /communities/join.php?id=$1 [L] RewriteRule ^community/([^/]*)/manage$ /communities/manage.php?id=$1 [L] RewriteRule ^game/([^/]*)$ /games/view.php?id=$1 [L] # Append .php on remaining requests RewriteCond %{DOCUMENT_ROOT}/$1.php -f RewriteRule (.*) $1.php [L]