forked from TrueCloudLab/neoneo-go
rpc: add CORS workaround for RPC
This one enables our RPC to be called from the browser if there is a need. It's insecure and not standards-compliant, thus this behaviour is configurable is not enabled by default. It makes our node with this workaround enabled compatible with neo-mon monitoring. Originally debugged by @anatoly-bogatyrev in #464.
This commit is contained in:
parent
e5205d26a3
commit
b46dd295bc
14 changed files with 72 additions and 22 deletions
|
@ -247,7 +247,7 @@ func startServer(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
server := network.NewServer(serverConfig, chain)
|
||||
rpcServer := rpc.NewServer(chain, cfg.ApplicationConfiguration.RPCPort, server)
|
||||
rpcServer := rpc.NewServer(chain, cfg.ApplicationConfiguration.RPC, server)
|
||||
errChan := make(chan error)
|
||||
monitoring := metrics.NewMetricsService(cfg.ApplicationConfiguration.Monitoring)
|
||||
|
||||
|
|
|
@ -67,7 +67,6 @@ type (
|
|||
// ApplicationConfiguration config specific to the node.
|
||||
ApplicationConfiguration struct {
|
||||
DBConfiguration storage.DBConfiguration `yaml:"DBConfiguration"`
|
||||
RPCPort uint16 `yaml:"RPCPort"`
|
||||
NodePort uint16 `yaml:"NodePort"`
|
||||
Relay bool `yaml:"Relay"`
|
||||
DialTimeout time.Duration `yaml:"DialTimeout"`
|
||||
|
@ -75,6 +74,15 @@ type (
|
|||
MaxPeers int `yaml:"MaxPeers"`
|
||||
MinPeers int `yaml:"MinPeers"`
|
||||
Monitoring metrics.PrometheusConfig `yaml:"Monitoring"`
|
||||
RPC RPCConfig `yaml:"RPC"`
|
||||
}
|
||||
|
||||
// RPCConfig is an RPC service configuration information (to be moved to the rpc package, see #423).
|
||||
RPCConfig struct {
|
||||
Enabled bool `yaml:"Enabled"`
|
||||
EnableCORSWorkaround bool `yaml:"EnableCORSWorkaround"`
|
||||
Address string `yaml:"Address"`
|
||||
Port uint16 `yaml:"Port"`
|
||||
}
|
||||
|
||||
// NetMode describes the mode the blockchain will operate on.
|
||||
|
|
|
@ -42,13 +42,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/mainnet.bolt"
|
||||
RPCPort: 20332
|
||||
NodePort: 20333
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 5
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20332
|
||||
Monitoring:
|
||||
Enabled: true
|
||||
Port: 2112
|
||||
|
|
|
@ -30,13 +30,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/privnet.bolt"
|
||||
RPCPort: 20336
|
||||
NodePort: 20337
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20336
|
||||
Monitoring:
|
||||
Enabled: true
|
||||
Port: 2112
|
||||
|
|
|
@ -27,13 +27,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/privnet.bolt"
|
||||
RPCPort: 20333
|
||||
NodePort: 20334
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20333
|
||||
Monitoring:
|
||||
Enabled: true
|
||||
Port: 2112
|
||||
|
|
|
@ -27,13 +27,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/privnet.bolt"
|
||||
RPCPort: 20335
|
||||
NodePort: 20336
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20335
|
||||
Monitoring:
|
||||
Enabled: true
|
||||
Port: 2112
|
||||
|
|
|
@ -27,13 +27,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/privnet.bolt"
|
||||
RPCPort: 20334
|
||||
NodePort: 20335
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20334
|
||||
Monitoring:
|
||||
Enabled: true
|
||||
Port: 2112
|
||||
|
|
|
@ -33,13 +33,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/privnet.bolt"
|
||||
RPCPort: 20331
|
||||
NodePort: 20332
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 3
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20331
|
||||
Monitoring:
|
||||
Enabled: true
|
||||
Port: 2112
|
||||
|
|
|
@ -42,13 +42,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/testnet.bolt"
|
||||
RPCPort: 20332
|
||||
NodePort: 20333
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 5
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20332
|
||||
Monitoring:
|
||||
Enabled: true
|
||||
Port: 2112
|
||||
|
|
|
@ -32,13 +32,16 @@ ApplicationConfiguration:
|
|||
# DB: 0
|
||||
# BoltDBOptions:
|
||||
# FilePath: "./chains/unit_testnet.bolt"
|
||||
RPCPort: 20332
|
||||
NodePort: 20333
|
||||
Relay: true
|
||||
DialTimeout: 3
|
||||
ProtoTickInterval: 2
|
||||
MaxPeers: 50
|
||||
MinPeers: 1
|
||||
RPC:
|
||||
Enabled: true
|
||||
EnableCORSWorkaround: false
|
||||
Port: 20332
|
||||
Monitoring:
|
||||
Enabled: false #since it's not useful for unit tests.
|
||||
Port: 2112
|
||||
|
|
2
go.mod
2
go.mod
|
@ -15,6 +15,8 @@ require (
|
|||
github.com/gomodule/redigo v2.0.0+incompatible // indirect
|
||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.9 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/mr-tron/base58 v1.1.2
|
||||
github.com/nspcc-dev/rfc6979 v0.1.0
|
||||
github.com/onsi/gomega v1.4.2 // indirect
|
||||
|
|
|
@ -21,6 +21,7 @@ type (
|
|||
Method string `json:"method"`
|
||||
RawParams json.RawMessage `json:"params,omitempty"`
|
||||
RawID json.RawMessage `json:"id,omitempty"`
|
||||
enableCORSWorkaround bool
|
||||
}
|
||||
|
||||
// Response represents a standard JSON-RPC 2.0
|
||||
|
@ -34,9 +35,10 @@ type (
|
|||
)
|
||||
|
||||
// NewRequest creates a new Request struct.
|
||||
func NewRequest() *Request {
|
||||
func NewRequest(corsWorkaround bool) *Request {
|
||||
return &Request{
|
||||
JSONRPC: jsonRPCVersion,
|
||||
enableCORSWorkaround: corsWorkaround,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +112,11 @@ func (r Request) WriteResponse(w http.ResponseWriter, result interface{}) {
|
|||
|
||||
func (r Request) writeServerResponse(w http.ResponseWriter, response Response) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
if r.enableCORSWorkaround {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
|
||||
}
|
||||
|
||||
encoder := json.NewEncoder(w)
|
||||
err := encoder.Encode(response)
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/CityOfZion/neo-go/config"
|
||||
"github.com/CityOfZion/neo-go/pkg/core"
|
||||
"github.com/CityOfZion/neo-go/pkg/core/transaction"
|
||||
"github.com/CityOfZion/neo-go/pkg/crypto"
|
||||
|
@ -24,6 +25,7 @@ type (
|
|||
Server struct {
|
||||
*http.Server
|
||||
chain core.Blockchainer
|
||||
config config.RPCConfig
|
||||
coreServer *network.Server
|
||||
}
|
||||
)
|
||||
|
@ -35,12 +37,15 @@ var (
|
|||
)
|
||||
|
||||
// NewServer creates a new Server struct.
|
||||
func NewServer(chain core.Blockchainer, port uint16, coreServer *network.Server) Server {
|
||||
func NewServer(chain core.Blockchainer, conf config.RPCConfig, coreServer *network.Server) Server {
|
||||
httpServer := &http.Server{
|
||||
Addr: conf.Address + ":" + strconv.FormatUint(uint64(conf.Port), 10),
|
||||
}
|
||||
|
||||
return Server{
|
||||
Server: &http.Server{
|
||||
Addr: ":" + strconv.FormatUint(uint64(port), 10),
|
||||
},
|
||||
Server: httpServer,
|
||||
chain: chain,
|
||||
config: conf,
|
||||
coreServer: coreServer,
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +53,10 @@ func NewServer(chain core.Blockchainer, port uint16, coreServer *network.Server)
|
|||
// Start creates a new JSON-RPC server
|
||||
// listening on the configured port.
|
||||
func (s *Server) Start(errChan chan error) {
|
||||
if !s.config.Enabled {
|
||||
log.Info("RPC server is not enabled")
|
||||
return
|
||||
}
|
||||
s.Handler = http.HandlerFunc(s.requestHandler)
|
||||
log.WithFields(log.Fields{
|
||||
"endpoint": s.Addr,
|
||||
|
@ -66,7 +75,7 @@ func (s *Server) Shutdown() error {
|
|||
}
|
||||
|
||||
func (s *Server) requestHandler(w http.ResponseWriter, httpRequest *http.Request) {
|
||||
req := NewRequest()
|
||||
req := NewRequest(s.config.EnableCORSWorkaround)
|
||||
|
||||
if httpRequest.Method != "POST" {
|
||||
req.WriteErrorResponse(
|
||||
|
|
|
@ -167,7 +167,7 @@ func initServerWithInMemoryChain(ctx context.Context, t *testing.T) (*core.Block
|
|||
|
||||
serverConfig := network.NewServerConfig(cfg)
|
||||
server := network.NewServer(serverConfig, chain)
|
||||
rpcServer := NewServer(chain, cfg.ApplicationConfiguration.RPCPort, server)
|
||||
rpcServer := NewServer(chain, cfg.ApplicationConfiguration.RPC, server)
|
||||
handler := http.HandlerFunc(rpcServer.requestHandler)
|
||||
|
||||
return chain, handler
|
||||
|
|
Loading…
Reference in a new issue