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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

DerokorianCommented:
Use the response flag in your .htaccess file maybe?

ErrorDocument 404 /404.php [R=200]
0
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
10 Tips to Protect Your Business from Ransomware

Did you know that ransomware is the most widespread, destructive malware in the world today? It accounts for 39% of all security breaches, with ransomware gangsters projected to make $11.5B in profits from online extortion by 2019.

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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.