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

This commit is contained in:
Maran 2017-01-05 11:57:41 +01:00 committed by Felix Lange
parent bbce726c8a
commit f087633efd
3 changed files with 49 additions and 15 deletions

View File

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

View File

@ -24,6 +24,7 @@ import (
"io" "io"
"net/http" "net/http"
"regexp" "regexp"
"strings"
"sync" "sync"
"time" "time"
@ -31,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/swarm/api" "github.com/ethereum/go-ethereum/swarm/api"
"github.com/rs/cors"
) )
const ( const (
@ -53,19 +55,37 @@ type sequentialReader struct {
lock sync.Mutex 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: // browser API for registering bzz url scheme handlers:
// https://developer.mozilla.org/en/docs/Web-based_protocol_handlers // https://developer.mozilla.org/en/docs/Web-based_protocol_handlers
// electron (chromium) api for registering bzz url scheme handlers: // electron (chromium) api for registering bzz url scheme handlers:
// https://github.com/atom/electron/blob/master/docs/api/protocol.md // https://github.com/atom/electron/blob/master/docs/api/protocol.md
// starts up http server // starts up http server
func StartHttpServer(api *api.Api, port string) { func StartHttpServer(api *api.Api, server *Server) {
serveMux := http.NewServeMux() serveMux := http.NewServeMux()
serveMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { serveMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
handler(w, r, api) handler(w, r, api)
}) })
go http.ListenAndServe(":"+port, serveMux) var allowedOrigins []string
glog.V(logger.Info).Infof("Swarm HTTP proxy started on localhost:%s", port) 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) { func handler(w http.ResponseWriter, r *http.Request, a *api.Api) {

View File

@ -52,6 +52,7 @@ type Swarm struct {
hive *network.Hive // the logistic manager hive *network.Hive // the logistic manager
backend chequebook.Backend // simple blockchain Backend backend chequebook.Backend // simple blockchain Backend
privateKey *ecdsa.PrivateKey privateKey *ecdsa.PrivateKey
corsString string
swapEnabled bool swapEnabled bool
} }
@ -71,7 +72,7 @@ func (self *Swarm) API() *SwarmAPI {
// creates a new swarm service instance // creates a new swarm service instance
// implements node.Service // 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) { if bytes.Equal(common.FromHex(config.PublicKey), storage.ZeroKey) {
return nil, fmt.Errorf("empty public key") return nil, fmt.Errorf("empty public key")
} }
@ -84,6 +85,7 @@ func NewSwarm(ctx *node.ServiceContext, backend chequebook.Backend, config *api.
swapEnabled: swapEnabled, swapEnabled: swapEnabled,
backend: backend, backend: backend,
privateKey: config.Swap.PrivateKey(), privateKey: config.Swap.PrivateKey(),
corsString: cors,
} }
glog.V(logger.Debug).Infof("Setting up Swarm service components") 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 // start swarm http proxy server
if self.config.Port != "" { 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) 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 return nil
} }