github.com/99designs/gqlgen@v0.17.45/graphql/executor/extensions.go (about) 1 package executor 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/99designs/gqlgen/graphql" 8 ) 9 10 // Use adds the given extension to this Executor. 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 // AroundFields is a convenience method for creating an extension that only implements field middleware 32 func (e *Executor) AroundFields(f graphql.FieldMiddleware) { 33 e.Use(aroundFieldFunc(f)) 34 } 35 36 // AroundRootFields is a convenience method for creating an extension that only implements root field middleware 37 func (e *Executor) AroundRootFields(f graphql.RootFieldMiddleware) { 38 e.Use(aroundRootFieldFunc(f)) 39 } 40 41 // AroundOperations is a convenience method for creating an extension that only implements operation middleware 42 func (e *Executor) AroundOperations(f graphql.OperationMiddleware) { 43 e.Use(aroundOpFunc(f)) 44 } 45 46 // AroundResponses is a convenience method for creating an extension that only implements response middleware 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 // this loop goes backwards so the first extension is the outer most middleware and runs first. 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 }