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  }