diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 5ba6bb8cff2c83c0a496244369c32143b07630f9..4c8c8281ebafbf47cb2447188b2b4666b0cb46a1 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -90,6 +90,10 @@
 			"ImportPath": "github.com/robertkrimen/otto/token",
 			"Rev": "dea31a3d392779af358ec41f77a07fcc7e9d04ba"
 		},
+		{
+			"ImportPath": "github.com/rs/cors",
+			"Rev": "6e0c3cb65fc0fdb064c743d176a620e3ca446dfb"
+		},
 		{
 			"ImportPath": "github.com/syndtr/goleveldb/leveldb",
 			"Rev": "832fa7ed4d28545eab80f19e1831fc004305cade"
diff --git a/Godeps/_workspace/src/github.com/rs/cors/.travis.yml b/Godeps/_workspace/src/github.com/rs/cors/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..bbb5185a2edc87ed46f15fd234ea3243e3aebfad
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/.travis.yml
@@ -0,0 +1,4 @@
+language: go
+go:
+- 1.3
+- 1.4
diff --git a/Godeps/_workspace/src/github.com/rs/cors/LICENSE b/Godeps/_workspace/src/github.com/rs/cors/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..d8e2df5a479a47e6afe311efdda70e2b541ad7a5
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Olivier Poitrey <rs@dailymotion.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Godeps/_workspace/src/github.com/rs/cors/README.md b/Godeps/_workspace/src/github.com/rs/cors/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..6f70c30aca0dca5a0ae93c19cc88429e1114e147
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/README.md
@@ -0,0 +1,84 @@
+# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![build](https://img.shields.io/travis/rs/cors.svg?style=flat)](https://travis-ci.org/rs/cors)
+
+CORS is a `net/http` handler implementing [Cross Origin Resource Sharing W3 specification](http://www.w3.org/TR/cors/) in Golang.
+
+## Getting Started
+
+After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`.
+
+```go
+package main
+
+import (
+    "net/http"
+
+    "github.com/rs/cors"
+)
+
+func main() {
+    h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+        w.Header().Set("Content-Type", "application/json")
+        w.Write([]byte("{\"hello\": \"world\"}"))
+    })
+
+    // cors.Default() setup the middleware with default options being
+    // all origins accepted with simple methods (GET, POST). See
+    // documentation below for more options.
+    handler = cors.Default().Handler(h)
+    http.ListenAndServe(":8080", handler)
+}
+```
+
+Install `cors`:
+
+    go get github.com/rs/cors
+
+Then run your server:
+
+    go run server.go
+
+The server now runs on `localhost:8080`:
+
+    $ curl -D - -H 'Origin: http://foo.com' http://localhost:8080/
+    HTTP/1.1 200 OK
+    Access-Control-Allow-Origin: foo.com
+    Content-Type: application/json
+    Date: Sat, 25 Oct 2014 03:43:57 GMT
+    Content-Length: 18
+
+    {"hello": "world"}
+
+### More Examples
+
+* `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go)
+* [Goji](https://goji.io): [examples/goji/server.go](https://github.com/rs/cors/blob/master/examples/goji/server.go)
+* [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go)
+* [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go)
+* [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go)
+
+## Parameters
+
+Parameters are passed to the middleware thru the `cors.New` method as follow:
+
+```go
+c := cors.New(cors.Options{
+    AllowedOrigins: []string{"http://foo.com"},
+    AllowCredentials: true,
+})
+
+// Insert the middleware
+handler = c.Handler(handler)
+```
+
+* **AllowedOrigins** `[]string`: A list of origins a cross-domain request can be executed from. If the special `*` value is present in the list, all origins will be allowed. The default value is `*`.
+* **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests.
+* **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`)
+* **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification
+* **AllowCredentials** `bool`: Indicates whether the request can include user credentials like cookies, HTTP authentication or client side SSL certificates. The default is `false`.
+* **MaxAge** `int`: Indicates how long (in seconds) the results of a preflight request can be cached. The default is `0` which stands for no max age.
+
+See [API documentation](http://godoc.org/github.com/rs/cors) for more info.
+
+## Licenses
+
+All source code is licensed under the [MIT License](https://raw.github.com/rs/cors/master/LICENSE).
diff --git a/Godeps/_workspace/src/github.com/rs/cors/bench_test.go b/Godeps/_workspace/src/github.com/rs/cors/bench_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..454375d2cca55292067021b527543d5a1e4426ce
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/bench_test.go
@@ -0,0 +1,37 @@
+package cors
+
+import (
+	"net/http"
+	"net/http/httptest"
+	"testing"
+)
+
+func BenchmarkWithout(b *testing.B) {
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
+
+	for i := 0; i < b.N; i++ {
+		testHandler.ServeHTTP(res, req)
+	}
+}
+
+func BenchmarkDefault(b *testing.B) {
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
+	handler := Default()
+
+	for i := 0; i < b.N; i++ {
+		handler.Handler(testHandler).ServeHTTP(res, req)
+	}
+}
+
+func BenchmarkPreflight(b *testing.B) {
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Access-Control-Request-Method", "GET")
+	handler := Default()
+
+	for i := 0; i < b.N; i++ {
+		handler.Handler(testHandler).ServeHTTP(res, req)
+	}
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/cors.go b/Godeps/_workspace/src/github.com/rs/cors/cors.go
new file mode 100644
index 0000000000000000000000000000000000000000..276bc40bb2c37953d9ba8b325735894c4d5191ad
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/cors.go
@@ -0,0 +1,308 @@
+/*
+Package cors is net/http handler to handle CORS related requests
+as defined by http://www.w3.org/TR/cors/
+
+You can configure it by passing an option struct to cors.New:
+
+    c := cors.New(cors.Options{
+        AllowedOrigins: []string{"foo.com"},
+        AllowedMethods: []string{"GET", "POST", "DELETE"},
+        AllowCredentials: true,
+    })
+
+Then insert the handler in the chain:
+
+    handler = c.Handler(handler)
+
+See Options documentation for more options.
+
+The resulting handler is a standard net/http handler.
+*/
+package cors
+
+import (
+	"log"
+	"net/http"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// Options is a configuration container to setup the CORS middleware.
+type Options struct {
+	// AllowedOrigins is a list of origins a cross-domain request can be executed from.
+	// If the special "*" value is present in the list, all origins will be allowed.
+	// Default value is ["*"]
+	AllowedOrigins []string
+	// AllowedMethods is a list of methods the client is allowed to use with
+	// cross-domain requests. Default value is simple methods (GET and POST)
+	AllowedMethods []string
+	// AllowedHeaders is list of non simple headers the client is allowed to use with
+	// cross-domain requests.
+	// If the special "*" value is present in the list, all headers will be allowed.
+	// Default value is [] but "Origin" is always appended to the list.
+	AllowedHeaders []string
+	// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
+	// API specification
+	ExposedHeaders []string
+	// AllowCredentials indicates whether the request can include user credentials like
+	// cookies, HTTP authentication or client side SSL certificates.
+	AllowCredentials bool
+	// MaxAge indicates how long (in seconds) the results of a preflight request
+	// can be cached
+	MaxAge int
+	// Debugging flag adds additional output to debug server side CORS issues
+	Debug bool
+	// log object to use when debugging
+	log *log.Logger
+}
+
+type Cors struct {
+	// The CORS Options
+	options Options
+}
+
+// New creates a new Cors handler with the provided options.
+func New(options Options) *Cors {
+	// Normalize options
+	// Note: for origins and methods matching, the spec requires a case-sensitive matching.
+	// As it may error prone, we chose to ignore the spec here.
+	normOptions := Options{
+		AllowedOrigins: convert(options.AllowedOrigins, strings.ToLower),
+		AllowedMethods: convert(options.AllowedMethods, strings.ToUpper),
+		// Origin is always appended as some browsers will always request
+		// for this header at preflight
+		AllowedHeaders:   convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey),
+		ExposedHeaders:   convert(options.ExposedHeaders, http.CanonicalHeaderKey),
+		AllowCredentials: options.AllowCredentials,
+		MaxAge:           options.MaxAge,
+		Debug:            options.Debug,
+		log:              log.New(os.Stdout, "[cors] ", log.LstdFlags),
+	}
+	if len(normOptions.AllowedOrigins) == 0 {
+		// Default is all origins
+		normOptions.AllowedOrigins = []string{"*"}
+	}
+	if len(normOptions.AllowedHeaders) == 1 {
+		// Add some sensible defaults
+		normOptions.AllowedHeaders = []string{"Origin", "Accept", "Content-Type"}
+	}
+	if len(normOptions.AllowedMethods) == 0 {
+		// Default is simple methods
+		normOptions.AllowedMethods = []string{"GET", "POST"}
+	}
+
+	if normOptions.Debug {
+		normOptions.log.Printf("Options: %v", normOptions)
+	}
+	return &Cors{
+		options: normOptions,
+	}
+}
+
+// Default creates a new Cors handler with default options
+func Default() *Cors {
+	return New(Options{})
+}
+
+// Handler apply the CORS specification on the request, and add relevant CORS headers
+// as necessary.
+func (cors *Cors) Handler(h http.Handler) http.Handler {
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if r.Method == "OPTIONS" {
+			cors.logf("Handler: Preflight request")
+			cors.handlePreflight(w, r)
+			// Preflight requests are standalone and should stop the chain as some other
+			// middleware may not handle OPTIONS requests correctly. One typical example
+			// is authentication middleware ; OPTIONS requests won't carry authentication
+			// headers (see #1)
+		} else {
+			cors.logf("Handler: Actual request")
+			cors.handleActualRequest(w, r)
+			h.ServeHTTP(w, r)
+		}
+	})
+}
+
+// Martini compatible handler
+func (cors *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) {
+	if r.Method == "OPTIONS" {
+		cors.logf("HandlerFunc: Preflight request")
+		cors.handlePreflight(w, r)
+	} else {
+		cors.logf("HandlerFunc: Actual request")
+		cors.handleActualRequest(w, r)
+	}
+}
+
+// Negroni compatible interface
+func (cors *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+	if r.Method == "OPTIONS" {
+		cors.logf("ServeHTTP: Preflight request")
+		cors.handlePreflight(w, r)
+		// Preflight requests are standalone and should stop the chain as some other
+		// middleware may not handle OPTIONS requests correctly. One typical example
+		// is authentication middleware ; OPTIONS requests won't carry authentication
+		// headers (see #1)
+	} else {
+		cors.logf("ServeHTTP: Actual request")
+		cors.handleActualRequest(w, r)
+		next(w, r)
+	}
+}
+
+// handlePreflight handles pre-flight CORS requests
+func (cors *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
+	options := cors.options
+	headers := w.Header()
+	origin := r.Header.Get("Origin")
+
+	if r.Method != "OPTIONS" {
+		cors.logf("  Preflight aborted: %s!=OPTIONS", r.Method)
+		return
+	}
+	if origin == "" {
+		cors.logf("  Preflight aborted: empty origin")
+		return
+	}
+	if !cors.isOriginAllowed(origin) {
+		cors.logf("  Preflight aborted: origin '%s' not allowed", origin)
+		return
+	}
+
+	reqMethod := r.Header.Get("Access-Control-Request-Method")
+	if !cors.isMethodAllowed(reqMethod) {
+		cors.logf("  Preflight aborted: method '%s' not allowed", reqMethod)
+		return
+	}
+	reqHeaders := parseHeaderList(r.Header.Get("Access-Control-Request-Headers"))
+	if !cors.areHeadersAllowed(reqHeaders) {
+		cors.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders)
+		return
+	}
+	headers.Set("Access-Control-Allow-Origin", origin)
+	headers.Add("Vary", "Origin")
+	// Spec says: Since the list of methods can be unbounded, simply returning the method indicated
+	// by Access-Control-Request-Method (if supported) can be enough
+	headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod))
+	if len(reqHeaders) > 0 {
+
+		// Spec says: Since the list of headers can be unbounded, simply returning supported headers
+		// from Access-Control-Request-Headers can be enough
+		headers.Set("Access-Control-Allow-Headers", strings.Join(reqHeaders, ", "))
+	}
+	if options.AllowCredentials {
+		headers.Set("Access-Control-Allow-Credentials", "true")
+	}
+	if options.MaxAge > 0 {
+		headers.Set("Access-Control-Max-Age", strconv.Itoa(options.MaxAge))
+	}
+	cors.logf("  Preflight response headers: %v", headers)
+}
+
+// handleActualRequest handles simple cross-origin requests, actual request or redirects
+func (cors *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
+	options := cors.options
+	headers := w.Header()
+	origin := r.Header.Get("Origin")
+
+	if r.Method == "OPTIONS" {
+		cors.logf("  Actual request no headers added: method == %s", r.Method)
+		return
+	}
+	if origin == "" {
+		cors.logf("  Actual request no headers added: missing origin")
+		return
+	}
+	if !cors.isOriginAllowed(origin) {
+		cors.logf("  Actual request no headers added: origin '%s' not allowed", origin)
+		return
+	}
+
+	// Note that spec does define a way to specifically disallow a simple method like GET or
+	// POST. Access-Control-Allow-Methods is only used for pre-flight requests and the
+	// spec doesn't instruct to check the allowed methods for simple cross-origin requests.
+	// We think it's a nice feature to be able to have control on those methods though.
+	if !cors.isMethodAllowed(r.Method) {
+		if cors.options.Debug {
+			cors.logf("  Actual request no headers added: method '%s' not allowed",
+				r.Method)
+		}
+
+		return
+	}
+	headers.Set("Access-Control-Allow-Origin", origin)
+	headers.Add("Vary", "Origin")
+	if len(options.ExposedHeaders) > 0 {
+		headers.Set("Access-Control-Expose-Headers", strings.Join(options.ExposedHeaders, ", "))
+	}
+	if options.AllowCredentials {
+		headers.Set("Access-Control-Allow-Credentials", "true")
+	}
+	cors.logf("  Actual response added headers: %v", headers)
+}
+
+// convenience method. checks if debugging is turned on before printing
+func (cors *Cors) logf(format string, a ...interface{}) {
+	if cors.options.Debug {
+		cors.options.log.Printf(format, a...)
+	}
+}
+
+// isOriginAllowed checks if a given origin is allowed to perform cross-domain requests
+// on the endpoint
+func (cors *Cors) isOriginAllowed(origin string) bool {
+	allowedOrigins := cors.options.AllowedOrigins
+	origin = strings.ToLower(origin)
+	for _, allowedOrigin := range allowedOrigins {
+		switch allowedOrigin {
+		case "*":
+			return true
+		case origin:
+			return true
+		}
+	}
+	return false
+}
+
+// isMethodAllowed checks if a given method can be used as part of a cross-domain request
+// on the endpoing
+func (cors *Cors) isMethodAllowed(method string) bool {
+	allowedMethods := cors.options.AllowedMethods
+	if len(allowedMethods) == 0 {
+		// If no method allowed, always return false, even for preflight request
+		return false
+	}
+	method = strings.ToUpper(method)
+	if method == "OPTIONS" {
+		// Always allow preflight requests
+		return true
+	}
+	for _, allowedMethod := range allowedMethods {
+		if allowedMethod == method {
+			return true
+		}
+	}
+	return false
+}
+
+// areHeadersAllowed checks if a given list of headers are allowed to used within
+// a cross-domain request.
+func (cors *Cors) areHeadersAllowed(requestedHeaders []string) bool {
+	if len(requestedHeaders) == 0 {
+		return true
+	}
+	for _, header := range requestedHeaders {
+		found := false
+		for _, allowedHeader := range cors.options.AllowedHeaders {
+			if allowedHeader == "*" || allowedHeader == header {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return false
+		}
+	}
+	return true
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/cors_test.go b/Godeps/_workspace/src/github.com/rs/cors/cors_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..f215018c965ffb3d628744ed165a77df2f5c281b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/cors_test.go
@@ -0,0 +1,288 @@
+package cors
+
+import (
+	"net/http"
+	"net/http/httptest"
+	"testing"
+)
+
+var testHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+	w.Write([]byte("bar"))
+})
+
+func assertHeaders(t *testing.T, resHeaders http.Header, reqHeaders map[string]string) {
+	for name, value := range reqHeaders {
+		if resHeaders.Get(name) != value {
+			t.Errorf("Invalid header `%s', wanted `%s', got `%s'", name, value, resHeaders.Get(name))
+		}
+	}
+}
+
+func TestNoConfig(t *testing.T) {
+	s := New(Options{
+	// Intentionally left blank.
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "",
+		"Access-Control-Allow-Methods":     "",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestWildcardOrigin(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"*"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestAllowedOrigin(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestDisallowedOrigin(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://barbaz.com")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "",
+		"Access-Control-Allow-Methods":     "",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestAllowedMethod(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+		AllowedMethods: []string{"PUT", "DELETE"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+	req.Header.Add("Access-Control-Request-Method", "PUT")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "PUT",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestDisallowedMethod(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+		AllowedMethods: []string{"PUT", "DELETE"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+	req.Header.Add("Access-Control-Request-Method", "PATCH")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "",
+		"Access-Control-Allow-Methods":     "",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestAllowedHeader(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+		AllowedHeaders: []string{"X-Header-1", "x-header-2"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+	req.Header.Add("Access-Control-Request-Method", "GET")
+	req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "GET",
+		"Access-Control-Allow-Headers":     "X-Header-2, X-Header-1",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestAllowedWildcardHeader(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+		AllowedHeaders: []string{"*"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+	req.Header.Add("Access-Control-Request-Method", "GET")
+	req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "GET",
+		"Access-Control-Allow-Headers":     "X-Header-2, X-Header-1",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestDisallowedHeader(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+		AllowedHeaders: []string{"X-Header-1", "x-header-2"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+	req.Header.Add("Access-Control-Request-Method", "GET")
+	req.Header.Add("Access-Control-Request-Headers", "X-Header-3, X-Header-1")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "",
+		"Access-Control-Allow-Methods":     "",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestOriginHeader(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+	req.Header.Add("Access-Control-Request-Method", "GET")
+	req.Header.Add("Access-Control-Request-Headers", "origin")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "GET",
+		"Access-Control-Allow-Headers":     "Origin",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
+
+func TestExposedHeader(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins: []string{"http://foobar.com"},
+		ExposedHeaders: []string{"X-Header-1", "x-header-2"},
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "X-Header-1, X-Header-2",
+	})
+}
+
+func TestAllowedCredentials(t *testing.T) {
+	s := New(Options{
+		AllowedOrigins:   []string{"http://foobar.com"},
+		AllowCredentials: true,
+	})
+
+	res := httptest.NewRecorder()
+	req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
+	req.Header.Add("Origin", "http://foobar.com")
+	req.Header.Add("Access-Control-Request-Method", "GET")
+
+	s.Handler(testHandler).ServeHTTP(res, req)
+
+	assertHeaders(t, res.Header(), map[string]string{
+		"Access-Control-Allow-Origin":      "http://foobar.com",
+		"Access-Control-Allow-Methods":     "GET",
+		"Access-Control-Allow-Headers":     "",
+		"Access-Control-Allow-Credentials": "true",
+		"Access-Control-Max-Age":           "",
+		"Access-Control-Expose-Headers":    "",
+	})
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..0a3e15cb8aaf1f7a489154eb4182d9bace0fd560
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/examples/alice/server.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/justinas/alice"
+	"github.com/rs/cors"
+)
+
+func main() {
+	c := cors.New(cors.Options{
+		AllowedOrigins: []string{"http://foo.com"},
+	})
+
+	mux := http.NewServeMux()
+
+	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		w.Write([]byte("{\"hello\": \"world\"}"))
+	})
+
+	chain := alice.New(c.Handler).Then(mux)
+	http.ListenAndServe(":8080", chain)
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..851ac41d01a9c3c6b79a225cb37461cb7c125530
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/examples/default/server.go
@@ -0,0 +1,18 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/rs/cors"
+)
+
+func main() {
+	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		w.Write([]byte("{\"hello\": \"world\"}"))
+	})
+
+	// Use default options
+	handler := cors.Default().Handler(h)
+	http.ListenAndServe(":8080", handler)
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..1fb4073aadd5515bdb19b59016dbe42758ace235
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/examples/goji/server.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/rs/cors"
+	"github.com/zenazn/goji"
+)
+
+func main() {
+	c := cors.New(cors.Options{
+		AllowedOrigins: []string{"http://foo.com"},
+	})
+	goji.Use(c.Handler)
+
+	goji.Get("/", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		w.Write([]byte("{\"hello\": \"world\"}"))
+	})
+
+	goji.Serve()
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..081af32f92f60710a02c2e7d3e6a6be2a620c06c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/examples/martini/server.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+	"github.com/go-martini/martini"
+	"github.com/martini-contrib/render"
+	"github.com/rs/cors"
+)
+
+func main() {
+	c := cors.New(cors.Options{
+		AllowedOrigins: []string{"http://foo.com"},
+	})
+
+	m := martini.Classic()
+	m.Use(render.Renderer())
+	m.Use(c.HandlerFunc)
+
+	m.Get("/", func(r render.Render) {
+		r.JSON(200, map[string]interface{}{"hello": "world"})
+	})
+
+	m.Run()
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..3cb33bff6fb3a56327bc4ee2305aaec7a2994aa7
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/examples/negroni/server.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/codegangsta/negroni"
+	"github.com/rs/cors"
+)
+
+func main() {
+	c := cors.New(cors.Options{
+		AllowedOrigins: []string{"http://foo.com"},
+	})
+
+	mux := http.NewServeMux()
+
+	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		w.Write([]byte("{\"hello\": \"world\"}"))
+	})
+
+	n := negroni.Classic()
+	n.Use(c)
+	n.UseHandler(mux)
+	n.Run(":3000")
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..eaa775e443ff6ee99831b56ddf7358d8247a6614
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/examples/nethttp/server.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/rs/cors"
+)
+
+func main() {
+	c := cors.New(cors.Options{
+		AllowedOrigins: []string{"http://foo.com"},
+	})
+
+	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		w.Write([]byte("{\"hello\": \"world\"}"))
+	})
+
+	http.ListenAndServe(":8080", c.Handler(handler))
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go b/Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..09404230065d26a8a4bd04bdb2d0d2391ca3a7f3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/examples/openbar/server.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+	"net/http"
+
+	"github.com/rs/cors"
+)
+
+func main() {
+	c := cors.New(cors.Options{
+		AllowedOrigins:   []string{"*"},
+		AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE"},
+		AllowCredentials: true,
+	})
+
+	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Content-Type", "application/json")
+		w.Write([]byte("{\"hello\": \"world\"}"))
+	})
+
+	http.ListenAndServe(":8080", c.Handler(h))
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/utils.go b/Godeps/_workspace/src/github.com/rs/cors/utils.go
new file mode 100644
index 0000000000000000000000000000000000000000..429ab1114b9eeaf40a32b3d457fd6f9b0ccea342
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/utils.go
@@ -0,0 +1,27 @@
+package cors
+
+import (
+	"net/http"
+	"strings"
+)
+
+type converter func(string) string
+
+// convert converts a list of string using the passed converter function
+func convert(s []string, c converter) []string {
+	out := []string{}
+	for _, i := range s {
+		out = append(out, c(i))
+	}
+	return out
+}
+
+func parseHeaderList(headerList string) (headers []string) {
+	for _, header := range strings.Split(headerList, ",") {
+		header = http.CanonicalHeaderKey(strings.TrimSpace(header))
+		if header != "" {
+			headers = append(headers, header)
+		}
+	}
+	return headers
+}
diff --git a/Godeps/_workspace/src/github.com/rs/cors/utils_test.go b/Godeps/_workspace/src/github.com/rs/cors/utils_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..3fc77fc1e0665c14a88c00c9f6559850a09b19a3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/rs/cors/utils_test.go
@@ -0,0 +1,28 @@
+package cors
+
+import (
+	"strings"
+	"testing"
+)
+
+func TestConvert(t *testing.T) {
+	s := convert([]string{"A", "b", "C"}, strings.ToLower)
+	e := []string{"a", "b", "c"}
+	if s[0] != e[0] || s[1] != e[1] || s[2] != e[2] {
+		t.Errorf("%v != %v", s, e)
+	}
+}
+
+func TestParseHeaderList(t *testing.T) {
+	h := parseHeaderList("header, second-header, THIRD-HEADER")
+	e := []string{"Header", "Second-Header", "Third-Header"}
+	if h[0] != e[0] || h[1] != e[1] || h[2] != e[2] {
+		t.Errorf("%v != %v", h, e)
+	}
+}
+
+func TestParseHeaderListEmpty(t *testing.T) {
+	if len(parseHeaderList("")) != 0 {
+		t.Error("should be empty sclice")
+	}
+}
diff --git a/cmd/geth/admin.go b/cmd/geth/admin.go
index 3a58b888148994aea8916671576e80479053bdf7..b217e88b5a9def4e07796e28d03ec33e1c6a8d20 100644
--- a/cmd/geth/admin.go
+++ b/cmd/geth/admin.go
@@ -2,8 +2,6 @@ package main
 
 import (
 	"fmt"
-	"net"
-	"net/http"
 	"os"
 	"time"
 
@@ -70,12 +68,20 @@ func (js *jsre) startRPC(call otto.FunctionCall) otto.Value {
 		return otto.FalseValue()
 	}
 
-	l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
+	config := rpc.RpcConfig{
+		ListenAddress: addr,
+		ListenPort:    uint(port),
+		// CorsDomain:    ctx.GlobalString(RPCCORSDomainFlag.Name),
+	}
+
+	xeth := xeth.New(js.ethereum, nil)
+	err = rpc.Start(xeth, config)
+
 	if err != nil {
-		fmt.Printf("Can't listen on %s:%d: %v", addr, port, err)
+		fmt.Printf(err.Error())
 		return otto.FalseValue()
 	}
-	go http.Serve(l, rpc.JSONRPC(xeth.New(js.ethereum, nil)))
+
 	return otto.TrueValue()
 }
 
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 05e2e4ae65f428931200b52dedeaabc3633a1d7c..62e30ac9a6ba03938f3b5ac6c3dfa0573296701f 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -233,6 +233,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
 		utils.VMDebugFlag,
 		utils.ProtocolVersionFlag,
 		utils.NetworkIdFlag,
+		utils.RPCCORSDomainFlag,
 	}
 
 	// missing:
diff --git a/cmd/mist/main.go b/cmd/mist/main.go
index fab651b228d39004a0ce901ba0a16cf8d330dec6..6780cfb3a1de8644e54b54f6ced96d6998878f15 100644
--- a/cmd/mist/main.go
+++ b/cmd/mist/main.go
@@ -47,12 +47,19 @@ var (
 		Usage: "absolute path to GUI assets directory",
 		Value: common.DefaultAssetPath(),
 	}
+	rpcCorsFlag = utils.RPCCORSDomainFlag
 )
 
 func init() {
+	// Mist-specific default
+	if len(rpcCorsFlag.Value) == 0 {
+		rpcCorsFlag.Value = "http://localhost"
+	}
+
 	app.Action = run
 	app.Flags = []cli.Flag{
 		assetPathFlag,
+		rpcCorsFlag,
 
 		utils.BootnodesFlag,
 		utils.DataDirFlag,
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 2a3e2f4476b9e4902fc9be473ec518eced8c229c..e82fd9c2851d1dc1c15a2cb639bee5ac341c6e8c 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -2,9 +2,6 @@ package utils
 
 import (
 	"crypto/ecdsa"
-	"fmt"
-	"net"
-	"net/http"
 	"os"
 	"path"
 	"runtime"
@@ -148,7 +145,11 @@ var (
 		Usage: "Port on which the JSON-RPC server should listen",
 		Value: 8545,
 	}
-
+	RPCCORSDomainFlag = cli.StringFlag{
+		Name:  "rpccorsdomain",
+		Usage: "Domain on which to send Access-Control-Allow-Origin header",
+		Value: "",
+	}
 	// Network Settings
 	MaxPeersFlag = cli.IntFlag{
 		Name:  "maxpeers",
@@ -255,12 +256,12 @@ func GetAccountManager(ctx *cli.Context) *accounts.Manager {
 }
 
 func StartRPC(eth *eth.Ethereum, ctx *cli.Context) {
-	addr := ctx.GlobalString(RPCListenAddrFlag.Name)
-	port := ctx.GlobalInt(RPCPortFlag.Name)
-	fmt.Println("Starting RPC on port: ", port)
-	l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", addr, port))
-	if err != nil {
-		Fatalf("Can't listen on %s:%d: %v", addr, port, err)
+	config := rpc.RpcConfig{
+		ListenAddress: ctx.GlobalString(RPCListenAddrFlag.Name),
+		ListenPort:    uint(ctx.GlobalInt(RPCPortFlag.Name)),
+		CorsDomain:    ctx.GlobalString(RPCCORSDomainFlag.Name),
 	}
-	go http.Serve(l, rpc.JSONRPC(xeth.New(eth, nil)))
+
+	xeth := xeth.New(eth, nil)
+	_ = rpc.Start(xeth, config)
 }
diff --git a/rpc/http.go b/rpc/http.go
index 919c567bd581ade393602230e2d5c25779329dad..f15d557ad1127d37c1211773eaaedd0d0cc4e9a4 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -2,12 +2,15 @@ package rpc
 
 import (
 	"encoding/json"
+	"fmt"
 	"io"
 	"io/ioutil"
+	"net"
 	"net/http"
 
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/xeth"
+	"github.com/rs/cors"
 )
 
 var rpclogger = logger.NewLogger("RPC")
@@ -17,13 +20,36 @@ const (
 	maxSizeReqLength = 1024 * 1024 // 1MB
 )
 
+func Start(pipe *xeth.XEth, config RpcConfig) error {
+	l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", config.ListenAddress, config.ListenPort))
+	if err != nil {
+		rpclogger.Errorf("Can't listen on %s:%d: %v", config.ListenAddress, config.ListenPort, err)
+		return err
+	}
+
+	var handler http.Handler
+	if len(config.CorsDomain) > 0 {
+		var opts cors.Options
+		opts.AllowedMethods = []string{"POST"}
+		opts.AllowedOrigins = []string{config.CorsDomain}
+
+		c := cors.New(opts)
+		handler = c.Handler(JSONRPC(pipe))
+	} else {
+		handler = JSONRPC(pipe)
+	}
+
+	go http.Serve(l, handler)
+
+	return nil
+}
+
 // JSONRPC returns a handler that implements the Ethereum JSON-RPC API.
 func JSONRPC(pipe *xeth.XEth) http.Handler {
 	api := NewEthereumApi(pipe)
 
 	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
-		// TODO this needs to be configurable
-		w.Header().Set("Access-Control-Allow-Origin", "*")
+		w.Header().Set("Content-Type", "application/json")
 
 		// Limit request size to resist DoS
 		if req.ContentLength > maxSizeReqLength {
diff --git a/rpc/messages.go b/rpc/messages.go
index 5c498234f9fb36c2adaebe39e8d0ff732286a897..43c4d5e0d091a52240cd83b480ff368361b95c02 100644
--- a/rpc/messages.go
+++ b/rpc/messages.go
@@ -21,6 +21,12 @@ import (
 	"fmt"
 )
 
+type RpcConfig struct {
+	ListenAddress string
+	ListenPort    uint
+	CorsDomain    string
+}
+
 type InvalidTypeError struct {
 	method string
 	msg    string