github.com/codysnider/go-ethereum@v1.10.18-0.20220420071915-14f4ae99222a/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/internal/ethapi" 24 "github.com/ethereum/go-ethereum/node" 25 "github.com/graph-gophers/graphql-go" 26 ) 27 28 type handler struct { 29 Schema *graphql.Schema 30 } 31 32 func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 33 var params struct { 34 Query string `json:"query"` 35 OperationName string `json:"operationName"` 36 Variables map[string]interface{} `json:"variables"` 37 } 38 if err := json.NewDecoder(r.Body).Decode(¶ms); err != nil { 39 http.Error(w, err.Error(), http.StatusBadRequest) 40 return 41 } 42 43 response := h.Schema.Exec(r.Context(), params.Query, params.OperationName, params.Variables) 44 responseJSON, err := json.Marshal(response) 45 if err != nil { 46 http.Error(w, err.Error(), http.StatusInternalServerError) 47 return 48 } 49 if len(response.Errors) > 0 { 50 w.WriteHeader(http.StatusBadRequest) 51 } 52 53 w.Header().Set("Content-Type", "application/json") 54 w.Write(responseJSON) 55 56 } 57 58 // New constructs a new GraphQL service instance. 59 func New(stack *node.Node, backend ethapi.Backend, cors, vhosts []string) error { 60 if backend == nil { 61 panic("missing backend") 62 } 63 // check if http server with given endpoint exists and enable graphQL on it 64 return newHandler(stack, backend, cors, vhosts) 65 } 66 67 // newHandler returns a new `http.Handler` that will answer GraphQL queries. 68 // It additionally exports an interactive query browser on the / endpoint. 69 func newHandler(stack *node.Node, backend ethapi.Backend, cors, vhosts []string) error { 70 q := Resolver{backend} 71 72 s, err := graphql.ParseSchema(schema, &q) 73 if err != nil { 74 return err 75 } 76 h := handler{Schema: s} 77 handler := node.NewHTTPHandlerStack(h, cors, vhosts, nil) 78 79 stack.RegisterHandler("GraphQL UI", "/graphql/ui", GraphiQL{}) 80 stack.RegisterHandler("GraphQL", "/graphql", handler) 81 stack.RegisterHandler("GraphQL", "/graphql/", handler) 82 83 return nil 84 }