magento2: HEAD request returns 404

Preconditions (*)

  1. Magento 2.3.0
  2. HTTPS
  3. Nginx

Steps to reproduce (*)

  1. Clear FPC and don’t access the site
  2. Run curl -X HEAD -i https://demo1-m2.mage.direct/ or curl -I https://demo1-m2.mage.direct/
  3. After couple of HEAD requests with response 404 the home page gets cached and after that any valid GET request returns 404 until FPC is refreshed.

Expected result (*)

  1. I expect HEAD request to return 200 and not 404

Actual result (*)

  1. HEAD request returns 404

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 9
  • Comments: 36 (31 by maintainers)

Commits related to this issue

Most upvoted comments

This is an issue with the Magento built-in full page cache. Here’s a quick fix for the issue while waiting for Magento to fix the root cause in the core:

Add this plugin in a di.xml somewhere

<type name="Magento\Framework\App\PageCache\Kernel">
    <plugin name="prevent_caching_404_head_results" type="VENDOR\MODULE\Plugin\PreventCachingHead404ResultsPlugin" />
</type>

And create the following class in the path defined by the di.xml file

<?php

namespace VENDOR\MODULE\Plugin;

class PreventCachingHead404ResultsPlugin
{
    /**
     * @var \Magento\Framework\App\Request\Http
     */
    protected $request;

    /**
     * PreventCachingHeadRequestsPlugin constructor.
     * @param \Magento\Framework\App\Request\Http $request
     */
    public function __construct(\Magento\Framework\App\Request\Http $request)
    {
        $this->request = $request;
    }

    /**
     * Prevent caching HEAD requests that return a 404 result
     * @param \Magento\Framework\App\PageCache\Kernel $subject
     * @param callable $proceed
     * @param \Magento\Framework\App\Response\Http $response
     * @return void
     */
    public function aroundProcess(
        \Magento\Framework\App\PageCache\Kernel $subject,
        callable $proceed,
        \Magento\Framework\App\Response\Http $response
    ) {
        if ($this->request->isHead() && $response->getHttpResponseCode() == 404) {
            return;
        }
        return $proceed($response);
    }
}

Alternatively you can disable the fullpage cache, but that is not advisable since it affects performance. Better solution is to put the store behind a Varnish cache, since that seems to be unaffected by this.

Got it. I only patched app/etc/di.xml, but now I understood that I (also?) have to patch the file vendor/magento/magento2-base/app/etc/di.xml. Thanks @mattijv!

@SteveEdson While waiting for the next release you can do a couple interim fixes:

  1. Setup a Varnish cache infront of your Magento installation and use that instead of the Magento built-in full page cache. Running a Varnish cache is in any case beneficial.

and/or

  1. Apply the change in this commit to the app/etc/di.xml file. That is the most important change to prevent HEAD requests from 404’ing your controllers (the rest is just fluff about handling the HEAD requests up to spec).

Have a production mode 2.3 site with Nginx that sometimes serves homepage as a 404 think this might be why. Suspect head requests sent by a “down notifier” service and then the 404 is cached and served up by full page cache.

Confirm 404 when doing Head request, flushing FPC cleans it out.

jQuery.ajax({ type: "HEAD", async: true, url: '/', }).done(function(message,text,jqXHR){ console.log(message, text, jqXHR.status) });

Someone made a plugin module to work around this in the meantime, same as mattijv’s earlier post. https://github.com/magic42/module-prevent-head-404-cache

HEAD requests should be supported automatically (on the framework level) for all GET requests, just w/o body. Caching should take this into account (GET should have separate cache to avoid empty body).

Looks like also supported by @Vinai