Skip to content
Advertisement

Getting a 500 Internal Server Error when rewriting 2 specific URLs

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…

  1. REQUEST_FILENAME is /market/item (ignoring the directory-prefix) and PATH_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.

  2. The RewriteRule directive then rewrites /market/item/1 to /market/item/1.php (clearly incorrect and not the intention). Since there is no L flag on this rule, processing continues… for the sake of the remaining rules, the PATH_INFO (from the initial request, /1) is appended to the resulting URL to become /market/item/1.php/1 (the DPI flag – discard path info – was created to prevent this specific behaviour).

  3. /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.

  4. REQUEST_FILENAME is again /market/item and PATH_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.

  5. The RewriteRule directive then rewrites /market/item/1.php to /market/item/1.php.php. Since there is no L flag on this rule, processing continues… for the sake of the remaining rules, the PATH_INFO (from the request, /1.php this time) is appended to the resulting URL to become /market/item/1.php.php/1.php.

  6. /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.

  7. 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]
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement