GraphQL server with a focus on ease of use

graphql-go Sourcegraph Build Status GoDoc

The goal of this project is to provide full support of the GraphQL draft specification with a set of idiomatic, easy to use Go packages.

While still under heavy development (internal APIs are almost certainly subject to change), this library is safe for production use.

Features

  • minimal API
  • support for context.Context
  • support for the OpenTracing standard
  • schema type-checking against resolvers
  • resolvers are matched to the schema based on method sets (can resolve a GraphQL schema with a Go interface or Go struct).
  • handles panics in resolvers
  • parallel execution of resolvers
  • subscriptions

Roadmap

We're trying out the GitHub Project feature to manage graphql-go's development roadmap. Feedback is welcome and appreciated.

(Some) Documentation

Basic Sample

package main

import (
        "log"
        "net/http"

        graphql "github.com/graph-gophers/graphql-go"
        "github.com/graph-gophers/graphql-go/relay"
)

type query struct{}

func (_ *query) Hello() string { return "Hello, world!" }

func main() {
        s := `
                type Query {
                        hello: String!
                }
        `
        schema := graphql.MustParseSchema(s, &query{})
        http.Handle("/query", &relay.Handler{Schema: schema})
        log.Fatal(http.ListenAndServe(":8080", nil))
}

To test:

$ curl -XPOST -d '{"query": "{ hello }"}' localhost:8080/query

Resolvers

A resolver must have one method or field for each field of the GraphQL type it resolves. The method or field name has to be exported and match the schema's field's name in a non-case-sensitive way. You can use struct fields as resolvers by using SchemaOpt: UseFieldResolvers(). For example,

opts := []graphql.SchemaOpt{graphql.UseFieldResolvers()}
schema := graphql.MustParseSchema(s, &query{}, opts...)

When using UseFieldResolvers schema option, a struct field will be used only when:

  • there is no method for a struct field
  • a struct field does not implement an interface method
  • a struct field does not have arguments

The method has up to two arguments:

  • Optional context.Context argument.
  • Mandatory *struct { ... } argument if the corresponding GraphQL field has arguments. The names of the struct fields have to be exported and have to match the names of the GraphQL arguments in a non-case-sensitive way.

The method has up to two results:

  • The GraphQL field's value as determined by the resolver.
  • Optional error result.

Example for a simple resolver method:

func (r *helloWorldResolver) Hello() string {
	return "Hello world!"
}

The following signature is also allowed:

func (r *helloWorldResolver) Hello(ctx context.Context) (string, error) {
	return "Hello world!", nil
}

Schema Options

  • UseStringDescriptions() enables the usage of double quoted and triple quoted. When this is not enabled, comments are parsed as descriptions instead.
  • UseFieldResolvers() specifies whether to use struct field resolvers.
  • MaxDepth(n int) specifies the maximum field nesting depth in a query. The default is 0 which disables max depth checking.
  • MaxParallelism(n int) specifies the maximum number of resolvers per request allowed to run in parallel. The default is 10.
  • Tracer(tracer trace.Tracer) is used to trace queries and fields. It defaults to trace.OpenTracingTracer.
  • ValidationTracer(tracer trace.ValidationTracer) is used to trace validation errors. It defaults to trace.NoopValidationTracer.
  • Logger(logger log.Logger) is used to log panics during query execution. It defaults to exec.DefaultLogger.
  • DisableIntrospection() disables introspection queries.

Custom Errors

Errors returned by resolvers can include custom extensions by implementing the ResolverError interface:

type ResolverError interface {
	error
	Extensions() map[string]interface{}
}

Example of a simple custom error:

type droidNotFoundError struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

func (e droidNotFoundError) Error() string {
	return fmt.Sprintf("error [%s]: %s", e.Code, e.Message)
}

func (e droidNotFoundError) Extensions() map[string]interface{} {
	return map[string]interface{}{
		"code":    e.Code,
		"message": e.Message,
	}
}

Which could produce a GraphQL error such as:

