title: Why Do My HTTP Headers only apply to sub-documents?
body: <p>I have created an htaccess file for my multi-site Wordpress website, which contains the standard rewrite rules followed by a mod_headers section, with conditional FilesMatch directives.</p>
  
  <p>The http headers all apply correctly to subdocuments of any Wordpress page (e.g. png, jpg, js, css etc), but <strong>never</strong> apply to the root document. Another pure html site on the same host does receive the headers correctly.</p>
  
  <p>For example:
      <code>https://www.somedomain.com/site.css</code>
  returns:</p>
  
  <pre><code>    HTTP/2 200 OK
      content-type: text/css
      date: Mon, 30 Mar 2020 09:36:10 GMT
      server: Apache
      x-content-type-options: nosniff
      last-modified: Sun, 29 Mar 2020 12:55:43 GMT
      etag: "14546d-5a1fdda3e88c5-gzip"
      accept-ranges: bytes
      cache-control: must-revalidate, public, max-age=31536000
      expires: Sat, 20 Mar 2021 09:36:10 GMT
      vary: Accept-Encoding,User-Agent
      content-encoding: gzip
  </code></pre>
  
  <p>but <code>https://www.somedomain.com/</code> only returns:</p>
  
  <pre><code>HTTP/1.1 200 Connection established
  content-type: text/html; charset=UTF-8
  date: Mon, 30 Mar 2020 09:36:09 GMT
  server: Apache
  x-powered-by: PHP/7.3.16
  cache-control: no-cache
  content-encoding: gzip
  </code></pre>
  
  <p>The htaccess code is below:</p>
  
  <pre><code>#BEGIN WordPress
  &lt;IfModule mod_rewrite.c&gt;
  RewriteEngine On
      RewriteBase /
      RewriteRule ^index\.php$ - [L]
  
  #add a trailing slash to /wp-admin
      RewriteRule ^wp-admin$ wp-admin/ [R=301,L]
  
      RewriteCond %{REQUEST_FILENAME} -f [OR]
      RewriteCond %{REQUEST_FILENAME} -d
      RewriteRule ^ - [L]
      RewriteRule ^(wp-(content|admin|includes).*) web/$1 [L]
      RewriteRule ^(.*\.php)$ web/$1 [L]
      RewriteRule . index.php [L]
  &lt;/IfModule&gt;
  #END WordPress
  
  #BEGIN Headers
  &lt;IfModule mod_headers.c&gt;
  #Remove server headers
      Header always unset X-Redirect-By
      Header always unset X-Powered-By
      Header always unset Location
  #Set server headers
      Header always set X-Content-Type-Options nosniff
      Header append Vary "Accept-Encoding, User-Agent"
  #Set Cache-Control
      &lt;FilesMatch "\.(ico|jpe?g|png|gif|svg|webp|swf|css|mp4)$"&gt;
          Header set Cache-Control "must-revalidate, public, max-age=31536000"
      &lt;/FilesMatch&gt;
      &lt;FilesMatch "\.(js)$"&gt;
          Header set Cache-Control "private"
      &lt;/FilesMatch&gt;
      &lt;FilesMatch "\.(php|x?html?|pdf|xlsx?|docx?|pptx?|zipx?)$"&gt;
          Header set Cache-Control "private, must-revalidate"
      &lt;/FilesMatch&gt;
  #PHP/HTML specific headers
      &lt;FilesMatch "\.(php|x?html?)$"&gt;
          Header always set X-Frame-Options "SAMEORIGIN"
          Header always set X-DNS-Prefetch-Control "on"
          Header always set Connection "keep-alive"
          Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
          Header always set Referrer-Policy "strict-origin-when-cross-origin"
          Header always set X-Clacks-Overhead "GNU Terry Pratchett"
      &lt;/FilesMatch&gt;
   &lt;/IfModule&gt;
  #END Headers
  </code></pre>