apache httpd - header merge ignoring existing header - apache

Using apache mod_proxy 2.5 I'm trying to merge or replace an existing access-control-allow-origin header with mod_headers in a proxypass location.
the answer returned from proxied backend already includes a access-control-allow-origin header which I'd like to merge or replace
Header always merge Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "OPTIONS, GET"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token, x-smp-appcid"
This results in a header duplicate which raises an error in all browser cause this header can only occur once.
same is for Header always set although this should replace the existing header.
I also tried to use if module to first check for the headers occurence and only set if unset. but it's somehow hard to look into response headers.
any help is appreciated

I got through the same problem by setting the Access-Control-Allow-Origin and Access-Control-Allow-Credentials headers only when its a preflight request
The second request ( POST, DELETE, PUT etc ) which is handled by the proxied backend ( which already sends the required headers ) is not a preflight request and hence the headers would not be set again by the Apache rules.
To check for preflight request, you could check whether the request contains:
REQUEST_METHOD == OPTIONS
Access-Control-Request-Method !-= ""
Origin != ""
Hope this helps.

Related

Add the Origin from the requests to the Access-Control-Allow-Origin header in the response

I'd like to allow all origins to fetch resources from my apache server.
Instead of adding:
Access-Control-Allow-Origin: *
I would like my server to craft a special response with :
Access-Control-Allow-Origin: <the value of the Origin received in the request>
Is there something I can add to httpd.conf to achieve this ?
Seems it can be achieved by adding those two lines:
SetEnvIf Origin ".*\S.*" ORIGIN=$0
Header always set Access-Control-Allow-Origin %{ORIGIN}e env=ORIGIN
The regex pretty much means anything except newline, tab, and space, so as long as the Origin is not empty add it to the response header.

Apache mod_rewrite pass Headers

I am running my apache on http://localhost:8083 and i am calling an API hosted on local box i.e. http://localhost:8082
I want to map http://localhost:8083/test-call/abc/authorize call to actual service call i.e. http://localhost:8082/TestCall/abc/authorize.
I have rewrite engine as follows in httpd.conf file:
RewriteEngine on
RewriteRule "^/test-call/(.*)$" "http://localhost:8082/TestCall/$1"
I can see that the call is being mapped correctly from developer console of chrome i.e. http://localhost:8082/TestCall/abc/authorize and i have disabled CORS on my browser as i am testing the API call only.
I have added the following headers in my httpd.conf file:
Header set Access-Control-Allow-Origin "http://localhost:8083"
Header always set Access-Control-Allow-Headers "Authorization, X-Requested-With, Content-Type, content-type, x-requested-with, Accept, Access-Control-Allow-Origin, Cache-Control"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Access-Control-Allow-Methods "GET, POST, DELETE, HEAD, OPTIONS"
Header always set Access-Control-Expose-Headers "Content-Security-Policy, Location"
Header always set Access-Control-Max-Age "3600"
Header always set REMOTE_USER "abc.def#db.com"
It's a react application and the bundles are getting loaded correctly with the specified headers above and also the REMOTE_USER is getting added to the REPONSE_HEADERS but for the rewritten URL, the headers are not getting applied.
I want to pass the REMOTE_USER header in the API call after rewrite/redirect.
I have enabled mod_headers and mod_rewrite.
What am i missing?

Disable Access-Control-Allow-Origin from apache or htaccess

In my local machine when I try to send a request via ajax using cross domain the request doesn't complete. I added this options to my .htaccess file:
Header always set Access-Control-Allow-Origin "https://accepted-domain"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
After that, everything worked just fine but when I uploaded this to my cPanel server the request didn't complete.
However, if I remove these lines from the .htaccess file everything works just fine.
The question is: How to disable this Access-Control-Allow-Origin in my cPanel host to define it with the domain I want to accept only ?
UPDATED
When I sent the request on my cPanel hosting the response was this message:
Failed to load http://receiver-domain.com/create.php: The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed. Origin 'http://sender-domain.com' is therefore not allowed access.
Which means the Access-Control-Allow-Origin has been set somewhere else.

