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