Where i should put Access-Control-Max-Age on preflight response header or xhr response header?
Access-Control-Max-Age
It should be set on the OPTIONS PREFLIGHT request, as it tells the browser for how long it can cache the preflight response data.
The Access-Control-Max-Age response header indicates how long the
results of a preflight request (that is the information contained in
the Access-Control-Allow-Methods and Access-Control-Allow-Headers
headers) can be cached.
Source https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
Related
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?
General:
Request URL:x/site.php
Request Method:OPTIONS
Status Code:302 Found
Remote Address:x.x.x.x:80
Response Headers:
view source
Access-Control-Allow-Headers:Content-Type
Access-Control-Allow-Origin:*
Access-Control-Max-Age:300
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Length:0
Content-Type:text/html; charset=UTF-8
Date:Thu, 02 Mar 2017 14:27:21 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Location:y
Pragma:no-cache
Server:Apache/2.4.25 (Ubuntu)
Request Headers:
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
DNT:1
Host:x
Origin:http://127.0.0.1:3000
Pragma:no-cache
Referer:http://127.0.0.1:3000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.90 Safari/537.36
Apache virtualhost config looks as so:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "http://127.0.0.1:3000"
Header set Access-Control-Allow-Origin "http://127.0.0.1"
Header set Access-Control-Max-Age "300"
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
Header set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, PATCH, OPTIONS"
</IfModule>
The preflight request is skipping the apache config and hitting my webapp directly, which does a redirect (hence the 302 and the location: y).
I don't know why the preflight request is not being handled by apache?
To fully CORS-enable an Apache web server, you need to have it configured to look like this:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Headers "Authorization"
Header always set Access-Control-Allow-Methods "GET"
Header always set Access-Control-Expose-Headers "Content-Security-Policy, Location"
Header always set Access-Control-Max-Age "600"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
Longer explanation at https://benjaminhorn.io/code/setting-cors-cross-origin-resource-sharing-on-apache-with-correct-response-headers-allowing-everything-through/
Some general notes on what values to set for the various Access-Control- response headers:
Access-Control-Allow-Headers: you must set it to include any header names your request sends except CORS-safelisted header names or so-called “forbidden” header names (names of headers set by the browser that you can’t set in your JavaScript); the spec alternatively allows the * wildcard as its value—so you can try it, though some browsers may not support it yet: Chrome bug, Firefox bug, Safari bug.
Access-Control-Allow-Methods: the spec alternatively allows the * wildcard—but again, as with Access-Control-Allow-Headers: *, some browsers may not support it yet.
Access-Control-Expose-Headers: set to include any response headers beyond Expires, Cache-Control, Content-Type, Pragma, Last-Modified, and Content-Language that your frontend code needs to read. A lot of people forget to set this and end up baffled about why they can’t read the value of a particular response header). Again the spec alternatively allows the * wildcard here, but some browsers may not support it yet.
Access-Control-Max-Age: Chrome has an upper limit of 600 (10 minutes) hardcoded, so there’s no point in setting a higher value for it than that (Chrome will just throttle it down to 10 minutes if you set it higher, and Safari limits it to only 5 minutes).
So then, about the particular request shown in the question, the specific changes and additions that would need to made are these:
Use Header always set instead of just Header set.
Use mod_rewrite to handle the OPTIONS by just sending back 200 OK with those headers.
The request has Access-Control-Request-Headers:authorization so in the Apache config, add Authorization in the Access-Control-Allow-Headers response header too.
Origin is a “forbidden” header name set by the browser, and Accept is a CORS-safelisted header name, so no need to include them in Access-Control-Allow-Headers.
The request sends no Content-Type, so no need for it in Access-Control-Allow-Headers in the response (and never needed for GET requests and otherwise only needed if the type is not application/x-www-form-urlencoded, text/plain, or multipart/form-data).
For Access-Control-Allow-Methods, the request seems to just be a GET, so unless the plan’s to also make POST/PUT/DELETE/PATCH requests, no point in including them.
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
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.
I want to request a URL every minute. But before I request the whole page, I want to check if it is updated based on ETag/Content-length/Age in the header. How can I implement this in Scrapy?
check out scrapy downloader middleware it comes with an implementation of RFC2616 policy
Do not attempt to store responses/requests with no-store
cache-control directive set
Do not serve responses from cache if no-cache cache-control directive is set even for fresh responses
Compute freshness lifetime from max-age cache-control directive
Compute freshness lifetime from Expires response header
Compute freshness lifetime from Last-Modified response header (heuristic used by Firefox)
Compute current age from Age response header
Compute current age from Date header
Revalidate stale responses based on Last-Modified response header
Revalidate stale responses based on ETag response header
Set Date header for any received response missing it