diff --git a/cmd/geth/config.go b/cmd/geth/config.go
index aff1530ff4..cb6cf54766 100644
--- a/cmd/geth/config.go
+++ b/cmd/geth/config.go
@@ -30,7 +30,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/dashboard"
"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/params"
whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
@@ -177,7 +177,7 @@ func makeFullNode(ctx *cli.Context) *node.Node {
// Configure GraphQL if required
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)
}
}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 859d4d959a..2cc881dbc4 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -142,6 +142,8 @@ var (
utils.GraphQLEnabledFlag,
utils.GraphQLListenAddrFlag,
utils.GraphQLPortFlag,
+ utils.GraphQLCORSDomainFlag,
+ utils.GraphQLVirtualHostsFlag,
utils.RPCApiFlag,
utils.WSEnabledFlag,
utils.WSListenAddrFlag,
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index e6834442ca..16cae43e3d 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -432,15 +432,25 @@ var (
Usage: "Enable the GraphQL server",
}
GraphQLListenAddrFlag = cli.StringFlag{
- Name: "graphqladdr",
+ Name: "graphql.addr",
Usage: "GraphQL server listening interface",
Value: node.DefaultGraphQLHost,
}
GraphQLPortFlag = cli.IntFlag{
- Name: "graphqlport",
+ Name: "graphql.port",
Usage: "GraphQL server listening port",
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{
Name: "rpccorsdomain",
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.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
diff --git a/common/hexutil/json.go b/common/hexutil/json.go
index 30bfb61c9b..777b08eca4 100644
--- a/common/hexutil/json.go
+++ b/common/hexutil/json.go
@@ -72,8 +72,10 @@ func (b Bytes) String() string {
return Encode(b)
}
+// ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type.
func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" }
+// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
@@ -204,8 +206,10 @@ func (b *Big) String() string {
return EncodeBig(b.ToInt())
}
+// ImplementsGraphQLType returns true if Big implements the provided GraphQL type.
func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
+// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Big) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
@@ -268,8 +272,10 @@ func (b Uint64) String() string {
return EncodeUint64(uint64(b))
}
+// ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type.
func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
+// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
diff --git a/common/types.go b/common/types.go
index cf61ec66c5..cb74cbd6ff 100644
--- a/common/types.go
+++ b/common/types.go
@@ -141,8 +141,10 @@ func (h Hash) Value() (driver.Value, error) {
return h[:], nil
}
+// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type.
func (_ Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" }
+// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (h *Hash) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
@@ -281,8 +283,10 @@ func (a Address) Value() (driver.Value, error) {
return a[:], nil
}
+// ImplementsGraphQLType returns true if Hash implements the specified GraphQL type.
func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" }
+// UnmarshalGraphQL unmarshals the provided GraphQL query data.
func (a *Address) UnmarshalGraphQL(input interface{}) error {
var err error
switch input := input.(type) {
diff --git a/ethgraphql/main_test.go b/ethgraphql/main_test.go
deleted file mode 100644
index acdb143f7d..0000000000
--- a/ethgraphql/main_test.go
+++ /dev/null
@@ -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)
- }
-}
diff --git a/ethgraphql/main.go b/graphql/grahpql.go
similarity index 99%
rename from ethgraphql/main.go
rename to graphql/grahpql.go
index 3c81c80e23..b16271e6d5 100644
--- a/ethgraphql/main.go
+++ b/graphql/grahpql.go
@@ -14,7 +14,8 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-package ethgraphql
+// Package graphql provides a GraphQL interface to Ethereum node data.
+package graphql
import (
"context"
@@ -38,7 +39,7 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rlp"
"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"
)
@@ -1021,7 +1022,7 @@ func (r *Resolver) Syncing() (*SyncState, error) {
func NewHandler(be *eth.EthAPIBackend) (http.Handler, error) {
q := Resolver{be}
- s, err := graphql.ParseSchema(schema, &q)
+ s, err := graphqlgo.ParseSchema(schema, &q)
if err != nil {
return nil, err
}
@@ -1034,7 +1035,7 @@ func NewHandler(be *eth.EthAPIBackend) (http.Handler, error) {
return mux, nil
}
-// Service encapsulates an ETHGraphQL service.
+// Service encapsulates a GraphQL service.
type Service struct {
endpoint string // The host:port endpoint for this service.
cors []string // Allowed CORS domains
diff --git a/ethgraphql/graphiql.go b/graphql/graphiql.go
similarity index 63%
rename from ethgraphql/graphiql.go
rename to graphql/graphiql.go
index 42bb7920fd..6d9dda3e8c 100644
--- a/ethgraphql/graphiql.go
+++ b/graphql/graphiql.go
@@ -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 (
"bytes"
diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go
new file mode 100644
index 0000000000..d63418398a
--- /dev/null
+++ b/graphql/graphql_test.go
@@ -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 .
+
+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)
+ }
+}
diff --git a/ethgraphql/schema.go b/graphql/schema.go
similarity index 94%
rename from ethgraphql/schema.go
rename to graphql/schema.go
index 9367cdc7cf..c1ba87d2d6 100644
--- a/ethgraphql/schema.go
+++ b/graphql/schema.go
@@ -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 .
+
+package graphql
const schema string = `
# Bytes32 is a 32 byte binary string, represented as 0x-prefixed hexadecimal.
diff --git a/node/config.go b/node/config.go
index a1a896df89..c259223cbb 100644
--- a/node/config.go
+++ b/node/config.go
@@ -110,6 +110,20 @@ type Config struct {
// for ephemeral nodes).
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
// clients. Please be aware that CORS is a browser enforced security, it's fully
// useless for custom HTTP clients.