.htaccess - how to set headers dynamically per domain? - apache

I'm trying to get CORS functioning with multiple domains.
Header add Access-Control-Allow-Origin "http://localhost, http://multiplay.io"
However, it seems that most browsers only support one domain. I've been told that the solution is to set the header per incoming domain.
How do you do this using the .htaccess file?

If it's only two values you wish to alternate between, you can use SetEnvIf to differentiate between the two.
SetEnvIf Referer "^http://localhost/" is_localhost
Header add Access-Control-Allow-Origin http://localhost env=is_localhost
Header add Access-Control-Allow-Origin http://multiplay.io env!=is_localhost
There may be a more elegant solution, but something like the above (untested) directives should work.
(Note that it is trivial to forge a Referer header, so be aware of the security implications of forged Referer headers when using Referer headers for pretty much anything.)
Additionally, if you just want to allow all hosts, you can specify * instead of listing multiple hostnames:
Header add Access-Control-Allow-Origin *
But I assume you already knew that and don't want to be that permissive.

Related

Get mod_proxy to pass a custom header to backend

I have a Python backend that is being reverse proxied by Apache/mod_proxy using fcgi (httpd 2.4 on rhel7).
I have a client that sets a custom header in the request, however mod_proxy does not appear to be sending that header on to the backend.
I know something similar exists for the host as ProxyPreserveHost - I would like to know how to do something similar for a custom header.
Can I do that with mod_proxy, or will I need to fall back on to mod_rewrite in some way?
TIA
It seems this line preserves the Header for reasons I don't quite understand:
SetEnvIf HTTP_MY_HEADER "(.*)" MY_HEADER=$0
The reason I don't understand this is that I am setting an Env var here, not a header -- are Env vars automatically turned into headers?
I though I might have to do this also, but was unnecessary:
RequestHeader set HTTP_MY_HEADER "${MY_HEADER}e"
I suppose this is an answer as "it works", although I would love to know why...

htaccess: Access-Control-Allow-Origin wildcard for TLD? (.com, .org...)

Is there a wildcard for any top level domain in .htaccess for Access-Control-Allow-Origin?
I want to allow all top level domains (and any subdomain) of *.example.*.
So: example.com, example.org, any.example.com ...
Currently it works with:
SetEnvIf Origin ^(https?://.+\.example\.com(?::\d{1,5})?|https?://.+\.example\.org(?::\d{1,5})?)$ CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin %{CORS_ALLOW_ORIGIN}e env=CORS_ALLOW_ORIGIN
Header merge Vary "Origin"
You can't specify a partial wildcard in the response.
You need to write code which examines the Origin request header, checks that it is acceptable and then echos it back in the response.

mod_rewrite: add a header if it doesn't already exist

I am attempting to add CORS handling using apache and mod_rewrite. The apache instance is front-ending multiple tomcat applications using mod_jk. Some of these applications have their own logic for adding CORS headers Access-Control-Allow-Origin, Access-Control-Max-Age, etc.
For the applications that didn't take care of the CORS logic, I would like to manage it on apache using mod rewrite.
Does anyone know if its possible to add a header to an HTTP response using mod_rewrite only if the header doesn't already exist? The browser reports an error if the CORS origin header is written twice.
mod_rewrite is to rewrite url's, not to set headers. What you want to use is mod_headers (documentation).
I don't know if mod_rewrite runs before mod_headers, but I would suggest to set environment variables using SetEnvIf instead (documentation).
You can do something like this:
SetEnvIf Request_URI "^/my/app/(.*)/?$" ADDHEADERS=1
Header set Access-Control-Max-Age 123456 env=ADDHEADERS

Can you use mod_rewrite to remove user-agent

Our application has a filter that uses the user-agent of incoming requests to redirect to our mobile site if appropriate. We have recently added a page to our web app that should be referenced by all types. We will be adding whitelist functionality to the filter in the longer term but in the short term we would like a simple way to stop the filter from triggering.
If we can remove or overwrite the user-agent from the request we will achieve our short-term aim, but this needs to be done in such a way so to avoid redeploying. Something like a mod_rewrite rule would be ideal.
Can mod_rewrite, or something similar, do the job? It would need to be a standard apache module so we don't have to do more than add a line or two of config.
Adendum:
Looks like we can use the following combination (or something similar)
SetEnvIf REQUEST_URI "special/uri/path" delete_user_agent
RequestHeader unset User-Agent env=delete_user_agent
No, you cannot do it with mod_rewrite: it can use User-Agent header in conditions, but cannot change it. What you need perhaps is mod_headers.
This module provides directives to control and modify HTTP request and
response headers. Headers can be merged, replaced or removed.
The directive would probably look like this:
RequestHeader unset User-Agent
(You may need to use early here to process this header before mod_rewrite will).

htaccess equivalent to PHP's $_SERVER['SERVER_NAME']?

I have a need to dynamically input the current domain name, into an htaccess file. This would be trivial in PHP but I can't figure out how to do it in "Apache Speak" and my Apache-fu is weak.
For the record, I've tried this:
SetEnvIfNoCase Referer %{SERVER_NAME} internal
and this:
SetEnvIfNoCase Referer %{HTTP_HOST} internal
but frankly I'm not sure if I'm even on the right track at all. The end result I'm after would look something like:
SetEnvIfNoCase Referer currentdomain.com internal
Try asking yourself, is there a different approach to your problem?
If there isn't a simple answer, it's most likely that there is a different way to approach the situation.
For example, if you could insert it dynamically once and write the .htaccess with php, you could possibly save yourself trouble and maybe even efficiency in your code.
There isn't one. If you're running 2.4 then you can use SetEnvIfExpr, but 2.2 or earlier require some work with mod_rewrite.
You can do this:
SetEnvIfNoCase Referer www\.whateveryourdomain\.com internal
The syntax for SetEnvIfNoCase is like this:
SetEnvIfNoCase attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ...
From Apache Docs
attribute can have:
An HTTP request header field (see RFC2616 for more information about these); for example: Host, User-Agent, Referer, and Accept-Language. A regular expression may be used to specify a set of request headers.
One of the following aspects of the request:
Remote_Host - the hostname (if available) of the client making the request
Remote_Addr - the IP address of the client making the request
Server_Addr - the IP address of the server on which the request was received (only with versions later than 2.0.43)
Request_Method - the name of the method being used (GET, POST, et cetera)
Request_Protocol - the name and version of the protocol with which the request was made (e.g., "HTTP/0.9", "HTTP/1.1", etc.)
Request_URI - the resource requested on the HTTP request line -- generally the portion of the URL following the scheme and host portion without the query string. See the RewriteCond directive of mod_rewrite for extra information on how to match your query string.
The name of an environment variable in the list of those associated with the request. This allows SetEnvIf directives to test against the result of prior matches. Only those environment variables defined by earlier SetEnvIf[NoCase] directives are available for testing in this manner. 'Earlier' means that they were defined at a broader scope (such as server-wide) or previously in the current directive's scope. Environment variables will be considered only if there was no match among request characteristics and a regular expression was not used for the attribute.
The same applies for SetEnvIfNoCase.