Prechádzať zdrojové kódy

swarm/api/http: add support for CORS headers (#3388)

Maran 8 rokov pred
rodič
commit
f087633efd
3 zmenil súbory, kde vykonal 49 pridanie a 15 odobranie
  1. 16 10
      cmd/swarm/main.go
  2. 23 3
      swarm/api/http/server.go
  3. 10 2
      swarm/swarm.go

+ 16 - 10
cmd/swarm/main.go

@@ -82,15 +82,15 @@ var (
 		Name:  "bzzconfig",
 		Usage: "Swarm config file path (datadir/bzz)",
 	}
-	SwarmSwapEnabled = cli.BoolFlag{
+	SwarmSwapEnabledFlag = cli.BoolFlag{
 		Name:  "swap",
 		Usage: "Swarm SWAP enabled (default false)",
 	}
-	SwarmSyncEnabled = cli.BoolTFlag{
+	SwarmSyncEnabledFlag = cli.BoolTFlag{
 		Name:  "sync",
 		Usage: "Swarm Syncing enabled (default true)",
 	}
-	EthAPI = cli.StringFlag{
+	EthAPIFlag = cli.StringFlag{
 		Name:  "ethapi",
 		Usage: "URL of the Ethereum API provider",
 		Value: node.DefaultIPCEndpoint("geth"),
@@ -112,6 +112,10 @@ var (
 		Name:  "defaultpath",
 		Usage: "path to file served for empty url path (none)",
 	}
+	CorsStringFlag = cli.StringFlag{
+		Name:  "corsdomain",
+		Usage: "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied seperated by a ',')",
+	}
 )
 
 func init() {
@@ -171,10 +175,11 @@ Prints the swarm hash of file or directory.
 		utils.IPCApiFlag,
 		utils.IPCPathFlag,
 		// bzzd-specific flags
-		EthAPI,
+		CorsStringFlag,
+		EthAPIFlag,
 		SwarmConfigPathFlag,
-		SwarmSwapEnabled,
-		SwarmSyncEnabled,
+		SwarmSwapEnabledFlag,
+		SwarmSyncEnabledFlag,
 		SwarmPortFlag,
 		SwarmAccountFlag,
 		SwarmNetworkIdFlag,
@@ -252,10 +257,11 @@ func registerBzzService(ctx *cli.Context, stack *node.Node) {
 	if len(bzzport) > 0 {
 		bzzconfig.Port = bzzport
 	}
-	swapEnabled := ctx.GlobalBool(SwarmSwapEnabled.Name)
-	syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabled.Name)
+	swapEnabled := ctx.GlobalBool(SwarmSwapEnabledFlag.Name)
+	syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabledFlag.Name)
 
-	ethapi := ctx.GlobalString(EthAPI.Name)
+	ethapi := ctx.GlobalString(EthAPIFlag.Name)
+	cors := ctx.GlobalString(CorsStringFlag.Name)
 
 	boot := func(ctx *node.ServiceContext) (node.Service, error) {
 		var client *ethclient.Client
@@ -265,7 +271,7 @@ func registerBzzService(ctx *cli.Context, stack *node.Node) {
 				utils.Fatalf("Can't connect: %v", err)
 			}
 		}
-		return swarm.NewSwarm(ctx, client, bzzconfig, swapEnabled, syncEnabled)
+		return swarm.NewSwarm(ctx, client, bzzconfig, swapEnabled, syncEnabled, cors)
 	}
 	if err := stack.Register(boot); err != nil {
 		utils.Fatalf("Failed to register the Swarm service: %v", err)

+ 23 - 3
swarm/api/http/server.go

@@ -24,6 +24,7 @@ import (
 	"io"
 	"net/http"
 	"regexp"
+	"strings"
 	"sync"
 	"time"
 
@@ -31,6 +32,7 @@ import (
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/logger/glog"
 	"github.com/ethereum/go-ethereum/swarm/api"
+	"github.com/rs/cors"
 )
 
 const (
@@ -53,19 +55,37 @@ type sequentialReader struct {
 	lock   sync.Mutex
 }
 
+// Server is the basic configuration needs for the HTTP server and also
+// includes CORS settings.
+type Server struct {
+	Addr       string
+	CorsString string
+}
+
 // browser API for registering bzz url scheme handlers:
 // https://developer.mozilla.org/en/docs/Web-based_protocol_handlers
 // electron (chromium) api for registering bzz url scheme handlers:
 // https://github.com/atom/electron/blob/master/docs/api/protocol.md
 
 // starts up http server
-func StartHttpServer(api *api.Api, port string) {
+func StartHttpServer(api *api.Api, server *Server) {
 	serveMux := http.NewServeMux()
 	serveMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 		handler(w, r, api)
 	})
-	go http.ListenAndServe(":"+port, serveMux)
-	glog.V(logger.Info).Infof("Swarm HTTP proxy started on localhost:%s", port)
+	var allowedOrigins []string
+	for _, domain := range strings.Split(server.CorsString, ",") {
+		allowedOrigins = append(allowedOrigins, strings.TrimSpace(domain))
+	}
+	c := cors.New(cors.Options{
+		AllowedOrigins: allowedOrigins,
+		AllowedMethods: []string{"POST", "GET", "DELETE", "PATCH", "PUT"},
+		MaxAge:         600,
+	})
+	hdlr := c.Handler(serveMux)
+
+	go http.ListenAndServe(server.Addr, hdlr)
+	glog.V(logger.Info).Infof("Swarm HTTP proxy started on localhost:%s", server.Addr)
 }
 
 func handler(w http.ResponseWriter, r *http.Request, a *api.Api) {

+ 10 - 2
swarm/swarm.go

@@ -52,6 +52,7 @@ type Swarm struct {
 	hive        *network.Hive          // the logistic manager
 	backend     chequebook.Backend     // simple blockchain Backend
 	privateKey  *ecdsa.PrivateKey
+	corsString  string
 	swapEnabled bool
 }
 
@@ -71,7 +72,7 @@ func (self *Swarm) API() *SwarmAPI {
 
 // creates a new swarm service instance
 // implements node.Service
-func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.Config, swapEnabled, syncEnabled bool) (self *Swarm, err error) {
+func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.Config, swapEnabled, syncEnabled bool, cors string) (self *Swarm, err error) {
 	if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) {
 		return nil, fmt.Errorf("empty public key")
 	}
@@ -84,6 +85,7 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.
 		swapEnabled: swapEnabled,
 		backend:     backend,
 		privateKey:  config.Swap.PrivateKey(),
+		corsString:  cors,
 	}
 	glog.V(logger.Debug).Infof("Setting up Swarm service components")
 
@@ -188,10 +190,16 @@ func (self *Swarm) Start(net *p2p.Server) error {
 
 	// start swarm http proxy server
 	if self.config.Port != "" {
-		go httpapi.StartHttpServer(self.api, self.config.Port)
+		addr := ":" + self.config.Port
+		go httpapi.StartHttpServer(self.api, &httpapi.Server{Addr: addr, CorsString: self.corsString})
 	}
+
 	glog.V(logger.Debug).Infof("Swarm http proxy started on port: %v", self.config.Port)
 
+	if self.corsString != "" {
+		glog.V(logger.Debug).Infof("Swarm http proxy started with corsdomain:", self.corsString)
+	}
+
 	return nil
 }