From 8651143344fc14e5157635b5be84c86f63002440 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Thu, 21 Jan 2016 23:05:18 +0100 Subject: [PATCH 1/2] Gateway: add support for HTTP OPTIONS request type OPTIONS is a noop request that is used by the browsers to check if server will accept cross-site XMLHttpRequest (indicated by the presence of CORS headers) Before this fix user could enable CORS headers in the Gateway config, but XHR failed due to the lack of support for OPTIONS request type (as described in https://git.io/vzgGe) License: MIT Signed-off-by: Marcin Rataj --- core/corehttp/gateway_handler.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 From 15d717c165462765ac25438c42da48c6de620ad9 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Fri, 22 Jan 2016 23:41:33 +0100 Subject: [PATCH 2/2] CORS header tests for Gateway - Implements https://github.com/ipfs/go-ipfs/pull/2232#issuecomment-173742385 - Separate test suite: - we don't want to pollute other gateway tests with CORS headers - (as of now) changing headers requires daemon restart anyway License: MIT Signed-off-by: Marcin Rataj --- test/sharness/t0112-gateway-cors.sh | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100755 test/sharness/t0112-gateway-cors.sh 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