-
Notifications
You must be signed in to change notification settings - Fork 0
/
module.go
130 lines (111 loc) · 3.87 KB
/
module.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package graphql
import (
"context"
"time"
"flamingo.me/dingo"
flamingoConfig "flamingo.me/flamingo/v3/framework/config"
"flamingo.me/flamingo/v3/framework/web"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/lru"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/spf13/cobra"
)
// Service defines the interface for graphql services
// The Schema returns the GraphQL Schema definition
// The Types configure the GraphQL type mapping and resolution
type Service interface {
Schema() []byte
Types(types *Types)
}
// Module defines the graphql entry point and binds the graphql command and routes
type Module struct{}
// Configure sets up dingo
func (*Module) Configure(injector *dingo.Injector) {
injector.BindMulti(new(cobra.Command)).ToProvider(command)
web.BindRoutes(injector, new(routes))
}
type routes struct {
exec graphql.ExecutableSchema
reverseRouter web.ReverseRouter
origins flamingoConfig.Slice
introspectionEnabled bool
uploadMaxSize int64
operationMiddlewares []graphql.OperationMiddleware
}
// Inject executable schema
func (r *routes) Inject(
reverseRouter web.ReverseRouter,
config *struct {
Exec graphql.ExecutableSchema `inject:",optional"`
OperationMiddlewares []graphql.OperationMiddleware `inject:",optional"`
Origins flamingoConfig.Slice `inject:"config:graphql.cors.origins"`
IntrospectionEnabled bool `inject:"config:graphql.introspectionEnabled,optional"`
UploadMaxSize int64 `inject:"config:graphql.multipartForm.uploadMaxSize,optional"`
},
) {
r.reverseRouter = reverseRouter
if config != nil {
r.exec = config.Exec
r.origins = config.Origins
r.introspectionEnabled = config.IntrospectionEnabled
r.uploadMaxSize = config.UploadMaxSize
r.operationMiddlewares = config.OperationMiddlewares
}
}
// Routes definition for flamingo router
func (r *routes) Routes(registry *web.RouterRegistry) {
if r.exec == nil {
panic("Please register/generate a schema module before running the server!")
}
var origins []string
err := r.origins.MapInto(&origins)
if err != nil {
panic(err)
}
corsHandler := corsHandler{origins: origins}
gqlHandler := func(es graphql.ExecutableSchema) *handler.Server {
srv := handler.New(es)
srv.AddTransport(transport.Websocket{
KeepAlivePingInterval: 10 * time.Second,
})
srv.AddTransport(transport.Options{})
srv.AddTransport(transport.GET{})
srv.AddTransport(transport.POST{})
srv.AddTransport(transport.MultipartForm{
MaxUploadSize: r.uploadMaxSize,
})
srv.SetQueryCache(lru.New(1000))
srv.Use(extension.Introspection{})
srv.Use(extension.AutomaticPersistedQuery{
Cache: lru.New(100),
})
return srv
}(r.exec)
gqlHandler.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
graphql.GetOperationContext(ctx).DisableIntrospection = !r.introspectionEnabled
return next(ctx)
})
for _, middleware := range r.operationMiddlewares {
gqlHandler.AroundOperations(middleware)
}
registry.MustRoute("/graphql", "graphql")
registry.HandleOptions("graphql", web.WrapHTTPHandler(corsHandler.preflightHandler()))
registry.HandleAny("graphql", wrapGqlHandler(corsHandler.gqlMiddleware(gqlHandler)))
registry.MustRoute("/graphql-console", "graphql.console")
u, _ := r.reverseRouter.Relative("graphql", nil)
registry.HandleAny("graphql.console", web.WrapHTTPHandler(playground.Handler("Flamingo GraphQL Console", u.String())))
}
// CueConfig for the module
func (m *Module) CueConfig() string {
return `
graphql: {
introspectionEnabled: bool | *false
multipartForm: {
uploadMaxSize: (int | *1.5M) & > 0
}
}
`
}