WordPress.org

Make WordPress Core

Opened 6 years ago

Closed 5 years ago

Last modified 6 weeks ago

#11348 closed defect (bug) (wontfix)

Archive Page Should be 404.php When !have_posts()

Reported by: miqrogroove Owned by: ryan
Milestone: Priority: high
Severity: major Version: 2.8.4
Component: Query Keywords:
Focuses: Cc:

Description

When categories are empty, WordPress does not link to /category/iamempty/ anywhere I can think of. Yet if you hit an empty category URL directly, WordPress fails to forward to the 404 page.

See also http://wordpress.org/support/topic/322407

Change History (27)

comment:1 @filosofo6 years ago

I don't think a 404 response is appropriate for an existing but empty category. According to the HTTP protocol, a 404 means "The server has not found anything matching the Request-URI." But in the case of an empty category, it has found something: that URI corresponds to the requested category.

comment:2 @greenshady6 years ago

  • Resolution set to invalid
  • Status changed from new to closed

It shouldn't be a 404. What's displayed on this page should be handled by the theme's category.php file. Just because something doesn't have posts, doesn't mean it's an invalid URL.

WordPress will also link to a category without posts using:

wp_list_categories( array( 'hide_empty' => false ) );

I'm going to mark this one as invalid unless others think this needs more discussion.

comment:3 follow-up: @miqrogroove6 years ago

  • Resolution invalid deleted
  • Status changed from closed to reopened

I'm reopening this ticket because the default theme doesn't have a category.php file, despite greenshady's assertion that it fixes this bug.

comment:4 follow-up: @miqrogroove6 years ago

But in the case of an empty category, it has found something

What did it find, and how is it relevant? This is a direct quote from a fresh WordPress installation:

"Sorry, but there aren't any posts in the term1 category yet."

That is the ONLY content being displayed other than the headers and footers. That is a not found condition, and that is exactly what the 404 status is used for.

comment:6 in reply to: ↑ 3 @greenshady6 years ago

Replying to miqrogroove:

I'm reopening this ticket because the default theme doesn't have a category.php file, despite greenshady's assertion that it fixes this bug.

Don't put words into my mouth. I'm not saying this is a bug at all.

And, the default theme does have an archive.php template, which handles category archives when there is no category.php template.

comment:7 in reply to: ↑ 4 @filosofo6 years ago

Replying to miqrogroove:

"Sorry, but there aren't any posts in the term1 category yet."

That is the ONLY content being displayed other than the headers and footers. That is a not found condition, and that is exactly what the 404 status is used for.

The conditions appropriate for a 404 response are defined in the HTTP RFC: "The server has not found anything matching the Request-URI."

In contrast, when you query an empty category the server does find something: that category's page. In WordPress categories can be empty. Hence, they can exist and be found by the server, even when they do not contain posts. Therefore the current behavior is not a bug and this ticket is invalid.

comment:8 follow-up: @miqrogroove6 years ago

filosofo, by your logic the server always finds index.php and should never use 404 for any reason.

comment:9 in reply to: ↑ 8 @filosofo6 years ago

Replying to miqrogroove:

filosofo, by your logic the server always finds index.php and should never use 404 for any reason.

No. The concept of "resource" is a logical one; it has to do with data and data's relationship across the web. Although

  • a garbage request string such as /index.php?whatever=irrelevant-string and
  • a blog post request such as /index.php?post_id=1

both involve the "index.php" file, they differ semantically. The first deserves a 404 response because its request doesn't map to a known resource; the second deserves something like a 200 because the request maps to a known resource (the blog post).

The actual implementation files routing the query, such as index.php, are not part of the semantics of the query.

With your example of /category/iamempty/ the query maps to a known, existing resource: namely, an empty category. The meaning of the query /category/iamempty/ is that it requests the category named "iamempty."

Because category "iamempty" exists, and the server has found it (the resource---the existing, empty category), returning a 404 in this case would go against the HTTP 404 definition.

comment:10 follow-up: @miqrogroove6 years ago

The meaning of the query /category/iamempty/ is that it requests the category named "iamempty."

Except that is not the meaning. The meaning can be customized. The default meaning is that it requests the posts in the category. When the category is empty, no links for the category exist, the category is hidden.

On a test server, I can make a directory with nothing in it. If I click on the index link it will respond 200 with no files listed. If I then hide the directory, the index link disappears, and the server responds 404 at the URL for the directory. Now by your explanation above, that means my server goes "against the HTTP 404 definition" because the empty category is an existing resource, even though it is empty and hidden.

I wonder, why did the authors of a web server not go out their way to ensure that an empty hidden resource respond with 200?

comment:11 @miqrogroove6 years ago

Another server I just tested responds 403 for hidden resources. That surprised me, actually, but I still didn't get anything like 200 Sorry there aren't any posts here.

comment:12 in reply to: ↑ 10 @filosofo6 years ago

Replying to miqrogroove:

The meaning of the query /category/iamempty/ is that it requests the category named "iamempty."

Except that is not the meaning. The meaning can be customized. The default meaning is that it requests the posts in the category.


How do you figure? What you're saying sounds a lot like the fallacy of composition. Besides, a typical category rewrite rule in WP looks like this:

'category/(.+?)/?$' => 
'index.php?category_name=$matches[1]'

That seems to be saying that a query for /category/iamempty/ is a query for the category named "iamempty." Common sense says the same thing.

