Htaccess conditional header set is ignoring the condition

.htaccessapache-2.2corshttp-headers

I'm trying to set headers if the origin is a particular site to solve a resource conflict I'm having (using Mautic hosted on a subdomain).

If I add the headers for any situation I get a 500 error when I try to use Mautic, but the resource being accessed from my site works, hence I only want to set them when my site is the origin.

This is what I have:

RewriteEngine On
#preserve HTTP(S)
RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ - [env=proto:http]

<IfModule mod_headers.c>
    SetEnvIfNoCase Origin %{ENV:proto}://mysite.com ENV_SET
    SetEnvIfNoCase Origin %{ENV:proto}://mautic.mysite.com ENV_SET=0
    Header add Access-Control-Allow-Origin %{ENV:proto}://mysite.com env=ENV_SET
    Header set Access-Control-Allow-Credentials true env=ENV_SET
    Header set Access-Control-Allow-Methods: GET, POST, PATCH, PUT, OPTIONS env=ENV_SET
    Header set Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token env=ENV_SET
</IfModule>

As far as I understood that would make the headers set conditionally on existence of the environment variable, but they're being set no matter what. If I remove the SetEnvIf lines they're still set. I did find this which suggests that it should be placed in configuration instead of .htaccess, but I'm not sure what that means.

Any suggestions on how I can fix this, or another way to make it work?

Thanks

EDIT: syntax updated with advice from w3dk, now looks like

    SetEnvIfNoCase Origin "%{ENV:proto}://mysite.com" ENV_SET
    SetEnvIfNoCase Origin "%{ENV:proto}://mautic.mysite.com" !ENV_SET
    Header set Access-Control-Allow-Origin "%{ENV:proto}://mysite.com" env=ENV_SET
    Header set Access-Control-Allow-Credentials "true" env=ENV_SET
    Header set Access-Control-Allow-Methods "GET, POST, PATCH, PUT, OPTIONS" env=ENV_SET
    Header set Access-Control-Allow-Headers "Origin, Content-Type, X-Auth-Token" env=ENV_SET

EDIT 2: Turns out it doesn't like the %{ENV:proto} part, so I've changed that to http and added another line for https. The subdomain is working fine and the headers are setting, except that I'm getting 'Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is 'true, true'.' in the console. It's only being set once (I also tried 'merge', and I'm using set for the Allow-Origin; I can't figure out where else this would be set.

Best Answer

Header set Access-Control-Allow-Methods: GET, POST, PATCH, PUT, OPTIONS env=ENV_SET

If the value contains spaces then it should be surrounded in double quotes. Probably safer to always enclose the value in quotes. You should also omit the : at the end of the header name. So, for example:

Header set Access-Control-Allow-Methods "GET, POST, PATCH, PUT, OPTIONS" env=ENV_SET
SetEnvIfNoCase Origin %{ENV:proto}://mautic.mysite.com ENV_SET=0

UPDATE: The third argument to SetEnvIf[NoCase] is a regex, so server variables (ie. %{ENV:proto} are not expanded - they will be matched literally. If you need to match either http or https then build that into a single regex, eg. https? (The ? makes the previous character optional). (However, your site should be either one or the other, not both?)

To unset/remove an environment variable, you should prefix it with an ! (exclamation mark) rather than set it to 0 (this is still set). For example:

SetEnvIfNoCase Origin https?://mautic.mysite.com !ENV_SET

If I remove the SetEnvIf lines they're still set.

Probably because of failing to quote the header value. But this could also be a caching issue - so make sure all caches are cleared.

...it should be placed in configuration instead of .htaccess

By "configuration" they are probably referring to the server config. This would be preferable (and disable the use of .htaccess files). However, it's not the cause of this issue.