* (bug 2585) HTTP 404 return code is now given for a page view if the page
authorBrion Vibber <brion@users.mediawiki.org>
Mon, 22 Dec 2008 23:38:58 +0000 (23:38 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Mon, 22 Dec 2008 23:38:58 +0000 (23:38 +0000)
  does not exist, allowing spiders and link checkers to detect broken links.

This is less expansive than the old 2005 implementation (r11307), hitting
only page views (won't affect action=edit) and doesn't attempt to cover
error conditions either (many of which should probably return a different code).

Pages which exist in the DB or return true for Title::isAlwaysKnown() such
as file pages for existing files, as well as category pages that exist, are
treated as existing by returning true for Article::hasViewableContent().

RELEASE-NOTES
includes/Article.php
includes/CategoryPage.php

index e6cc2ae..5b7fff3 100644 (file)
@@ -241,7 +241,8 @@ The following extensions are migrated into MediaWiki 1.14:
 * (bug 16760) Add CSS-class to action links of Special:Log
 * (bug 505) Time zones can now be specified by location in user preferences,
   avoiding the need to manually update for DST. Patch by Brad Jorsch.
-
+* (bug 2585) HTTP 404 return code is now given for a page view if the page
+  does not exist, allowing spiders and link checkers to detect broken links.
 
 === Bug fixes in 1.14 ===
 
index 527638d..1b4bcce 100644 (file)
@@ -508,6 +508,18 @@ class Article {
        public function exists() {
                return $this->getId() > 0;
        }
+       
+       /**
+        * Check if this page is something we're going to be showing
+        * some sort of sensible content for. If we return false, page
+        * views (plain action=view) will return an HTTP 404 response,
+        * so spiders and robots can know they're following a bad link.
+        *
+        * @return bool
+        */
+       public function hasViewableContent() {
+               return $this->exists() || $this->mTitle->isAlwaysKnown();
+       }
 
        /**
         * @return int The view count for the page
@@ -714,6 +726,7 @@ class Article {
                $rdfrom = $wgRequest->getVal( 'rdfrom' );
                $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
                $purge = $wgRequest->getVal( 'action' ) == 'purge';
+               $return404 = false;
 
                $wgOut->setArticleFlag( true );
 
@@ -813,12 +826,22 @@ class Article {
                                        $text = wfMsg( 'noarticletext' );
                                }
                        }
+                       
                        # Non-existent pages
                        if( $this->getID() === 0 ) {
                                $wgOut->setRobotPolicy( 'noindex,nofollow' );
                                $text = "<div class='noarticletext'>\n$text\n</div>";
+                               if( !$this->hasViewableContent() ) {
+                                       // If there's no backing content, send a 404 Not Found
+                                       // for better machine handling of broken links.
+                                       $return404 = true;
+                               }
                        } 
 
+                       if( $return404 ) {
+                               $wgRequest->response()->header( "HTTP/1.x 404 Not Found" );
+                       }
+
                        # Another whitelist check in case oldid is altering the title
                        if( !$this->mTitle->userCanRead() ) {
                                $wgOut->loginToUse();
index f150e37..f5c2540 100644 (file)
@@ -36,6 +36,19 @@ class CategoryPage extends Article {
                        $this->closeShowCategory();
                }
        }
+       
+       /**
+        * Don't return a 404 for categories in use.
+        */
+       function hasViewableContent() {
+               if( parent::hasViewableContent() ) {
+                       return true;
+               } else {
+                       $cat = Category::newFromTitle( $this->mTitle );
+                       return $cat->getId() != 0;
+               }
+                       
+       }
 
        function openShowCategory() {
                # For overloading