1 package executor
2
3 import (
4 "context"
5 "fmt"
6
7 "github.com/99designs/gqlgen/graphql"
8 )
9
10
11 func (e *Executor) Use(extension graphql.HandlerExtension) {
12 if err := extension.Validate(e.es); err != nil {
13 panic(err)
14 }
15
16 switch extension.(type) {
17 case graphql.OperationParameterMutator,
18 graphql.OperationContextMutator,
19 graphql.OperationInterceptor,
20 graphql.RootFieldInterceptor,
21 graphql.FieldInterceptor,
22 graphql.ResponseInterceptor:
23 e.extensions = append(e.extensions, extension)
24 e.ext = processExtensions(e.extensions)
25
26 default:
27 panic(fmt.Errorf("cannot Use %T as a gqlgen handler extension because it does not implement any extension hooks", extension))
28 }
29 }
30
31
32 func (e *Executor) AroundFields(f graphql.FieldMiddleware) {
33 e.Use(aroundFieldFunc(f))
34 }
35
36
37 func (e *Executor) AroundRootFields(f graphql.RootFieldMiddleware) {
38 e.Use(aroundRootFieldFunc(f))
39 }
40
41
42 func (e *Executor) AroundOperations(f graphql.OperationMiddleware) {
43 e.Use(aroundOpFunc(f))
44 }
45
46
47 func (e *Executor) AroundResponses(f graphql.ResponseMiddleware) {
48 e.Use(aroundRespFunc(f))
49 }
50
51 type extensions struct {
52 operationMiddleware graphql.OperationMiddleware
53 responseMiddleware graphql.ResponseMiddleware
54 rootFieldMiddleware graphql.RootFieldMiddleware
55 fieldMiddleware graphql.FieldMiddleware
56 operationParameterMutators []graphql.OperationParameterMutator
57 operationContextMutators []graphql.OperationContextMutator
58 }
59
60 func processExtensions(exts []graphql.HandlerExtension) extensions {
61 e := extensions{
62 operationMiddleware: func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
63 return next(ctx)
64 },
65 responseMiddleware: func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
66 return next(ctx)
67 },
68 rootFieldMiddleware: func(ctx context.Context, next graphql.RootResolver) graphql.Marshaler {
69 return next(ctx)
70 },
71 fieldMiddleware: func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
72 return next(ctx)
73 },
74 }
75
76
77 for i := len(exts) - 1; i >= 0; i-- {
78 p := exts[i]
79 if p, ok := p.(graphql.OperationInterceptor); ok {
80 previous := e.operationMiddleware
81 e.operationMiddleware = func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
82 return p.InterceptOperation(ctx, func(ctx context.Context) graphql.ResponseHandler {
83 return previous(ctx, next)
84 })
85 }
86 }
87
88 if p, ok := p.(graphql.ResponseInterceptor); ok {
89 previous := e.responseMiddleware
90 e.responseMiddleware = func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
91 return p.InterceptResponse(ctx, func(ctx context.Context) *graphql.Response {
92 return previous(ctx, next)
93 })
94 }
95 }
96
97 if p, ok := p.(graphql.RootFieldInterceptor); ok {
98 previous := e.rootFieldMiddleware
99 e.rootFieldMiddleware = func(ctx context.Context, next graphql.RootResolver) graphql.Marshaler {
100 return p.InterceptRootField(ctx, func(ctx context.Context) graphql.Marshaler {
101 return previous(ctx, next)
102 })
103 }
104 }
105
106 if p, ok := p.(graphql.FieldInterceptor); ok {
107 previous := e.fieldMiddleware
108 e.fieldMiddleware = func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
109 return p.InterceptField(ctx, func(ctx context.Context) (res interface{}, err error) {
110 return previous(ctx, next)
111 })
112 }
113 }
114 }
115
116 for _, p := range exts {
117 if p, ok := p.(graphql.OperationParameterMutator); ok {
118 e.operationParameterMutators = append(e.operationParameterMutators, p)
119 }
120
121 if p, ok := p.(graphql.OperationContextMutator); ok {
122 e.operationContextMutators = append(e.operationContextMutators, p)
123 }
124 }
125
126 return e
127 }
128
129 type aroundOpFunc func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler
130
131 func (r aroundOpFunc) ExtensionName() string {
132 return "InlineOperationFunc"
133 }
134
135 func (r aroundOpFunc) Validate(schema graphql.ExecutableSchema) error {
136 if r == nil {
137 return fmt.Errorf("OperationFunc can not be nil")
138 }
139 return nil
140 }
141
142 func (r aroundOpFunc) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
143 return r(ctx, next)
144 }
145
146 type aroundRespFunc func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response
147
148 func (r aroundRespFunc) ExtensionName() string {
149 return "InlineResponseFunc"
150 }
151
152 func (r aroundRespFunc) Validate(schema graphql.ExecutableSchema) error {
153 if r == nil {
154 return fmt.Errorf("ResponseFunc can not be nil")
155 }
156 return nil
157 }
158
159 func (r aroundRespFunc) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
160 return r(ctx, next)
161 }
162
163 type aroundFieldFunc func(ctx context.Context, next graphql.Resolver) (res interface{}, err error)
164
165 func (f aroundFieldFunc) ExtensionName() string {
166 return "InlineFieldFunc"
167 }
168
169 func (f aroundFieldFunc) Validate(schema graphql.ExecutableSchema) error {
170 if f == nil {
171 return fmt.Errorf("FieldFunc can not be nil")
172 }
173 return nil
174 }
175
176 func (f aroundFieldFunc) InterceptField(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
177 return f(ctx, next)
178 }
179
180 type aroundRootFieldFunc func(ctx context.Context, next graphql.RootResolver) graphql.Marshaler
181
182 func (f aroundRootFieldFunc) ExtensionName() string {
183 return "InlineRootFieldFunc"
184 }
185
186 func (f aroundRootFieldFunc) Validate(schema graphql.ExecutableSchema) error {
187 if f == nil {
188 return fmt.Errorf("RootFieldFunc can not be nil")
189 }
190 return nil
191 }
192
193 func (f aroundRootFieldFunc) InterceptRootField(ctx context.Context, next graphql.RootResolver) graphql.Marshaler {
194 return f(ctx, next)
195 }
196
View as plain text