In wp-includes/classes.php, we see that a query starts out as an assumed 404 until it matches an object:

 148 // If we match a rewrite rule, this will be cleared.
 149 $error = '404';

Of course the query /category/iamempty/ matches the rule given above, so then the following comes into play when WP_Query shows that there are no posts in category "iamempty":

 463   // Don't 404 for these queries if they matched an object.
 464   if ( ( is_tag() || is_category() || is_author() ) && 
          $wp_query->get_queried_object() ) {
 465           if ( !is_404() )
 466                   status_header( 200 );
 467           return;
 468   }

Note how the category is considered the queried object (and for a non-existent queried object, $wp_query->get_queried_object() returns null). And also, note the analogy to an author's page: would you consider an author's page non-existent just because she hadn't yet written any posts?


When the category is empty, no links for the category exist, the category is hidden.

greenshady already proved this false, above:

WordPress will also link to a category without posts using:
wp_list_categories( array( 'hide_empty' => false ) );


On a test server, I can make a directory with nothing in it. If I click on the index link it will respond 200 with no files listed. If I then hide the directory, the index link disappears, and the server responds 404 at the URL for the directory. Now by your explanation above, that means my server goes "against the HTTP 404 definition" because the empty category is an existing resource, even though it is empty and hidden.


Please refer again to the definition of a 404 response: "The server has not found anything matching the Request-URI." If you've hidden a file from the web server, then it can't find it, can it?

And I really don't understand why you think a hidden directory is analogous to an empty category. Thankfully in real life my empty glass isn't hidden; otherwise the waiter would never get me a refill!



I wonder, why did the authors of a web server not go out their way to ensure that an empty hidden resource respond with 200?


Don't conflate "hidden" and "empty," as they're obviously not the same (even to Apache). As you pointed out above:

On a test server, I can make a directory with nothing in it. If I click on the index link it will respond 200 with no files listed.

comment:13 @miqrogroove6 years ago

How do you figure?

When there are posts, it shows the posts. Where there are no posts, it says there are no posts found. That's all it does by default. That's all it does. Why are you quoting all this code?

would you consider an author's page non-existent just because she hadn't yet written any posts?

Absolutely, yes. This is the entire content shown on a default author page:

"Sorry, but there aren't any posts by user1 yet."

I'd be grateful for the ability to 404 that page as well.

they're obviously not the same

I never said they were the same.

comment:14 @aaroncampbell5 years ago

Please see #5324 and [8761]

There are plenty of times where I've wanted an "author" page to exist even if the user hasn't posted anything (like a profile page). Tags and categories can both have definitions (#9381), which may make sense to display even if no posts exist yet for that tag or category.

I think it should stay just as it is.

comment:15 @aaroncampbell5 years ago

To clarify, if someone wants to make something in all this easier to extend from a plugin or theme...I'm fine with that. I'd like the default behavior to "stay just as it is"

comment:16 @technosailor5 years ago

filosofo is bang on. As the contributor of the patch in #5324, I'll weigh in.

1) You seem to only want to fight. That's not really a great way to get things done.
2) Server resources and web application resources are different
3) A 404 is a server response code
4) Apache/IIS can both find an empty category archive so it is not a 404
5) Apache/IIS cannot find a URL like /my-lovely-category-archive/iamempty/ without help from a plugin so it would be a 404.
6) Reiterating 4... WordPress can run a successful query against the database because it has all the resources necessary to do it with /category/iamempty/. It returns an empty dataset from MySQL but not an empty HTTP resource. It's not a 404.
7) Reiterating 5... WordPres cannot create a successful dataset from MySQL because the variables passed via HTTP are not legitimate. Therefore the HTTP request is bad resource URI generating a legitimate 404.

Why are we even debating this?

comment:17 follow-up: @jdingman5 years ago

+1, if a post doesn't exist, it should return 404 as the status code, not 200, which it currently does

comment:18 @miqrogroove5 years ago

  • Milestone changed from 2.9 to 3.0
  • Priority changed from normal to high
  • Severity changed from normal to major

Raising Severity and Priority for 3.0

comment:19 in reply to: ↑ 17 @miqrogroove5 years ago

Replying to jdingman:

+1, if a post doesn't exist, it should return 404 as the status code, not 200, which it currently does

If I can get support for this issue on posts but not categories, I will take what I can get.

comment:20 @beaulebens5 years ago

If a request is for a specific post_id (e.g. ?p=123) and that post_id does not exist within wp_posts, then I'd agree, it should return a 404; that content is truly not found.

In the specific example cited on this ticket though, where we're talking about a Category, which does exist, but doesn't contain any posts, then I think 200 is an appropriate response code (the Category was indeed found after all).

comment:23 @miqrogroove5 years ago

(!empty($_SERVER['QUERY_STRING']) && (false === strpos($_SERVER['REQUEST_URI'], '?')))

ow, my brain, after reading this... :(

comment:24 @miqrogroove5 years ago

Discussion spilled over to #12250 for clarity.

This ticket will likely end up wontfix.

comment:25 @aaroncampbell5 years ago

I just wanted to echo beaulebens, if a category, tag, or author exists and just has no posts, it should give 200 not 404. If the category, tag, or author doesn't exist, that's a different story.

comment:26 @miqrogroove5 years ago

  • Milestone 3.0 deleted
  • Resolution set to wontfix
  • Status changed from reopened to closed

No traction for remaining issues.

comment:27 @boonebgorges6 weeks ago

#20203 was marked as a duplicate.

Note: See TracTickets for help on using tickets.