httpd duplicate Access-Control-Allow-Origin with "Header always set"

I am trying to enable CORS on my server. It hosts both an Apache HTTPD and an Apache Tomee.
HTTPD is configured as:
SetEnvIf Origin "^https://(.+\.)?my-domain.com$" allowed_origin=$0
Header always set Access-Control-Allow-Origin %{allowed_origin}e env=allowed_origin
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS, HEAD, PUT, DELETE, PATCH"
Header set Access-Control-Allow-Headers "accept,x-requested-method,origin,x-requested-with,x-request,cache-control,content-type"
Header set Access-Control-Max-Age "600"
and my Tomee web XML :
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Language,Keep-Alive</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT,PATCH,DELETE</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
My problem is I get the Access-Control-Allow-Credentials header twice in the response to the preflight OPTIONS request :
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://my-origin.my-domain.com
Access-Control-Allow-Origin: https://my-origin.my-domain.com
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 600
Access-Control-Allow-Methods: GET, POST, OPTIONS, HEAD, PUT, DELETE, PATCH
Access-Control-Allow-Headers: accept,x-requested-method,origin,x-requested-with,x-request,cache-control,content-type,authorization
I don't understand why the usage of the set keyword in my HTTPD configuration does not remove the duplicate Access-Control-Allow-Origin.
Moreover, if I remove the 'always' keyword it returns one Access-Control-Allow-Origin only...
Experiencing a similar issue. Spent a lot of time in debugging.
It is a bug in Apache. A failure of the internal design and a failure to document it.
Header [table] set [cookie] [value] [...]
That's the command to manipulate headers. There are at least two cookie tables in apache.
onsuccess, default, used for 20X status codes.
always, used for errors, including redirects codes.
Judging by my experience in the wild, all cookies from all tables are appended to the response.
In your example, the cookie set by Tomcat is in the onsuccess table, the cookie sets in apache is in the always table. The response gets both cookies, hence the duplication.
It gets more messy than that. The tables have different meaning depending on what modules are in use. For instance, when using proxy or CGI, the relevant table for cookies is onsuccess if the upstream server delivers an error successfully, but always if an internal apache error occurs.
This behavior is not documented. That seems not intentional but a consequence of apache internals. In the current state, it is basically impossible to manipulate headers properly with Apache.
The accepted answer is correct. This is just a way of handling it that I've been using.
SetEnvIf Origin "^(.*(\.yoursite.com)[:0-9]*)$" cors=$1
# wash out these headers in the 'onsuccess' table if we get them from the backend
Header onsuccess unset Access-Control-Allow-Origin env=cors
Header onsuccess unset Access-Control-Allow-Credentials env=cors
Header onsuccess unset Access-Control-Allow-Methods env=cors
Header onsuccess unset Access-Control-Allow-Headers env=cors
# add them to the 'always' table
Header always set Access-Control-Allow-Origin %{cors}e env=cors
Header always set Access-Control-Allow-Credentials "true" env=cors
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, PUT, DELETE" env=cors
Header always set Access-Control-Allow-Headers "accept,x-requested-method,origin" env=cors

Apache httpd: Conditionally set response header based on other *response* header

Is there a way to set a new response header conditionally, where the condition uses another response header? Specifically, the new response header should be set only if the response has a certain Content-Type.
I have looked into mod_headers in combination with mod_setenvif but it looks like conditions can only use request headers, not response headers.
Thanks, John
Apache 2.4 is the answer:
Set Cache-Control header when response content type is application/pdf
Header set Cache-Control "no-store,no-transform" "expr=%{resp:Content-Type} =~ m|application/pdf|"
Do NOT try with the IF directive. It is evaluated too early in the process. For example, the following will NOT work:
<If "%{resp:Content-Type} =~ m|application/pdf|">
Header set Cache-Control "no-store, no-transform"
</If>