mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
fix cors: defaults should take the port of the listener
need to do it this way to avoid VERY confusing situations where the user would change the API port (to another port, or maybe even to :0). this way things dont break on the user, and by default, users only need to change the API address and things should still "just work" License: MIT Signed-off-by: Juan Batiz-Benet <juan@benet.ai>
This commit is contained in:
parent
3f1cbe2f43
commit
3ee83a7c5e
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -55,13 +56,6 @@ const (
|
||||
ACACredentials = "Access-Control-Allow-Credentials"
|
||||
)
|
||||
|
||||
var localhostOrigins = []string{
|
||||
"http://127.0.0.1",
|
||||
"https://127.0.0.1",
|
||||
"http://localhost",
|
||||
"https://localhost",
|
||||
}
|
||||
|
||||
var mimeTypes = map[string]string{
|
||||
cmds.JSON: "application/json",
|
||||
cmds.XML: "application/xml",
|
||||
@ -91,21 +85,7 @@ func skipAPIHeader(h string) bool {
|
||||
|
||||
func NewHandler(ctx cmds.Context, root *cmds.Command, cfg *ServerConfig) *Handler {
|
||||
if cfg == nil {
|
||||
cfg = &ServerConfig{}
|
||||
}
|
||||
|
||||
if cfg.CORSOpts == nil {
|
||||
cfg.CORSOpts = new(cors.Options)
|
||||
}
|
||||
|
||||
// by default, use GET, PUT, POST
|
||||
if cfg.CORSOpts.AllowedMethods == nil {
|
||||
cfg.CORSOpts.AllowedMethods = []string{"GET", "POST", "PUT"}
|
||||
}
|
||||
|
||||
// by default, only let 127.0.0.1 through.
|
||||
if cfg.CORSOpts.AllowedOrigins == nil {
|
||||
cfg.CORSOpts.AllowedOrigins = localhostOrigins
|
||||
panic("must provide a valid ServerConfig")
|
||||
}
|
||||
|
||||
// Wrap the internal handler with CORS handling-middleware.
|
||||
@ -375,6 +355,16 @@ func allowReferer(r *http.Request, cfg *ServerConfig) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
u, err := url.Parse(referer)
|
||||
if err != nil {
|
||||
// bad referer. but there _is_ something, so bail.
|
||||
log.Debug("failed to parse referer: ", referer)
|
||||
// debug because referer comes straight from the client. dont want to
|
||||
// let people DOS by putting a huge referer that gets stored in log files.
|
||||
return false
|
||||
}
|
||||
origin := u.Scheme + "://" + u.Host
|
||||
|
||||
// check CORS ACAOs and pretend Referer works like an origin.
|
||||
// this is valid for many (most?) sane uses of the API in
|
||||
// other applications, and will have the desired effect.
|
||||
@ -384,7 +374,7 @@ func allowReferer(r *http.Request, cfg *ServerConfig) bool {
|
||||
}
|
||||
|
||||
// referer is allowed explicitly
|
||||
if o == referer {
|
||||
if o == origin {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ func originCfg(origins []string) *ServerConfig {
|
||||
return &ServerConfig{
|
||||
CORSOpts: &cors.Options{
|
||||
AllowedOrigins: origins,
|
||||
AllowedMethods: []string{"GET", "PUT", "POST"},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -46,6 +47,13 @@ type testCase struct {
|
||||
ResHeaders map[string]string
|
||||
}
|
||||
|
||||
var defaultOrigins = []string{
|
||||
"http://localhost",
|
||||
"http://127.0.0.1",
|
||||
"https://localhost",
|
||||
"https://127.0.0.1",
|
||||
}
|
||||
|
||||
func getTestServer(t *testing.T, origins []string) *httptest.Server {
|
||||
cmdsCtx, err := coremock.MockCmdsCtx()
|
||||
if err != nil {
|
||||
@ -59,6 +67,10 @@ func getTestServer(t *testing.T, origins []string) *httptest.Server {
|
||||
},
|
||||
}
|
||||
|
||||
if len(origins) == 0 {
|
||||
origins = defaultOrigins
|
||||
}
|
||||
|
||||
handler := NewHandler(cmdsCtx, cmdRoot, originCfg(origins))
|
||||
return httptest.NewServer(handler)
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
cors "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/rs/cors"
|
||||
@ -29,6 +30,13 @@ or
|
||||
ipfs daemon --api-http-header 'Access-Control-Allow-Origin: *'
|
||||
`
|
||||
|
||||
var defaultLocalhostOrigins = []string{
|
||||
"http://127.0.0.1:<port>",
|
||||
"https://127.0.0.1:<port>",
|
||||
"http://localhost:<port>",
|
||||
"https://localhost:<port>",
|
||||
}
|
||||
|
||||
func addCORSFromEnv(c *cmdsHttp.ServerConfig) {
|
||||
origin := os.Getenv(originEnvKey)
|
||||
if origin != "" {
|
||||
@ -58,6 +66,39 @@ func addHeadersFromConfig(c *cmdsHttp.ServerConfig, nc *config.Config) {
|
||||
c.Headers = nc.API.HTTPHeaders
|
||||
}
|
||||
|
||||
func addCORSDefaults(c *cmdsHttp.ServerConfig) {
|
||||
// by default use localhost origins
|
||||
if len(c.CORSOpts.AllowedOrigins) == 0 {
|
||||
c.CORSOpts.AllowedOrigins = defaultLocalhostOrigins
|
||||
}
|
||||
|
||||
// by default, use GET, PUT, POST
|
||||
if len(c.CORSOpts.AllowedMethods) == 0 {
|
||||
c.CORSOpts.AllowedMethods = []string{"GET", "POST", "PUT"}
|
||||
}
|
||||
}
|
||||
|
||||
func patchCORSVars(c *cmdsHttp.ServerConfig, addr net.Addr) {
|
||||
|
||||
// we have to grab the port from an addr, which may be an ip6 addr.
|
||||
// TODO: this should take multiaddrs and derive port from there.
|
||||
port := ""
|
||||
if tcpaddr, ok := addr.(*net.TCPAddr); ok {
|
||||
port = strconv.Itoa(tcpaddr.Port)
|
||||
} else if udpaddr, ok := addr.(*net.UDPAddr); ok {
|
||||
port = strconv.Itoa(udpaddr.Port)
|
||||
}
|
||||
|
||||
// we're listening on tcp/udp with ports. ("udp!?" you say? yeah... it happens...)
|
||||
for i, o := range c.CORSOpts.AllowedOrigins {
|
||||
// TODO: allow replacing <host>. tricky, ip4 and ip6 and hostnames...
|
||||
if port != "" {
|
||||
o = strings.Replace(o, "<port>", port, -1)
|
||||
}
|
||||
c.CORSOpts.AllowedOrigins[i] = o
|
||||
}
|
||||
}
|
||||
|
||||
func CommandsOption(cctx commands.Context) ServeOption {
|
||||
return func(n *core.IpfsNode, l net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
|
||||
|
||||
@ -69,6 +110,8 @@ func CommandsOption(cctx commands.Context) ServeOption {
|
||||
|
||||
addHeadersFromConfig(cfg, n.Repo.Config())
|
||||
addCORSFromEnv(cfg)
|
||||
addCORSDefaults(cfg)
|
||||
patchCORSVars(cfg, l.Addr())
|
||||
|
||||
cmdHandler := cmdsHttp.NewHandler(cctx, corecommands.Root, cfg)
|
||||
mux.Handle(cmdsHttp.ApiPath+"/", cmdHandler)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user