CORS is a mechanism to allow code running in a browser (Javascript for example) make requests to a domain other then the one from where it originated.
Swift supports CORS requests to containers and objects.
CORS metadata is held on the container only. The values given apply to the container itself and all objects within it.
The supported headers are,
Metadata | Use |
---|---|
X-Container-Meta-Access-Control-Allow-Origin | Origins to be allowed to make Cross Origin Requests, space separated. |
X-Container-Meta-Access-Control-Max-Age | Max age for the Origin to hold the preflight results. |
X-Container-Meta-Access-Control-Expose-Headers | Headers exposed to the user agent (e.g. browser) in the actual request response. Space separated. |
In addition the the values set in container metadata, some cluster-wide values
may also be configured using the strict_cors_mode
, cors_allow_origin
and cors_expose_headers
in proxy-server.conf
. See
proxy-server.conf-sample
for more information.
Before a browser issues an actual request it may issue a preflight request. The preflight request is an OPTIONS call to verify the Origin is allowed to make the request. The sequence of events are,
When a browser receives a response to an actual request it only exposes those
headers listed in the Access-Control-Expose-Headers
header. By default Swift
returns the following values for this header,
etag
, x-timestamp
, x-trans-id
,
x-openstack-request-id
X-Container-Meta-*
for containers and
X-Object-Meta-*
for objects)X-Container-Meta-Access-Control-Expose-Headers
cors_expose_headers
option in
proxy-server.conf
Note
An OPTIONS request to a symlink object will respond with the options for the symlink only, the request will not be redirected to the target object. Therefore, if the symlink’s target object is in another container with CORS settings, the response will not reflect the settings.
To see some CORS Javascript in action download the test CORS page (source below). Host it on a webserver and take note of the protocol and hostname (origin) you’ll be using to request the page, e.g. http://localhost.
Locate a container you’d like to query. Needless to say the Swift cluster
hosting this container should have CORS support. Append the origin of the
test page to the container’s X-Container-Meta-Access-Control-Allow-Origin
header,:
curl -X POST -H 'X-Auth-Token: xxx' \
-H 'X-Container-Meta-Access-Control-Allow-Origin: http://localhost' \
http://192.168.56.3:8080/v1/AUTH_test/cont1
At this point the container is now accessible to CORS clients hosted on http://localhost. Open the test CORS page in your browser.
Assuming the request succeeds you should see the response header and body. If something went wrong the response status will be 0.
A sample cross-site test page is located in the project source tree
doc/source/test-cors.html
.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Test CORS</title> </head> <body> Token<br><input id="token" type="text" size="64"><br><br> Method<br> <select id="method"> <option value="GET">GET</option> <option value="HEAD">HEAD</option> <option value="POST">POST</option> <option value="DELETE">DELETE</option> <option value="PUT">PUT</option> </select><br><br> URL (Container or Object)<br><input id="url" size="64" type="text"><br><br> <input id="submit" type="button" value="Submit" onclick="submit(); return false;"> <pre id="response_headers"></pre> <p> <hr> <pre id="response_body"></pre> <script type="text/javascript"> function submit() { var token = document.getElementById('token').value; var method = document.getElementById('method').value; var url = document.getElementById('url').value; document.getElementById('response_headers').textContent = null; document.getElementById('response_body').textContent = null; var request = new XMLHttpRequest(); request.onreadystatechange = function (oEvent) { if (request.readyState == 4) { responseHeaders = 'Status: ' + request.status; responseHeaders = responseHeaders + '\nStatus Text: ' + request.statusText; responseHeaders = responseHeaders + '\n\n' + request.getAllResponseHeaders(); document.getElementById('response_headers').textContent = responseHeaders; document.getElementById('response_body').textContent = request.responseText; } } request.open(method, url); if (token != '') { // custom headers always trigger a pre-flight request request.setRequestHeader('X-Auth-Token', token); } request.send(null); } </script> </body> </html>
Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.