htaccess rewrite 404 to be php handled and return 200 OK

This one is driving me crazy...

OBJECTIVE:

When a file is requested that isn't there, my system will actually find the right "$data" and return it as a 200-- not a 404 error.

My method...

Add this to my htaccess file:
ErrorDocument 404 /404.php

In 404.php, actually return a 200 OK with:
header('HTTP/1.1 200 OK', true, 200);
echo $data;


PROBLEM:

When I use "header('HTTP/1.1 200 OK', true, 200);" I still get a 404 coming back to the browser.


INSANITY:

When I use "header('HTTP/1.1 201 OK', true, 200);" it works PERFECTLY-- except I really want to return a 200 not a 201.


Does anyone know how I can solve this problem? I've reproduced this on a couple of different Apache setups so I think anyone else can get the same thing by:

- Setting up htaccess with the ErrorDocument line.
- Setting up 404.php like mine and return something "$data".
- Try browsing to any non-existent page.
- Inspect your http responses and you'll see it's a 404, unless you change the header to 201 instead of 200 (or actually any 2xx instead of 200).

I'm using php 5.3.


cnxmaxAsked:
Who is Participating?
 
DerokorianCommented:
Or, if that doesn't work, as it may not... you could use conditionals instead of error document:

RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) 404.php [R=200]

Open in new window


Untested, but I hope it helps
0
 
DerokorianCommented:
Use the response flag in your .htaccess file maybe?

ErrorDocument 404 /404.php [R=200]
0
 
COBOLdinosaurCommented:
The server is doing what it should do and what you are trying to do is mislead the user.  It does not  return 200 because things were not as they should be.  Return the 201 is accurate given the change made because that is what a 201 says.  Why do you think it is important to mislead the user?  You should actually be letting them know that the 404 occured so they quit using the incorrect url that caused it.

Cd&
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
Ray PaseurCommented:
I use a 404 handler.  The goal here is to let someone put in something like http://landonbaseball.com/coaches and get it redirected to /coaches.php

My .htaccess says this:

ErrorDocument 404 /404handler.php
AddType application/x-httpd-php5 .html .htm .php

I am pretty sure the server is returning a 200 OK because when I monitor the site with a nonsense URL, I still get a 200 http code back from CURL.
<?php // 404handler.php
error_reporting(E_ALL);
session_start();

if (isset($_SERVER["REQUEST_URI"]))
{
    // SAVE THE REQUEST
    $_SESSION["REQUEST_URI"] = $_SERVER["REQUEST_URI"];

    // IF A PHP SCRIPT IS NOT FOUND GO TO THE HOME PAGE
    if (preg_match('#\.php#i', $_SERVER["REQUEST_URI"]))
    {
        header('Location: /');
        exit;
    }

    // IF A NON-PHP SCRIPT IS NOT FOUND, TRY IT WITH PHP
    $arr = explode('?', $_SERVER["REQUEST_URI"]);
    $arr[0] .= '.php';
    $uri = implode('?', $arr);
    header("Location: $uri");
    exit;
}

// IF NO REQUEST URI
header('Location: /');
exit;

Open in new window

0
 
COBOLdinosaurCommented:
The reason we have standards is to insure interoperability.  When you start hacking around with the protocol standards, you are just begging for security software somewhere to trigger a flag that gets you labelled as a potentially dangerous site.

Cd&
0
 
cnxmaxAuthor Commented:
@Cd& - Thanks for the tips. I'm doing something similar to what Google does:

http://code.google.com/speed/pss/faq.html#howdoespss

("Google serves requests received for your serving domain by fetching content from your reference domain and rewriting it.")

This allows me to statically host massive websites that have a dynamic source ("reference domain", as Google calls it). It's not that I'm trying to trick anyone or that anyone is requesting a real 404-- it's that I want to return the source file the first time it is requested if it doesn't exist (and save a cached static version at that time so it can be quickly returned next time it's requested).

I know that technically a 201 might be correct-- but realistically there are tons of bots, crawlers, and other clients that only check for a 200. It would be nice if standards were always best... but in the real world responding to non-compliant systems with what they expect is better than doing it "right".

0
 
cnxmaxAuthor Commented:
Thanks for the helpful advice Derokorian. My final solution was:


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ 404.php?$1 [L]
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.