Skip to content

Commit 82629c0

Browse files
committed
gateway: fix CORs headers
fixes #5138 -- always add user-agent to access-control-allow-headers. fixes #5888 -- same with content-type. fixes #5892 -- extend user-provided headers instead of overriding them. License: MIT Signed-off-by: Steven Allen <[email protected]>
1 parent 543be29 commit 82629c0

File tree

2 files changed

+57
-14
lines changed

2 files changed

+57
-14
lines changed

core/corehttp/gateway.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"net"
66
"net/http"
7+
"sort"
78

89
version "github.com/ipfs/go-ipfs"
910
core "github.com/ipfs/go-ipfs/core"
@@ -18,6 +19,26 @@ type GatewayConfig struct {
1819
PathPrefixes []string
1920
}
2021

22+
// A helper function to clean up a set of headers:
23+
// 1. Canonicalizes.
24+
// 2. Deduplicates.
25+
// 3. Sorts.
26+
func cleanHeaderSet(headers []string) []string {
27+
// Deduplicate and canonicalize.
28+
m := make(map[string]struct{}, len(headers))
29+
for _, h := range headers {
30+
m[http.CanonicalHeaderKey(h)] = struct{}{}
31+
}
32+
result := make([]string, 0, len(m))
33+
for k := range m {
34+
result = append(result, k)
35+
}
36+
37+
// Sort
38+
sort.Strings(result)
39+
return result
40+
}
41+
2142
func GatewayOption(writable bool, paths ...string) ServeOption {
2243
return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
2344
cfg, err := n.Repo.Config()
@@ -30,8 +51,43 @@ func GatewayOption(writable bool, paths ...string) ServeOption {
3051
return nil, err
3152
}
3253

54+
headers := make(map[string][]string, len(cfg.Gateway.HTTPHeaders))
55+
for h, v := range cfg.Gateway.HTTPHeaders {
56+
headers[h] = v
57+
}
58+
59+
// Hard-coded headers.
60+
const ACAHeadersName = "Access-Control-Allow-Headers"
61+
const ACEHeadersName = "Access-Control-Expose-Headers"
62+
const ACAOriginName = "Access-Control-Allow-Origin"
63+
const ACAMethodsName = "Access-Control-Allow-Methods"
64+
65+
if _, ok := headers[ACAOriginName]; !ok {
66+
// Default to *all*
67+
headers[ACAOriginName] = []string{"*"}
68+
}
69+
if _, ok := headers[ACAMethodsName]; !ok {
70+
// Default to GET
71+
headers[ACAMethodsName] = []string{"GET"}
72+
}
73+
74+
headers[ACAHeadersName] = cleanHeaderSet(
75+
append([]string{
76+
"Content-Type",
77+
"User-Agent",
78+
"Range",
79+
"X-Requested-With",
80+
}, headers[ACAHeadersName]...))
81+
82+
headers[ACEHeadersName] = cleanHeaderSet(
83+
append([]string{
84+
"Content-Range",
85+
"X-Chunked-Output",
86+
"X-Stream-Output",
87+
}, headers[ACEHeadersName]...))
88+
3389
gateway := newGatewayHandler(n, GatewayConfig{
34-
Headers: cfg.Gateway.HTTPHeaders,
90+
Headers: headers,
3591
Writable: writable,
3692
PathPrefixes: cfg.Gateway.PathPrefixes,
3793
}, api)

core/corehttp/gateway_handler.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,6 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
184184
w.Header().Set("X-IPFS-Path", urlPath)
185185
w.Header().Set("Etag", etag)
186186

187-
// set 'allowed' headers
188-
// & expose those headers
189-
var allowedHeadersArr = []string{
190-
"Content-Range",
191-
"X-Chunked-Output",
192-
"X-Stream-Output",
193-
}
194-
195-
var allowedHeaders = strings.Join(allowedHeadersArr, ", ")
196-
197-
w.Header().Set("Access-Control-Allow-Headers", allowedHeaders)
198-
w.Header().Set("Access-Control-Expose-Headers", allowedHeaders)
199-
200187
// Suborigin header, sandboxes apps from each other in the browser (even
201188
// though they are served from the same gateway domain).
202189
//

0 commit comments

Comments
 (0)