SwiftStack
Blog

Using CORS With Swift

What is CORS?

Cross-Origin Resource Sharing, or CORS, is a draft standard that enables web applications to make client-side requests to resources on another domain.

Normally browsers limit client-side code (eg JavaScript) by only allowing the code to access resources hosted on the same domain as the code that is running. This prevents malicious sites from presenting themselves as trusted sites. Under this “same-origin” security model, http://evil.example.com/ will not be able to load your bank’s web content and masquerade as a legitimate site. However, the same-origin security policy has the side effect of limiting some web application developers, too. The same-origin policy prevents a web application hosted at http://app.example.com from uploading images directly to http://images.example.com. CORS is the standard way to tell a browser that both sites are trusted and requests between the two should be allowed.

CORS and Swift

OpenStack Swift allows users to set CORS headers on data stored in Swift. This gives application developers the flexibility to upload data to Swift or host web content directly from Swift without having to build and maintain a separate proxying layer to get around the same-origin security model.

CORS headers in Swift are implemented on a per-container basis. To use CORS headers on data in your Swift cluster, set the appropriate metadata headers on your containers. Setting this container metadata causes all requests for objects in that container to return with the CORS headers and respond appropriately to OPTIONS requests.

The headers you can set on your containers are:

X-Container-Meta-Access-Control-Allow-Origin
X-Container-Meta-Access-Control-Max-Age
X-Container-Meta-Access-Control-Allow-Headers
X-Container-Meta-Access-Control-Expose-Headers

These are standard container metadata headers, but when a CORS request is made to the container or to an object in the container, these metadata entries are set on the response.

A Simple Demo

Let’s play with the CORS functionality in Swift.

First, let’s create a container with the CORS headers:

curl -i -XPUT -H "X-Auth-Token: exampletoken" \
    -H "X-Container-Meta-Access-Control-Allow-Origin: http://webapp.example.com" \
    http://swift.example.com/v1/AUTH_example/c

You can, of course, set headers on existing containers with a POST request.

Next let’s create an object in that container:

curl -i -XPUT --data-binary 1234 -H "X-Auth-Token: exampletoken" \
    -H "X-Container-Meta-Access-Control-Allow-Origin: http://webapp.example.com" \
    http://swift.example.com/v1/AUTH_example/c/o

And now we can make CORS requests and see what happens. The first request is the CORS pre-flight request. The draft spec defines a successful response as having a 200 status code and anything else as a CORS pre-flight request failure.

curl -i -XOPTIONS -H "X-Auth-Token: exampletoken" \
    -H "Origin: http://webapp.example.com" \
    -H "Access-Control-Request-Method: POST" \
    http://swift.example.com/v1/AUTH_example/c/o
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://webapp.example.com
Access-Control-Allow-Methods: HEAD, GET, PUT, POST, COPY, OPTIONS, DELETE
Access-Control-Allow-Headers: x-auth-token
Allow: HEAD, GET, PUT, POST, COPY, OPTIONS, DELETE
Content-Length: 0
X-Trans-Id: txcfd8e244793046fcacbc7df4200e53c3
Date: Sat, 02 Feb 2013 07:35:23 GMT

Since we got a successful response, we can make the actual request:

curl -i -XPOST -H "X-Auth-Token: exampletoken" \
    -H "Content-Type: text/plain" \
    -H "Origin: http://webapp.example.com" \
    http://swift.example.com/v1/AUTH_example/c/o
HTTP/1.1 202 Accepted
Access-Control-Allow-Origin: http://webapp.example.com
Content-Type: text/html; charset=UTF-8
Content-Length: 76
Access-Control-Expose-Headers: cache-control, content-language, content-type, expires, last-modified, pragma, etag, x-timestamp, x-trans-id
X-Trans-Id: txa73ddbc322e84484b542c9f1d39ed9d1
Date: Sat, 02 Feb 2013 07:38:07 GMT

<html><h1>Accepted</h1><p>The request is accepted for processing.</p></html>

This is exactly what would happen if, for example, you had a webapp (running at webapp.example.com) and you wanted to allow your users update data within your Swift cluster directly. The Swift docs include an example Javascript file you can use to test CORS requests against your Swift cluster.

John Dickinson

John Dickinson

Director of Technology, SwiftStack
OpenStack Swift Project Technical Lead

Categories

OpenStack, OpenStack Swift, PlanetOpenstack, SwiftStack

OpenStack Swift API Sprint at PyCon OpenStack Swift Grizzly Release

Comments

© 2014 SwiftStack Inc.        San Francisco, CA         contact@swiftstack.com