I have a content type in a Drupal 6 site that allows the creator of a node to mark the node as "withdrawn"; he can still see it, but attempts by others to see it are caught and redirected somewhere else, like their user page.

So far so good, but I'm concerned about what happens when search bots show up looking for the node; they get a 302 response from the server and are then redirected to the "somewhere else" page with an http code 200. What ought to happen (I think) is that the request by Googlebot for the node should result in a 403 or 410 error code, causing (eventually) the page to get dropped from the Google index. So I'd like to have the page generation work just like it is, except with a 401/410/whatever getting sent back as the response to the initial request.

I've tried putting some header() calls into the part of the code that detects the disallowed access, but they're not working, presumably because I'm too far along in the page construction by the time that call happens for the new header information to matter.

Is there any way to get this error code generated while still getting the user to the page I want them to be at?

3 Answers 3


drupal_goto Can help you

drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302)


$path: A Drupal path or a full URL.

$query: A URL-encoded query string to append to the link, or an array of query key/value-pairs without any URL-encoding. Passed to url().

$fragment: A destination fragment identifier (named anchor).

$http_response_code: Valid values for an actual "goto" as per RFC 2616 section 10.3 are:

  • 301 Moved Permanently (the recommended value for most redirects)
  • 302 Found (default in Drupal and PHP, sometimes used for spamming search engines)
  • 303 See Other
  • 304 Not Modified
  • 305 Use Proxy
  • 307 Temporary Redirect (alternative to "503 Site Down for Maintenance")

Note: Other values are defined by RFC 2616, but are rarely used and poorly supported.


I think I've got an answer for this -- at least, it seems to be working for me, and (after the fact) seems fairly obvious :) After detecting the issue:

  • Do drupal_set_header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found'); to generate the 404 response. This works where header() doesn't; it knows how to fit the header into the page being generated.

  • You can't do a drupal_goto() to generate the desired content -- this will generate a new page with a new URL. Instead, call whatever code gets called at your desired destination page and PRINT (not return) the result.

This gives me what I want: an apparent 404 error at the desired location, but with content corresponding to what I want. This is in some sense a custom 404 page; I played around with the customerror module, but doing it this way seemed simpler. Anyway, it works...


If I understand you well I won't bother about redirects:

function mymodule_view($node, $teaser = FALSE, $page = FALSE) {
   global $user;

   if (_is_node_withdrawn($node)) {
       if (! _user_allowed_to_view($user)) {

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.