diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 3d8baf8260e..ddabc474d8c 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -82,6 +82,11 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + if r.Method == "OPTIONS" { + i.optionsHandler(w, r) + return + } + errmsg := "Method " + r.Method + " not allowed: " if !i.config.Writable { w.WriteHeader(http.StatusMethodNotAllowed) @@ -94,6 +99,15 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { log.Error(errmsg) // TODO(cryptix): log errors until we have a better way to expose these (counter metrics maybe) } +func (i *gatewayHandler) optionsHandler(w http.ResponseWriter, r *http.Request) { + /* + OPTIONS is a noop request that is used by the browsers to check + if server accepts cross-site XMLHttpRequest (indicated by the presence of CORS headers) + https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests + */ + i.addUserHeaders(w) // return all custom headers (including CORS ones, if set) +} + func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(i.node.Context(), time.Hour) // the hour is a hard fallback, we don't expect it to happen, but just in case diff --git a/test/sharness/t0112-gateway-cors.sh b/test/sharness/t0112-gateway-cors.sh new file mode 100755 index 00000000000..7bdd829154a --- /dev/null +++ b/test/sharness/t0112-gateway-cors.sh @@ -0,0 +1,78 @@ +#!/bin/sh +# +# Copyright (c) 2016 Marcin Rataj +# MIT Licensed; see the LICENSE file in this repository. +# + +test_description="Test HTTP Gateway CORS Support" + +test_config_ipfs_cors_headers() { + ipfs config --json Gateway.HTTPHeaders.Access-Control-Allow-Origin '["*"]' + ipfs config --json Gateway.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST"]' + ipfs config --json Gateway.HTTPHeaders.Access-Control-Allow-Headers '["X-Requested-With"]' + + ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]' + ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST"]' + ipfs config --json API.HTTPHeaders.Access-Control-Allow-Headers '["X-Requested-With"]' +} + +. lib/test-lib.sh + +test_init_ipfs +test_config_ipfs_gateway_readonly $ADDR_GWAY +test_config_ipfs_cors_headers +test_launch_ipfs_daemon + +gwport=$PORT_GWAY +apiport=$PORT_API +thash='QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn' + +# Gateway + +# HTTP GET Request +test_expect_success "GET to Gateway succeeds" ' + curl -svX GET "http://127.0.0.1:$gwport/ipfs/$thash" 2>curl_output +' +# GET Response from Gateway should contain CORS headers +test_expect_success "GET response for Gateway resource looks good" ' + grep "Access-Control-Allow-Origin:" curl_output && + grep "Access-Control-Allow-Methods:" curl_output && + grep "Access-Control-Allow-Headers:" curl_output +' + +# HTTP OPTIONS Request +test_expect_success "OPTIONS to Gateway succeeds" ' + curl -svX OPTIONS "http://127.0.0.1:$gwport/ipfs/$thash" 2>curl_output +' +# OPTION Response from Gateway should contain CORS headers +test_expect_success "OPTIONS response for Gateway resource looks good" ' + grep "Access-Control-Allow-Origin:" curl_output && + grep "Access-Control-Allow-Methods:" curl_output && + grep "Access-Control-Allow-Headers:" curl_output +' + +# Read-Only API (at the Gateway Port) + +# HTTP GET Request +test_expect_success "GET to API succeeds" ' + curl -svX GET "http://127.0.0.1:$gwport/api/v0/cat?arg=$thash" 2>curl_output +' +# GET Response from the API should NOT contain CORS headers +# Blacklisting: https://git.io/vzaj2 +# Rationale: https://git.io/vzajX +test_expect_success "OPTIONS response for API looks good" ' + grep -q "Access-Control-Allow-" curl_output && false || true +' + +# HTTP OPTIONS Request +test_expect_success "OPTIONS to API succeeds" ' + curl -svX OPTIONS "http://127.0.0.1:$gwport/api/v0/cat?arg=$thash" 2>curl_output +' +# OPTIONS Response from the API should NOT contain CORS headers +test_expect_success "OPTIONS response for API looks good" ' + grep -q "Access-Control-Allow-" curl_output && false || true +' + +test_kill_ipfs_daemon + +test_done