I have only just started this but I wanted to post for opinion. In IRC I was pushed towards using hook_page_alter() instead of defining a new hook. However hook_page_alter() runs after the 404 header has been sent. I don't expect the code as is to get in. Largely I am posting this as a start because I work on large sites (Economist.com) and I don't want to have to use nfs to share the files directory as it adds another single point of failure in the stack.
Background for wanting hook_404()
The approach that Vignette and other large cm systems take is as follows.
Server X and Y are physical or logical Drupal servers that share the same codebase and database.
1) User A uploads an image ( sites/default/dog.png ) to server X to be included onto node/1234.
2) User B loads node/1234 on server Y. When the request comes into load sites/default/dog.png it fires a Drupal 404 page. If hook_404() exists a module of some sort could look up whether the file exists in the files table and go collect the image from the correct server, write the image locally and either serve the image or redirect to it. I am intentionally vague on how the module would collect the image from Server Y or Z or Q as this is an example use case.
2) User C loads node/1234 on server Y. When the request comes into load sites/default/dog.png the file exists and is served by the webserver. Apache never gets involved.
This approach doesn't need each upload to jump through hoops to put each file uploaded on each server which is fast for the person uploading. It doesn't require a cron job to push the relevant files around which would have time lag issues anyway.
ImageCache registers the callback for imagecache/% if I remember correctly but I think something using a hook_404() could capture any missing URL. In fact imagecache in D7 could well use this approach. I imagine I could have a module with the callback for sites/% to work in the same way as ImageCache but it seems less glamorous.
Opinions?
Comment | File | Size | Author |
---|---|---|---|
#8 | 444756_hook_page_not_found_8.patch | 5.01 KB | deviantintegral |
#6 | 444756_hook_page_not_found.patch | 2.51 KB | deviantintegral |
#5 | hook404.patch | 1.16 KB | stewsnooze |
hook404.patch | 1.14 KB | stewsnooze | |
Comments
Comment #1
deviantintegral CreditAttribution: deviantintegral commentedWow - this is great timing.
I need the same feature but for another reason. In this case, we have two sites, example.com and subsite.example.com. If users type example.com/some-path, and it 404's, we want to check to see if it exists on subsite.example.com, and redirect there. Since Drupal sets the header before calling the path in the site404 variable, it's impossible to redirect as a header has all ready been set.
Two thoughts at the moment:
Comment #2
j.somers CreditAttribution: j.somers commentedI agree with the remarks from #1.
Secondly, as far as I know none of the existing hook_*() functions are called directly. I believe you need to perform the actions in your hook_404() function directly and you can use module_invoke_all.
So it becomes something like:
Comment #3
stewsnoozeI've changed the code to support the two comments. Additionally in the patch there is a space removed from the end of the line in theme_menu_tree() as my eclipse is set up to remove end of line spaces. I could pull that out if needed but I don't see the point yet.
Also I've created a very small sample module that would use the hook and can be edited to return different page states, like access denied or page not found e.t.c.
You can toy with that by downloading it from
http://www.stewsnooze.com/content/support-adding-hookpagenotfound-drupal-7
Comment #4
deviantintegral CreditAttribution: deviantintegral commentedCan you attach the patch please?
Comment #5
stewsnoozeha ha. I am such a fool.
Patch attached.
Comment #6
deviantintegral CreditAttribution: deviantintegral commentedLooks pretty good to me.
Here's an updated patch which contains hook API documentation. The example is just how I'm currently using this hook, but I'm open to making it a simpler example if someone has any ideas.
Comment #8
deviantintegral CreditAttribution: deviantintegral commentedRerolled patch - only difference was the comment cleanup that got fixed in another commit.
Comment #10
sun.core CreditAttribution: sun.core commentedComment #11
deviantintegral CreditAttribution: deviantintegral commentedI'm able to write my module for D7 using the built-in API's now that we have drupal_static(). The only catch is that you have to remember to unset($_REQUEST['destination']) before calling drupal_goto(), otherwise you get redirected to the previous destination. The following seems to work fine when set as the callback for the site404 variable:
I'm marking as won't fix as I believe all of the other cases mentioned in this issue can now be handled.
Comment #12
sammarks15 CreditAttribution: sammarks15 commentedhook404.patch queued for re-testing.
Comment #13
sammarks15 CreditAttribution: sammarks15 commented#8: 444756_hook_page_not_found_8.patch queued for re-testing.
Comment #15
marcingy CreditAttribution: marcingy commentedAs per #11 this is not needed and this issue has been closed for 3 years.
Comment #16
fredcy CreditAttribution: fredcy commentedThe general scheme in comment #11 works except that I had to use
$_GET['destination']
instead of$_REQUEST['destination']
.EDIT: Also, doing the redirect as part of the default 404 page results in Drupal logging the original access as a page-not-found error even when we never return a 404 to the browser/client. Seems like a real hook would be better, as in the originally proposed patch.