Forum Moderators: phranque

Message Too Old, No Replies

mod rewrite and errordocument

         

Lordie

3:09 pm on Feb 5, 2009 (gmt 0)

10+ Year Member



Hello folks.

I am having a issue when using mod_rewrite to (doh ;)) rewrite URLs.
The rewriting part works, but typing anything that has not yet been rewritten the page loads without giving a 404 message (hope my explanation is plain enough).

Posting my .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On

RewriteBase /

RewriteRule ^([a-zA-Z0-9]+)\.html$ /index.php?page=$1 [L]
</IfModule>

If anyone got a better way of getting the job done I would appreciate it very much.

Cheers!

g1smd

3:28 pm on Feb 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Your PHP script needs to test the value of $1 and send "HEADER 404 Not Found" if the value is not one that resolves to real content, and "200 OK" with content if it does.

Lordie

3:40 pm on Feb 5, 2009 (gmt 0)

10+ Year Member



Thanks for the reply!

However, your answer made my head hurt and I am even more lost. Care to give an example?

g1smd

5:04 pm on Feb 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



<?php
$pageID = htmlspecialchars($_GET["page"]);

IF $pageID !== $a-valid-page-ID 
{
HEADER ("HTTP/1.1 404 Not Found");

echo ('DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head><title>Not Found</title></head>
<body><p>Page Not Found</p></body>
</html>');
}
?>

Lordie

5:35 pm on Feb 5, 2009 (gmt 0)

10+ Year Member



Thanks again!

That makes more sense. Will try it and see how it goes :)

g1smd

5:47 pm on Feb 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



You'll need to do the $a-valid-page-ID bit.

Likely this will be an array with all the valid IDs, or you'll send the ID as a database query and see if it matches any of the entries.

If there is no match, send the PHP-generated 404 headers and PHP-generated 404 page.

Lordie

5:50 pm on Feb 5, 2009 (gmt 0)

10+ Year Member



Reading my brain are you? :P
Thanks for answering questions I have not thought of yet lol. *thumbs up* ^^

jdMorgan

6:20 pm on Feb 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Senior WebmasterWorld members are generally very good mind-readers... :)

Jim

Lordie

6:32 pm on Feb 5, 2009 (gmt 0)

10+ Year Member



I can also use header("location: /error.html") right? and have the HEADER ("HTTP/1.1 404 Not Found"); in that file :)

g1smd

7:21 pm on Feb 5, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I think not.

I think it will throw a dangerous "302 Found" response.

Try it and see. Use the Live HTTP Headers extension for Firefox to see all of the servers responses (there may be more than one).

If there are chained responses, like 302 -> 404 or somesuch then run like hell.

You need the 404 response to be the first immediate response to the request.

Lordie

1:32 pm on Feb 7, 2009 (gmt 0)

10+ Year Member



Hmm, still does not work, posting current code:

* Valid Pages */
$valid_pages = array(
"",
"services",
"projects",
"about",
"contact",
"register"
);
/* Checking Valid Address */
$page = htmlspecialchars($_GET['page']);
if ($valid_pages !== $page && $page !== "")
{
HEADER("HTTP/1.1 404 Not Found");
include "/web/404.html";
exit;
}

The thing is that I am getting 404 where there actually is a match.
The one that is matching ATM is register, $_GET address is ?page=register that mod_rewrite translates to register.html, but unfortunately the if() seems to ignore that and gives a 404 instead. O.o

g1smd

1:36 pm on Feb 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Don't you need a loop to examine each of the valid page names in the array in turn?

Lordie

1:48 pm on Feb 7, 2009 (gmt 0)

10+ Year Member



Yeah, tried that but did not work either for some reason...

for($i = 0; $i < count($valid_pages); $i++)
{
loops and arrays have always been a weak point of mine, since I just can not get them to work (with the exception of mysql arrays).
}

g1smd

