Fixes in response to review

This commit is contained in:
Nick Johnson 2018-11-22 14:20:55 +13:00
parent 738f505e7b
commit 202a1003ee
11 changed files with 120 additions and 24 deletions

View file

@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/dashboard" "github.com/ethereum/go-ethereum/dashboard"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethgraphql" "github.com/ethereum/go-ethereum/graphql"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
@ -177,7 +177,7 @@ func makeFullNode(ctx *cli.Context) *node.Node {
// Configure GraphQL if required // Configure GraphQL if required
if ctx.GlobalIsSet(utils.GraphQLEnabledFlag.Name) { if ctx.GlobalIsSet(utils.GraphQLEnabledFlag.Name) {
if err := ethgraphql.RegisterGraphQLService(stack, cfg.Node.GraphQLEndpoint(), cfg.Node.HTTPCors, cfg.Node.HTTPVirtualHosts, cfg.Node.HTTPTimeouts); err != nil { if err := graphql.RegisterGraphQLService(stack, cfg.Node.GraphQLEndpoint(), cfg.Node.GraphQLCors, cfg.Node.GraphQLVirtualHosts, cfg.Node.HTTPTimeouts); err != nil {
utils.Fatalf("Failed to register the Ethereum service: %v", err) utils.Fatalf("Failed to register the Ethereum service: %v", err)
} }
} }

View file

@ -142,6 +142,8 @@ var (
utils.GraphQLEnabledFlag, utils.GraphQLEnabledFlag,
utils.GraphQLListenAddrFlag, utils.GraphQLListenAddrFlag,
utils.GraphQLPortFlag, utils.GraphQLPortFlag,
utils.GraphQLCORSDomainFlag,
utils.GraphQLVirtualHostsFlag,
utils.RPCApiFlag, utils.RPCApiFlag,
utils.WSEnabledFlag, utils.WSEnabledFlag,
utils.WSListenAddrFlag, utils.WSListenAddrFlag,

View file

@ -432,15 +432,25 @@ var (
Usage: "Enable the GraphQL server", Usage: "Enable the GraphQL server",
} }
GraphQLListenAddrFlag = cli.StringFlag{ GraphQLListenAddrFlag = cli.StringFlag{
Name: "graphqladdr", Name: "graphql.addr",
Usage: "GraphQL server listening interface", Usage: "GraphQL server listening interface",
Value: node.DefaultGraphQLHost, Value: node.DefaultGraphQLHost,
} }
GraphQLPortFlag = cli.IntFlag{ GraphQLPortFlag = cli.IntFlag{
Name: "graphqlport", Name: "graphql.port",
Usage: "GraphQL server listening port", Usage: "GraphQL server listening port",
Value: node.DefaultGraphQLPort, Value: node.DefaultGraphQLPort,
} }
GraphQLCORSDomainFlag = cli.StringFlag{
Name: "graphql.rpccorsdomain",
Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
Value: "",
}
GraphQLVirtualHostsFlag = cli.StringFlag{
Name: "graphql.rpcvhosts",
Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
}
RPCCORSDomainFlag = cli.StringFlag{ RPCCORSDomainFlag = cli.StringFlag{
Name: "rpccorsdomain", Name: "rpccorsdomain",
Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
@ -811,8 +821,13 @@ func setGraphQL(ctx *cli.Context, cfg *node.Config) {
cfg.GraphQLHost = ctx.GlobalString(GraphQLListenAddrFlag.Name) cfg.GraphQLHost = ctx.GlobalString(GraphQLListenAddrFlag.Name)
} }
} }
cfg.GraphQLPort = ctx.GlobalInt(GraphQLPortFlag.Name) cfg.GraphQLPort = ctx.GlobalInt(GraphQLPortFlag.Name)
if ctx.GlobalIsSet(GraphQLCORSDomainFlag.Name) {
cfg.GraphQLCors = splitAndTrim(ctx.GlobalString(GraphQLCORSDomainFlag.Name))
}
if ctx.GlobalIsSet(GraphQLVirtualHostsFlag.Name) {
cfg.GraphQLVirtualHosts = splitAndTrim(ctx.GlobalString(GraphQLVirtualHostsFlag.Name))
}
} }
// setWS creates the WebSocket RPC listener interface string from the set // setWS creates the WebSocket RPC listener interface string from the set

View file

