Skip to content

Commit

Permalink
Merge pull request ipfs/kubo#1529 from ipfs/cors-fix
Browse files Browse the repository at this point in the history
Fix CORS Support

This commit was moved from ipfs/kubo@9e4d6e1
  • Loading branch information
jbenet committed Jul 29, 2015
2 parents e34779c + 7b098f2 commit 5012dee
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 6 deletions.
63 changes: 57 additions & 6 deletions gateway/core/corehttp/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,73 @@ package corehttp
import (
"net/http"
"os"
"strings"

cors "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/rs/cors"

commands "github.com/ipfs/go-ipfs/commands"
cmdsHttp "github.com/ipfs/go-ipfs/commands/http"
core "github.com/ipfs/go-ipfs/core"
corecommands "github.com/ipfs/go-ipfs/core/commands"
config "github.com/ipfs/go-ipfs/repo/config"
)

const (
// TODO rename
originEnvKey = "API_ORIGIN"
)
const originEnvKey = "API_ORIGIN"
const originEnvKeyDeprecate = `You are using the ` + originEnvKey + `ENV Variable.
This functionality is deprecated, and will be removed in future versions.
Instead, try either adding headers to the config, or passing them via
cli arguments:
ipfs config API.HTTPHeaders 'Access-Control-Allow-Origin' '*'
ipfs daemon
or
ipfs daemon --api-http-header 'Access-Control-Allow-Origin: *'
`

func addCORSFromEnv(c *cmdsHttp.ServerConfig) {
origin := os.Getenv(originEnvKey)
if origin != "" {
log.Warning(originEnvKeyDeprecate)
if c.CORSOpts == nil {
c.CORSOpts.AllowedOrigins = []string{origin}
}
c.CORSOpts.AllowedOrigins = append(c.CORSOpts.AllowedOrigins, origin)
}
}

func addHeadersFromConfig(c *cmdsHttp.ServerConfig, nc *config.Config) {
log.Info("Using API.HTTPHeaders:", nc.API.HTTPHeaders)

if acao := nc.API.HTTPHeaders[cmdsHttp.ACAOrigin]; acao != nil {
c.CORSOpts.AllowedOrigins = acao
}
if acam := nc.API.HTTPHeaders[cmdsHttp.ACAMethods]; acam != nil {
c.CORSOpts.AllowedMethods = acam
}
if acac := nc.API.HTTPHeaders[cmdsHttp.ACACredentials]; acac != nil {
for _, v := range acac {
c.CORSOpts.AllowCredentials = (strings.ToLower(v) == "true")
}
}

c.Headers = nc.API.HTTPHeaders
}

func CommandsOption(cctx commands.Context) ServeOption {
return func(n *core.IpfsNode, mux *http.ServeMux) (*http.ServeMux, error) {
origin := os.Getenv(originEnvKey)
cmdHandler := cmdsHttp.NewHandler(cctx, corecommands.Root, origin)

cfg := &cmdsHttp.ServerConfig{
CORSOpts: &cors.Options{
AllowedMethods: []string{"GET", "POST", "PUT"},
},
}

addHeadersFromConfig(cfg, n.Repo.Config())
addCORSFromEnv(cfg)

cmdHandler := cmdsHttp.NewHandler(cctx, corecommands.Root, cfg)
mux.Handle(cmdsHttp.ApiPath+"/", cmdHandler)
return mux, nil
}
Expand Down
4 changes: 4 additions & 0 deletions gateway/core/corehttp/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Gateway struct {
}

type GatewayConfig struct {
Headers map[string][]string
BlockList *BlockList
Writable bool
}
Expand All @@ -27,6 +28,9 @@ func NewGateway(conf GatewayConfig) *Gateway {

func (g *Gateway) ServeOption() ServeOption {
return func(n *core.IpfsNode, mux *http.ServeMux) (*http.ServeMux, error) {
// pass user's HTTP headers
g.Config.Headers = n.Repo.Config().Gateway.HTTPHeaders

gateway, err := newGatewayHandler(n, g.Config)
if err != nil {
return nil, err
Expand Down
11 changes: 11 additions & 0 deletions gateway/core/corehttp/gateway_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
return
}

i.addUserHeaders(w) // ok, _now_ write user's headers.
w.Header().Set("X-IPFS-Path", urlPath)

// Suborigin header, sandboxes apps from each other in the browser (even
Expand Down Expand Up @@ -229,6 +230,7 @@ func (i *gatewayHandler) postHandler(w http.ResponseWriter, r *http.Request) {
return
}

i.addUserHeaders(w) // ok, _now_ write user's headers.
w.Header().Set("IPFS-Hash", k.String())
http.Redirect(w, r, ipfsPathPrefix+k.String(), http.StatusCreated)
}
Expand All @@ -242,6 +244,7 @@ func (i *gatewayHandler) putEmptyDirHandler(w http.ResponseWriter, r *http.Reque
return
}

i.addUserHeaders(w) // ok, _now_ write user's headers.
w.Header().Set("IPFS-Hash", key.String())
http.Redirect(w, r, ipfsPathPrefix+key.String()+"/", http.StatusCreated)
}
Expand Down Expand Up @@ -340,6 +343,7 @@ func (i *gatewayHandler) putHandler(w http.ResponseWriter, r *http.Request) {
return
}

i.addUserHeaders(w) // ok, _now_ write user's headers.
w.Header().Set("IPFS-Hash", key.String())
http.Redirect(w, r, ipfsPathPrefix+key.String()+"/"+strings.Join(components, "/"), http.StatusCreated)
}
Expand Down Expand Up @@ -411,10 +415,17 @@ func (i *gatewayHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
return
}

i.addUserHeaders(w) // ok, _now_ write user's headers.
w.Header().Set("IPFS-Hash", key.String())
http.Redirect(w, r, ipfsPathPrefix+key.String()+"/"+strings.Join(components[:len(components)-1], "/"), http.StatusCreated)
}

func (i *gatewayHandler) addUserHeaders(w http.ResponseWriter) {
for k, v := range i.config.Headers {
w.Header()[k] = v
}
}

func webError(w http.ResponseWriter, message string, err error, defaultCode int) {
if _, ok := err.(path.ErrNoLink); ok {
webErrorWithCode(w, message, err, http.StatusNotFound)
Expand Down

0 comments on commit 5012dee

Please sign in to comment.