github.com/bcnmy/go-ethereum@v1.10.27/graphql/service.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package graphql 18 19 import ( 20 "encoding/json" 21 "net/http" 22 23 "github.com/ethereum/go-ethereum/eth/filters" 24 "github.com/ethereum/go-ethereum/internal/ethapi" 25 "github.com/ethereum/go-ethereum/node" 26 "github.com/graph-gophers/graphql-go" 27 ) 28 29 type handler struct { 30 Schema *graphql.Schema 31 } 32 33 func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 34 var params struct { 35 Query string `json:"query"` 36 OperationName string `json:"operationName"` 37 Variables map[string]interface{} `json:"variables"` 38 } 39 if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { 40 http.Error(w, err.Error(), http.StatusBadRequest) 41 return 42 } 43 44 response := h.Schema.Exec(r.Context(), params.Query, params.OperationName, params.Variables) 45 responseJSON, err := json.Marshal(response) 46 if err != nil { 47 http.Error(w, err.Error(), http.StatusInternalServerError) 48 return 49 } 50 if len(response.Errors) > 0 { 51 w.WriteHeader(http.StatusBadRequest) 52 } 53 54 w.Header().Set("Content-Type", "application/json") 55 w.Write(responseJSON) 56 } 57 58 // New constructs a new GraphQL service instance. 59 func New(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cors, vhosts []string) error { 60 _, err := newHandler(stack, backend, filterSystem, cors, vhosts) 61 return err 62 } 63 64 // newHandler returns a new `http.Handler` that will answer GraphQL queries. 65 // It additionally exports an interactive query browser on the / endpoint. 66 func newHandler(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cors, vhosts []string) (*handler, error) { 67 q := Resolver{backend, filterSystem} 68 69 s, err := graphql.ParseSchema(schema, &q) 70 if err != nil { 71 return nil, err 72 } 73 h := handler{Schema: s} 74 handler := node.NewHTTPHandlerStack(h, cors, vhosts, nil) 75 76 stack.RegisterHandler("GraphQL UI", "/graphql/ui", GraphiQL{}) 77 stack.RegisterHandler("GraphQL", "/graphql", handler) 78 stack.RegisterHandler("GraphQL", "/graphql/", handler) 79 80 return &h, nil 81 }