@ -72,8 +72,10 @@ func (b Bytes) String() string {
return Encode(b) return Encode(b)
} }
// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type.
func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" } func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Bytes) UnmarshalGraphQL(input interface{}) error { func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
var err error var err error
switch input := input.(type) { switch input := input.(type) {
@ -204,8 +206,10 @@ func (b *Big) String() string {
return EncodeBig(b.ToInt()) return EncodeBig(b.ToInt())
} }
// ImplementsGraphQLType returns true if Big implements the provided GraphQL type.
func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" } func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Big) UnmarshalGraphQL(input interface{}) error { func (b *Big) UnmarshalGraphQL(input interface{}) error {
var err error var err error
switch input := input.(type) { switch input := input.(type) {
@ -268,8 +272,10 @@ func (b Uint64) String() string {
return EncodeUint64(uint64(b)) return EncodeUint64(uint64(b))
} }
// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type.
func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" } func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Uint64) UnmarshalGraphQL(input interface{}) error { func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
var err error var err error
switch input := input.(type) { switch input := input.(type) {

View file

@ -141,8 +141,10 @@ func (h Hash) Value() (driver.Value, error) {
return h[:], nil return h[:], nil
} }
// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type.
func (_ Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" } func (_ Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (h *Hash) UnmarshalGraphQL(input interface{}) error { func (h *Hash) UnmarshalGraphQL(input interface{}) error {
var err error var err error
switch input := input.(type) { switch input := input.(type) {
@ -281,8 +283,10 @@ func (a Address) Value() (driver.Value, error) {
return a[:], nil return a[:], nil
} }
// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type.
func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" } func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" }
// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (a *Address) UnmarshalGraphQL(input interface{}) error { func (a *Address) UnmarshalGraphQL(input interface{}) error {
var err error var err error
switch input := input.(type) { switch input := input.(type) {

View file

@ -1,13 +0,0 @@
package ethgraphql
import (
"testing"
)
func TestBuildSchema(t *testing.T) {
// Make sure the schema can be parsed and matched up to the object model.
_, err := NewHandler(nil)
if err != nil {
t.Errorf("Could not construct GraphQL handler: %v", err)
}
}

View file

@ -14,7 +14,8 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethgraphql // Package graphql provides a GraphQL interface to Ethereum node data.
package graphql
import ( import (
"context" "context"
@ -38,7 +39,7 @@ import (
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
graphql "github.com/graph-gophers/graphql-go" graphqlgo "github.com/graph-gophers/graphql-go"
"github.com/graph-gophers/graphql-go/relay" "github.com/graph-gophers/graphql-go/relay"
) )
@ -1021,7 +1022,7 @@ func (r *Resolver) Syncing() (*SyncState, error) {
func NewHandler(be *eth.EthAPIBackend) (http.Handler, error) { func NewHandler(be *eth.EthAPIBackend) (http.Handler, error) {
q := Resolver{be} q := Resolver{be}
s, err := graphql.ParseSchema(schema, &q) s, err := graphqlgo.ParseSchema(schema, &q)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1034,7 +1035,7 @@ func NewHandler(be *eth.EthAPIBackend) (http.Handler, error) {
return mux, nil return mux, nil
} }
// Service encapsulates an ETHGraphQL service. // Service encapsulates a GraphQL service.
type Service struct { type Service struct {
endpoint string // The host:port endpoint for this service. endpoint string // The host:port endpoint for this service.
cors []string // Allowed CORS domains cors []string // Allowed CORS domains

View file

@ -1,4 +1,26 @@
package ethgraphql // The MIT License (MIT)
//
// Copyright (c) 2016 Muhammed Thanish
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package graphql
import ( import (
"bytes" "bytes"

29
graphql/graphql_test.go Normal file
View file

@ -0,0 +1,29 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package graphql
import (
"testing"
)
func TestBuildSchema(t *testing.T) {
// Make sure the schema can be parsed and matched up to the object model.
_, err := NewHandler(nil)
if err != nil {
t.Errorf("Could not construct GraphQL handler: %v", err)
}
}

View file

@ -1,4 +1,20 @@
package ethgraphql // Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package graphql
const schema string = ` const schema string = `
# Bytes32 is a 32 byte binary string, represented as 0x-prefixed hexadecimal. # Bytes32 is a 32 byte binary string, represented as 0x-prefixed hexadecimal.

View file

@ -110,6 +110,20 @@ type Config struct {
// for ephemeral nodes). // for ephemeral nodes).
GraphQLPort int `toml:",omitempty"` GraphQLPort int `toml:",omitempty"`
// GraphQLCors is the Cross-Origin Resource Sharing header to send to requesting
// clients. Please be aware that CORS is a browser enforced security, it's fully
// useless for custom HTTP clients.
GraphQLCors []string `toml:",omitempty"`
// GraphQLVirtualHosts is the list of virtual hostnames which are allowed on incoming requests.
// This is by default {'localhost'}. Using this prevents attacks like
// DNS rebinding, which bypasses SOP by simply masquerading as being within the same
// origin. These attacks do not utilize CORS, since they are not cross-domain.
// By explicitly checking the Host-header, the server will not allow requests
// made against the server with a malicious host domain.
// Requests using ip address directly are not affected
GraphQLVirtualHosts []string `toml:",omitempty"`
// HTTPCors is the Cross-Origin Resource Sharing header to send to requesting // HTTPCors is the Cross-Origin Resource Sharing header to send to requesting
// clients. Please be aware that CORS is a browser enforced security, it's fully // clients. Please be aware that CORS is a browser enforced security, it's fully
// useless for custom HTTP clients. // useless for custom HTTP clients.