github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/core/corehttp/commands.go (about) 1 package corehttp 2 3 import ( 4 "net" 5 "net/http" 6 "os" 7 "strconv" 8 "strings" 9 10 cors "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/rs/cors" 11 12 commands "github.com/ipfs/go-ipfs/commands" 13 cmdsHttp "github.com/ipfs/go-ipfs/commands/http" 14 core "github.com/ipfs/go-ipfs/core" 15 corecommands "github.com/ipfs/go-ipfs/core/commands" 16 config "github.com/ipfs/go-ipfs/repo/config" 17 ) 18 19 const originEnvKey = "API_ORIGIN" 20 const originEnvKeyDeprecate = `You are using the ` + originEnvKey + `ENV Variable. 21 This functionality is deprecated, and will be removed in future versions. 22 Instead, try either adding headers to the config, or passing them via 23 cli arguments: 24 25 ipfs config API.HTTPHeaders 'Access-Control-Allow-Origin' '*' 26 ipfs daemon 27 28 or 29 30 ipfs daemon --api-http-header 'Access-Control-Allow-Origin: *' 31 ` 32 33 var defaultLocalhostOrigins = []string{ 34 "http://127.0.0.1:<port>", 35 "https://127.0.0.1:<port>", 36 "http://localhost:<port>", 37 "https://localhost:<port>", 38 } 39 40 func addCORSFromEnv(c *cmdsHttp.ServerConfig) { 41 origin := os.Getenv(originEnvKey) 42 if origin != "" { 43 log.Warning(originEnvKeyDeprecate) 44 if c.CORSOpts == nil { 45 c.CORSOpts.AllowedOrigins = []string{origin} 46 } 47 c.CORSOpts.AllowedOrigins = append(c.CORSOpts.AllowedOrigins, origin) 48 } 49 } 50 51 func addHeadersFromConfig(c *cmdsHttp.ServerConfig, nc *config.Config) { 52 log.Info("Using API.HTTPHeaders:", nc.API.HTTPHeaders) 53 54 if acao := nc.API.HTTPHeaders[cmdsHttp.ACAOrigin]; acao != nil { 55 c.CORSOpts.AllowedOrigins = acao 56 } 57 if acam := nc.API.HTTPHeaders[cmdsHttp.ACAMethods]; acam != nil { 58 c.CORSOpts.AllowedMethods = acam 59 } 60 if acac := nc.API.HTTPHeaders[cmdsHttp.ACACredentials]; acac != nil { 61 for _, v := range acac { 62 c.CORSOpts.AllowCredentials = (strings.ToLower(v) == "true") 63 } 64 } 65 66 c.Headers = nc.API.HTTPHeaders 67 } 68 69 func addCORSDefaults(c *cmdsHttp.ServerConfig) { 70 // by default use localhost origins 71 if len(c.CORSOpts.AllowedOrigins) == 0 { 72 c.CORSOpts.AllowedOrigins = defaultLocalhostOrigins 73 } 74 75 // by default, use GET, PUT, POST 76 if len(c.CORSOpts.AllowedMethods) == 0 { 77 c.CORSOpts.AllowedMethods = []string{"GET", "POST", "PUT"} 78 } 79 } 80 81 func patchCORSVars(c *cmdsHttp.ServerConfig, addr net.Addr) { 82 83 // we have to grab the port from an addr, which may be an ip6 addr. 84 // TODO: this should take multiaddrs and derive port from there. 85 port := "" 86 if tcpaddr, ok := addr.(*net.TCPAddr); ok { 87 port = strconv.Itoa(tcpaddr.Port) 88 } else if udpaddr, ok := addr.(*net.UDPAddr); ok { 89 port = strconv.Itoa(udpaddr.Port) 90 } 91 92 // we're listening on tcp/udp with ports. ("udp!?" you say? yeah... it happens...) 93 for i, o := range c.CORSOpts.AllowedOrigins { 94 // TODO: allow replacing <host>. tricky, ip4 and ip6 and hostnames... 95 if port != "" { 96 o = strings.Replace(o, "<port>", port, -1) 97 } 98 c.CORSOpts.AllowedOrigins[i] = o 99 } 100 } 101 102 func commandsOption(cctx commands.Context, command *commands.Command) ServeOption { 103 return func(n *core.IpfsNode, l net.Listener, mux *http.ServeMux) (*http.ServeMux, error) { 104 105 cfg := &cmdsHttp.ServerConfig{ 106 CORSOpts: &cors.Options{ 107 AllowedMethods: []string{"GET", "POST", "PUT"}, 108 }, 109 } 110 rcfg, err := n.Repo.Config() 111 if err != nil { 112 return nil, err 113 } 114 115 addHeadersFromConfig(cfg, rcfg) 116 addCORSFromEnv(cfg) 117 addCORSDefaults(cfg) 118 patchCORSVars(cfg, l.Addr()) 119 120 cmdHandler := cmdsHttp.NewHandler(cctx, command, cfg) 121 mux.Handle(cmdsHttp.ApiPath+"/", cmdHandler) 122 return mux, nil 123 } 124 } 125 126 func CommandsOption(cctx commands.Context) ServeOption { 127 return commandsOption(cctx, corecommands.Root) 128 } 129 130 func CommandsROOption(cctx commands.Context) ServeOption { 131 return commandsOption(cctx, corecommands.RootRO) 132 }