Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gateway: add support for HTTP OPTIONS request type #2232

Merged
merged 2 commits into from
Jan 24, 2016
Merged

Gateway: add support for HTTP OPTIONS request type #2232

merged 2 commits into from
Jan 24, 2016

Conversation

lidel
Copy link
Member

@lidel lidel commented Jan 21, 2016

This potentially closes #934

OPTIONS is a noop request that is used by the browsers to check if server explicitly accepts cross-site XMLHttpRequest (XHR). The acceptance is indicated by the presence of CORS headers.

Before this fix user could enable CORS headers in the Gateway config (note that this disabled by default):

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"]'

..but requests sent from JavaScript failed due to the lack of support for OPTIONS request type.
I described details of the problem with XHR in ipfs/ipfs-companion#45 (comment).

With this fix sending cross-site XHR to the local Gateway works as expected.

Reference:

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 <[email protected]>
@ghost
Copy link

ghost commented Jan 21, 2016

Thanks! -- could you add a test which makes sure this works for both the gateway and the readonly api at :8080/api?

@lidel
Copy link
Member Author

lidel commented Jan 21, 2016

@lgierth where should I add OPTION tests?
Gateway in core/corehttp/gateway_test.go and API in commands/http/handler_test.go ?

BTW: while OPTIONS itself works with API, CORS headers such as Access-Control-Allow-* are removed from /api/v0/* responses as a security measure (even if user explicitly added them):

In short: cross-site XHR currently does not work for API resources.

@@ -82,6 +82,11 @@ func (i *gatewayHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}

if r.Method == "OPTIONS" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this enabled in both ro and writable case? Shouldn't it be enabled for ro only, ref: #934 (comment).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel we should always produce OPTIONS response.
Gateway owner can decide what types of requests are accepted by customizing Access-Control-Allow-Method header (GET is ro, POST, PUT, DELETE are rw).
All major browsers respect this header and refuse to do XHR requests if method is not whitelisted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ic

@rht rht added the topic/gateway Topic gateway label Jan 22, 2016
@rht
Copy link
Contributor

rht commented Jan 22, 2016

@lidel I think the test is to be put in test/sharness/t0110-gateway.sh.

To speed-up this PR, here is a quick test template:

test_gateway_options_request() {
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"]'

test_expect_success "OPTIONS to gateway succeeds" '
    curl -svX OPTIONS "http://localhost:$port/ipfs/" 2>curl_output
'
test_expect_success "OPTIONS to gateway output looks good" '
    grep "Origin:" curl_output &&
    grep "Access-Control-Request-Method:" curl_output &&
    grep "Access-Control-Request-Headers:" curl_output
'
}

@rht
Copy link
Contributor

rht commented Jan 22, 2016

I figured that the cors wrapper in https:/ipfs/go-ipfs/blob/a2b0287a5f6fb5c0f35b63688ad5ac81c451afce/commands/http/handler.go#L102 was meant to handle preflight (see https:/rs/cors/blob/45d446e551b0020074e771dee17d2bb2fd2e9b44/cors.go#L245).

Somehow it doesn't get enabled.

@rht
Copy link
Contributor

rht commented Jan 22, 2016

  1. It appears that the github.com/rs/cors library used in the current master is outdated. Either 1. use that lib, or 2. replicate the essentially functionality (only show Origin, Access-Control-Request-Method, Access-Control-Request-Headers, instead of addUserHeaders).
  2. I tested the pr and it didn't work on the ro api. Either leave this to a separate PR, or put a few lines in commands/http/handler.go. Edit: ic, because it was intentionally removed Gateway: add support for HTTP OPTIONS request type #2232 (comment)

@rht
Copy link
Contributor

rht commented Jan 22, 2016

Just updated the test. It should be runnable.

- Implements
  #2232 (comment)
- 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 <[email protected]>
@lidel
Copy link
Member Author

lidel commented Jan 22, 2016

Thank you @rht, I decided to add CORS headers and OPTIONS tests as a separate file in 15d717c

  • I don't want to pollute other gateway tests with CORS headers
  • (as of now) changing headers requires daemon restart anyway to see the changes
  • we may want to add more CORS-related tests in future as our browser addons and IPFS-based app ecosystem matures

I feel that the goal of this PR is to add missing support for OPTIONS and that is all.
Further CORS improvements should be separate PRs.

Let me know if I should add anything else for this to be merged.

@rht
Copy link
Contributor

rht commented Jan 22, 2016

There could be test for gateway ACL as well.
The test file LGTM.
The travis-ci build stall is orthogonal to this pr.
This is ready to merge, I think.

@jbenet
Copy link
Member

jbenet commented Jan 24, 2016

LGTM!

@jbenet
Copy link
Member

jbenet commented Jan 24, 2016

thanks @lidel

jbenet added a commit that referenced this pull request Jan 24, 2016
Gateway: add support for HTTP OPTIONS request type
@jbenet jbenet merged commit a5c4c5d into ipfs:master Jan 24, 2016
@lidel lidel deleted the cors-preflight-fix branch January 24, 2016 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic/gateway Topic gateway
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Gateway should allow CORS
3 participants