{
  "errors": [
    {
      "message": "error [NotFound]: This is not the droid you are looking for",
      "path": [
        "droid"
      ],
      "extensions": {
        "code": "NotFound",
        "message": "This is not the droid you are looking for"
      }
    }
  ],
  "data": null
}

Examples

Companies that use this library

Owner
A group of gophers collaborating on GraphQL
null
Comments
  • Support subscriptions

    Support subscriptions

    This addresses the subscription part of #15.

    Please look through subscription_test.go which has an example subscription resolver implemented.

    I've left // TODO: ... markers where I feel the implementation could be improved, though not sure how.

    Missing from this PR is tracing for the execution of each query.

    I've put together a graphQL server that supports subscriptions as a proof of concept based on these changes (though it might be out of sync since this PR is changing)

  • Use Struct Field Resolver instead of Method

    Use Struct Field Resolver instead of Method

    This fixes #28. Essentially, it reduces lot of boilerplate code by making use of struct field as resolvers instead of creating methods for each struct field.

    Now, methods are required only when

    1. a struct implements a GraphQL interface. In this case, you create methods for fields which overlap
    2. a struct exposes a GraphQL field that accepts additional arguments i.e., first: Int, last: Int etc.
    3. there is GraphQL union type

    By using struct fields as resolvers, one could also benefit from DRY codebase by not having a pair of a struct which look the same (one for GraphQL and one for DB)

    Does this break existing API?

    No. This change is completely transparent and you can continue using your existing codebase.

    Can I still continue using methods as resolvers?

    Yes, by default, it uses method resolvers.

    How can I use struct fields as resolvers?

    When invoking graphql.ParseSchema() or graphql.MustParseSchema() to parse the schema, you pass in graphql.UseFieldResolvers() as an argument. For an example, take a look at ./example/social/server/server.go

    Additional Notes

    • also fixes #124
    • for an example, take a look at ./example/social/social.go & ./example/social/server/server.go
    • Unit tests are missing
  • Handle separate schemas?

    Handle separate schemas?

    Hello,

    Is there a (good) way to handle several separate schemas (modularization)? As it is, only a single schema can be parsed by this lib. I have several schemas split in several files.

    Thanks, Howe

  • Feature Request: Schema Stitching. Combining multiple schemas into one

    Feature Request: Schema Stitching. Combining multiple schemas into one

    Hi,

    are there any plan for implemente this feature or similar??

    Thanks a lot for all yours work.

    Ref: https://dev-blog.apollodata.com/graphql-schema-stitching-8af23354ac37

  • Update handler to follow best practices

    Update handler to follow best practices

    It would be really cool if relay.Handler can be updated to support the best practices outlined here: http://graphql.org/learn/serving-over-http/

    For example, it would be nice to support both GET and POST and deal with different Content-Types.

    I think the handler from graphql-go can be used as a reference as it is pretty complete: https://github.com/graphql-go/handler/blob/master/handler.go

  • Use field as resolver instead of method.

    Use field as resolver instead of method.

    Would it be possible to use a struct field as a resolver instead of always using methods? Most of my methods are just simple getters so it would be convenient to allow resolver to default to field. Then I could implement method only when I need special logic.

  • roadmap

    roadmap

    Hello,

    It would be great to see how feature compliant is this library with the graphql spec. Is it possible to maintain an issue or project to get an idea of when one can use certain feature.

    thanks. bsr

  • Added ability to use your own directives usage

    Added ability to use your own directives usage

    Hi,

    Description

    This PR goal is to bring ability to use so custom directives, as mentioned in issue https://github.com/graph-gophers/graphql-go/issues/151.

    I would be interested in having feedbacks, mainly on the way that I am currently re-using the internal/common package exported to be used publicly in pkg/common: maybe I could just copy objects I need (but I need a lot of these defined in package ;-)).

    Example usage

    Assuming that I have the following schema:

    directive @customDirective(
    	customAttribute: String!
    ) on FIELD_DEFINITION
    
    schema {
    	query: Query
    }
    
    type Query {
    	myTestQuery: String! @customDirective(customAttribute: hi)
    }
    

    I can use the directive in my resolver by adding a new argument:

    func (r *customDirectiveResolver) MyTestQuery(ctx context.Context, directives common.DirectiveList) string {
    	customDirective := directives.Get("customDirective")
    	customAttribute, _ := customDirective.Args.Get("customAttribute")
    
    	return fmt.Sprintf(
    		"Hello custom directive '%s' with attribute value '%s'!",
    		customDirective.Name.Name,
    		customAttribute.String(),
    	)
    }
    

    Thank you!

  • Use Struct Field Resolver instead of Method

    Use Struct Field Resolver instead of Method

    This fixes #28. Essentially, it reduces lot of boilerplate code by making use of struct field as resolvers instead of creating methods for each struct field.

    Now, methods are required only when

    1. a struct implements a GraphQL interface. In this case, you create methods for fields which overlap
    2. a struct exposes a GraphQL field that accepts additional arguments i.e., first: Int, last: Int etc.
    3. there is GraphQL union type

    By using struct fields as resolvers, one could also benefit from DRY codebase by not having a pair of a struct which look the same (one for GraphQL and one for DB)

    Does this break existing API?

    No. This change is completely transparent and you can continue using your existing codebase.

    Can I still continue using methods as resolvers?

    Yes, by default, it uses method resolvers. Even when UseFieldResolvers() is turned on, the method is given higher priority than the field. When there is no method, the field will be used if there is any.

    How can I use struct fields as resolvers?

    When invoking graphql.ParseSchema() or graphql.MustParseSchema() to parse the schema, you pass in graphql.UseFieldResolvers() as an argument. For an example, take a look at ./example/social/server/server.go

    Additional Notes

    • for an example, take a look at ./example/social/social.go & ./example/social/server/server.go
    • Unit tests are missing
  • POC: custom error handlers

    POC: custom error handlers

    This proof of concept will likely need changes before it can be merged but I hope it can serve as a starting point for a conversation around how we can elegantly handle errors in this library.

    This change gives users an optional hook to handle errors. Access to this hook opens up the door for several use cases:

    • Send more information rich errors to the client (related to #37) like sending error codes or other data related to error.
    • Single place to filter out "non-user-safe" errors from being sent to the client.
    • Integrate/send errors created in my resolves or graphql to a logging/monitoring service.

    One benefit of this approach is that it is non-breaking. Users are able to "opt-in" when needed.

  • implement sql.Scanner and driver.Value for graphql.ID type

    implement sql.Scanner and driver.Value for graphql.ID type

    This makes graphql.ID type implement sql.Scanner and driver.Valuer. This simplifies the data structures that I'm using so that they can implement the types that graphql likes but can also be marshaled into the DB.

  • Add Custom Directive Support for Fields

    Add Custom Directive Support for Fields

    based on graph-gophers/graphql-go#446 and work by @eko

    I intend to revive the stalled conversation from #446 with this PR. I addressed the open comments on that change.

  • Supporting Json as a scalar type

    Supporting Json as a scalar type

    This is continuation to Issue-537.

    Requirement is to have a field of json type, as in support all valid json types in one field,

    1. string - "abcd"
    2. map - map[string]interface{}
    3. slice - []interface{}

    Please suggest a way forward.

    Code Snippet:

    type JSON map[string]interface{}
    
    func (JSON) ImplementsGraphQLType(name string) bool {
    	return strings.Compare(name, "JSON") == 0
    }
    
    func (j *JSON) UnmarshalGraphQL(v interface{}) error {
    	if jsonMap, ok := v.(JSON); ok {
    		*j = jsonMap
    		return nil
    	}
    
    	return fmt.Errorf("wrong type `%T` for JSON", v)
    }
    
    type query struct {
    	Name string
    	Age  int
    }
    
    func (_ *query) Data() JSON    { return map[string]interface{}{"key": "1234", "Type": "development"} }
    func (_ *query) Data1() string { return "data2" }
    
    func graphQLEndpoint() {
    	s := `
                    type Query {
    					Name: String!
    					Data: JSON!
    					Data1: String!
                    }
    				scalar JSON
            `
    
    	queryObj := query{}
    	schema := graphql.MustParseSchema(s, &queryObj, graphql.UseFieldResolvers())
    	http.Handle("/query", &relay.Handler{Schema: schema})
    	log.Fatal(http.ListenAndServe(":8080", nil))
    }
    
  • Apollo Federation Compatibility

    Apollo Federation Compatibility

    Hi Y’all,

    Super excited to see that 1.4.0included support for Apollo Federation.

    Our team at Apollo maintains the Apollo Federation Subgraph Compatibility repo. Our goal for this project is to highlight projects that have support for Apollo Federation so that users of those libraries can see a visual representation of that support. We also include libraries in this list within our test suite to further validate their functionality.

    If you’d like to have your project tested against the Apollo Federation spec and displayed within this list, you can take a look at getting started here, or open an issue on our repo.

    Our team is happy to help with the process and answer any questions! Let me know what y’all think.

  • Expose Validate API?

    Expose Validate API?

    Hi team, I am hoping use it to write a "gateway" plugin for Traefik to further limit the queries exposed by Hasura GraphQL Engine.

    The Validate API is so useful! Currently it is in internal folder.

    https://github.com/graph-gophers/graphql-go/blob/5a1c1721f1b3d0c600222327f4a6d1dd5dd1d50c/internal/validation/validation.go#L68

    I am wondering is it possible to expose this Validate API? So we can leverage this API to do more work. Thank you so much! 😊

  • Support for nested Union type within schema type. And Union type as input?

    Support for nested Union type within schema type. And Union type as input?

    Hi Graph Gophers.

    We are trying to use the Union type in our schema. The first example I have tried is similar to the starwars example's SearchResult type, but the field is nested in another parent type.

    Does the package cater for this scenario? I cannot seem to get it to work. I get this error:

    "0": "j", "1": "s", "2": "o", "3": "n", "4": ":", "5": " ", "6": "e", "7": "r", "8": "r", "9": "o", "10": "r", "11": " ", "12": "c", "13": "a", "14": "l", "15": "l", "16": "i", "17": "n", "18": "g", "19": " ", "20": "M", "21": "a", "22": "r", "23": "s", "24": "h", "25": "a", "26": "l", "27": "J", "28": "S", "29": "O", "30": "N", "31": " ", "32": "f", "33": "o", "34": "r", "35": " ", "36": "t", "37": "y", "38": "p", "39": "e", "40": " ", "41": "j", "42": "s", "43": "o", "44": "n", "45": ".", "46": "R", "47": "a", "48": "w", "49": "M", "50": "e", "51": "s", "52": "s", "53": "a", "54": "g", "55": "e", "56": ":", "57": " ", "58": "i", "59": "n", "60": "v", "61": "a", "62": "l", "63": "i", "64": "d", "65": " ", "66": "c", "67": "h", "68": "a", "69": "r", "70": "a", "71": "c", "72": "t", "73": "e", "74": "r", "75": " ", "76": "'", "77": ",", "78": "'", "79": " ", "80": "l", "81": "o", "82": "o", "83": "k", "84": "i", "85": "n", "86": "g", "87": " ", "88": "f", "89": "o", "90": "r", "91": " ", "92": "b", "93": "e", "94": "g", "95": "i", "96": "n", "97": "n", "98": "i", "99": "n", "100": "g", "101": " ", "102": "o", "103": "f", "104": " ", "105": "v", "106": "a", "107": "l", "108": "u", "109": "e",

    And then I also want to confirm if the scenario for using a Union type as an input type has been covered yet?

  • Any plans to support enisdenjo/graphql-ws?

    Any plans to support enisdenjo/graphql-ws?

GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.
GraphJin - Build APIs in 5 minutes with GraphQL. An instant GraphQL to SQL compiler.

GraphJin - Build APIs in 5 minutes GraphJin gives you a high performance GraphQL API without you having to write any code. GraphQL is automagically co

Jan 1, 2023
GQLEngine is the best productive solution for implementing a GraphQL server 🚀

GQLEngine is the best productive solution for implementing a graphql server for highest formance examples starwars: https://github.com/gqlengine/starw

Apr 24, 2022
go generate based graphql server library
go generate based graphql server library

gqlgen What is gqlgen? gqlgen is a Go library for building GraphQL servers without any fuss. gqlgen is based on a Schema first approach — You get to D

Dec 31, 2022
Fast :zap: reverse proxy in front of any GraphQL server for caching, securing and monitoring.
Fast :zap: reverse proxy in front of any GraphQL server for caching, securing and monitoring.

Fast ⚡ reverse proxy in front of any GraphQL server for caching, securing and monitoring. Features ?? Caching RFC7234 compliant HTTP Cache. Cache quer

Nov 5, 2022
A collection of Go packages for creating robust GraphQL APIs

api-fu api-fu (noun) (informal) Mastery of APIs. ?? Packages The top level apifu package is an opinionated library that aims to make it as easy as pos

Dec 28, 2022
graphql parser + utilities

graphql utilities for dealing with GraphQL queries in Go. This package focuses on actually creating GraphQL servers and expects you to describe your s

Dec 20, 2022
An implementation of GraphQL for Go / Golang

graphql An implementation of GraphQL in Go. Follows the official reference implementation graphql-js. Supports: queries, mutations & subscriptions. Do

Dec 26, 2022
Convert Golang Struct To GraphQL Object On The Fly

Straf Convert Golang Struct To GraphQL Object On The Fly Easily Create GraphQL Schemas Example Converting struct to GraphQL Object type UserExtra stru

Oct 26, 2022
⚡️ A Go framework for rapidly building powerful graphql services

Thunder is a Go framework for rapidly building powerful graphql servers. Thunder has support for schemas automatically generated from Go types, live q

Dec 24, 2022
gqlanalysis makes easy to develop static analysis tools for GraphQL in Go.
gqlanalysis makes easy to develop static analysis tools for GraphQL in Go.

gqlanalysis gqlanalysis defines the interface between a modular static analysis for GraphQL in Go. gqlanalysis is inspired by go/analysis. gqlanalysis

Dec 14, 2022
Tools to write high performance GraphQL applications using Go/Golang.

graphql-go-tools Sponsors WunderGraph Are you looking for a GraphQL e2e data fetching solution? Supports frameworks like NextJS, type safety with gene

Dec 27, 2022
Go monolith with embedded microservices including GRPC,REST,GraphQL and The Clean Architecture.
Go monolith with embedded microservices including GRPC,REST,GraphQL and The Clean Architecture.

GoArcc - Go monolith with embedded microservices including GRPC,REST, graphQL and The Clean Architecture. Description When you start writing a Go proj

Dec 21, 2022
GraphQL implementation for click house in Go.
GraphQL implementation for click house in Go.

clickhouse-graphql-go GraphQL implementation for clickhouse in Go. This package stores real time streaming websocket data in clickhouse and uses Graph

Nov 20, 2022
GraphQL parser comparison in different languages

graphql-parser-bench Parsing a schema or document can be a critical part of the application, especially if you have to care about latency. This is the

Jul 10, 2022
A simple Go, GraphQL, and PostgreSQL starter template

Simple Go/GraphQL/PostgreSQL template Purpose Have a good starting point for any project that needs a graphql, go, and postgres backend. It's a very l

Jan 8, 2022
A GraphQL complete example using Golang And PostgreSQL

GraphQL with Golang A GraphQL complete example using Golang & PostgreSQL Installation Install the dependencies go get github.com/graphql-go/graphql go

Dec 6, 2022
This app is an attempt towards using go lang with graphql data fetch in react front end.

go_movies _A React js + GraphQL supported with backend in GoLang. This app is an attempt towards using go lang with graphql data fetch in react front

Dec 7, 2021
proof-of-concept minimal GraphQL service for LTV

LTV GraphQL Proof-of-Concept This is a barebones proof-of-concept of a possible GraphQL implementation that interacts with Core. It includes a few ver

Jan 4, 2022
Learn GraphQL with THE IDOLM@STER SHINY COLORS.

faaaar Learn GraphQL with THE IDOLM@STER SHINY COLORS. Getting Started The following is a simple example which get information about 20-year-old idols

Dec 11, 2022