0

I'm having an issue with media/attachment files and I'm not quite sure how WordPress is returning the URL that it does. I've noticed that I can add anything as a subdirectory structure before a media slug and WordPress will return a 200 header and somehow direct to the correct media. For example:

http://mysite.dev/asdfasdfadsfasdf/media-slug

When the correct URL should be:

http://mysite.dev/media-slug

The incorrect URL returns a 200 HTTP header and the attachment template loads fine even with the correct file. I thought this was happening as a result of something in the canonical.php file but after quite a bit of testing and even deleting everything in that file (in a test environment), WordPress is still doing this. If I do this for regular posts WordPress returns a 301 and redirects to the actual post URL, which is what I would have expected. Anyone know what is different about media? This is happening on a site where a lot is going on but I also tried it on super basic WP install in a test environment. Permalink structure is set to:

/%postname%/

Is this permalink setting part of the problem?

  • what is the case where these incorrect URLs would be an issue? – Milo Apr 1 '14 at 1:32
  • Well, in this case there are missing files on the server and the the slugs are the same as the file names with the exception of dashes instead of periods for the file extension (.pdf instead of -pdf) but instead of 404ing the media post loads with a 200. I'd rather have them 404 to better figure out what files are missing (there are lots of files). Clicking on the link to download the file just brings you back to the media post (first a 301 with the added slash at the end then a 200). These files might have been added with a custom import script - paths look like: /pdfs/filename.pdf – Bjorn Apr 1 '14 at 14:41
  • 1
    an attachment is a post of type attachment, if the associated file was deleted without using the API, then the attachment posts will still exist. I think you need to instead hook an action before the template is loaded and check if the attached file exists, then set a 404 header yourself. – Milo Apr 1 '14 at 16:33
  • Thanks, great idea. I've implemented that and also added a 1 line htaccess file with "RewriteEngine off" to the old /pdfs/ directory where files are missing from so it will 404 in case there are any direct links to the files anywhere. – Bjorn Apr 1 '14 at 20:21
2

Milo got me on the right track. If anyone else happens to have this issue the code I used is:

/**
* Redirect broken attachment links to 404
*/

function ww_404_broken_links(){
  global $wp_query;

  if(is_attachment()){
    $attachment_path = get_attached_file( get_the_ID() );

    //If the file doesn't exist on the server show 404
    if(!file_exists($attachment_path)){
        $wp_query->set_404();
        status_header( 404 );
        get_template_part( 404 );
        exit();
    }
  }
}

add_action('template_redirect', 'ww_404_broken_links');

I also added an htaccess file in the old files directory with just:

RewriteEngine off

So both the attachment posts and the direct links to the files 404 if the file is missing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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