1:58 pm on Feb 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I expect
count($valid_pages)[b]-1[/b];
is probably needed.

And you're comparing

 $valid_pages[b][$i][/b] 
with the word coming in from the GET.

Each time around the loop, do the compare and only set a flag if there is a match (like

IF ($valid_pages[$i] == $page) {$match="Y"; }
or similar)

The loop will run "i" times, so do not unset the flag if following iterations don't match.

After the loop, look at the flag. If it is NOT set (not set means that nothing matched), send the 404 page.

If it is set, continue with the script and send the real page of content.

[edited by: g1smd at 2:19 pm (utc) on Feb. 7, 2009]

Lordie

2:10 pm on Feb 7, 2009 (gmt 0)

10+ Year Member



I'm afraid I didn't get the round and flag part.

Lordie

2:26 pm on Feb 7, 2009 (gmt 0)

10+ Year Member



OK, I think I got it working. Code so far:
/* Valid Pages */
$valid_pages = array(
"",
"services",
"projects",
"about",
"contact",
"register"
);
/* Checking Valid Address */
$page = htmlspecialchars($_GET['page']);
for ($i = 0; $i < count($valid_pages)-1; $i++)
{
if ($valid_pages[$i] == $page && $page !== "")
{
HEADER("HTTP/1.1 404 Not Found");
echo $valid_pages[$i];
include "/web/404.html";
exit;
}
}
Didn't have to do the flag part thing either.
Any improvements would be appreciated. :)

g1smd

2:31 pm on Feb 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



If you ask for "about" I think that code will send a "404" the first time round the loop because "services" does not match "about".

Next time round it will send another 404, because "about" does not match "projects".

That's incorrect. Send either a 404 or the content only after you have done all of the matching for the whole list.

[edited by: g1smd at 2:34 pm (utc) on Feb. 7, 2009]

Lordie

2:34 pm on Feb 7, 2009 (gmt 0)

10+ Year Member



Yeah, the only link that's working is register. I'm stuck >.<

g1smd

2:36 pm on Feb 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Look at my post way above. The solution is laid out, using the temporary "flag" variable.

The loop runs to see if anything matches, comparing one URL at a time, and only sets the flag if a match is found.

After the loop (not inside it) a single compare looks to see if the flag was set. If it was not set, then nothing in the list was a match, and so the 404 page must be sent.

Lordie

2:48 pm on Feb 7, 2009 (gmt 0)

10+ Year Member



I don't get it! *bangs head against screen (luckily it's a CRT ;))*
So I take it that I need to set:
if ($valid_pages[$i] == $pages)
{
$match = "Y";
}
inside the for() loop right? But then what? *lost* :¦
Thanks man for helping out! <3

g1smd

2:55 pm on Feb 7, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



$match="N";
$page = htmlspecialchars($_GET['page']);

FOR ($i = 0; $i < count($valid_pages)-1; $i++) 
{
IF ($valid_pages[$i] == $page && $page !== "")
{
$match="Y";
}
}

 IF ($match !== "Y" )
{
HEADER("HTTP/1.1 404 Not Found");

include "/web/404.html"; 
exit;
}
ELSE
{
-- send out the real page of content --
}

Lordie

3:31 pm on Feb 7, 2009 (gmt 0)

10+ Year Member



OK. So now I got:
$match = "N";
$page = htmlspecialchars($_GET['page']);
for ($i = 0; $i < count($valid_pages)-1; $i++)
{
if ($valid_pages[$i] == $page && $page !== "") { $match = "Y"; }
}
if ($match !== "Y")
{
HEADER("HTTP/1.1 404 Not Found");
include "/web/404.html";
exit;
}
Still doesn't work though.
http:// <snip> to see for yourself.
The services page do actually exist and it's included in my switch in the index.php file *shrug* O.O

[edited by: jdMorgan at 3:34 pm (utc) on Feb. 7, 2009]
[edit reason] No URLs, please. See Terms of Service. [/edit]