github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/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.FieldInterceptor, 21 graphql.ResponseInterceptor: 22 e.extensions = append(e.extensions, extension) 23 e.ext = processExtensions(e.extensions) 24 25 default: 26 panic(fmt.Errorf("cannot Use %T as a gqlgen handler extension because it does not implement any extension hooks", extension)) 27 } 28 } 29 30 // AroundFields is a convenience method for creating an extension that only implements field middleware 31 func (e *Executor) AroundFields(f graphql.FieldMiddleware) { 32 e.Use(aroundFieldFunc(f)) 33 } 34 35 // AroundOperations is a convenience method for creating an extension that only implements operation middleware 36 func (e *Executor) AroundOperations(f graphql.OperationMiddleware) { 37 e.Use(aroundOpFunc(f)) 38 } 39 40 // AroundResponses is a convenience method for creating an extension that only implements response middleware 41 func (e *Executor) AroundResponses(f graphql.ResponseMiddleware) { 42 e.Use(aroundRespFunc(f)) 43 } 44 45 type extensions struct { 46 operationMiddleware graphql.OperationMiddleware 47 responseMiddleware graphql.ResponseMiddleware 48 fieldMiddleware graphql.FieldMiddleware 49 operationParameterMutators []graphql.OperationParameterMutator 50 operationContextMutators []graphql.OperationContextMutator 51 } 52 53 func processExtensions(exts []graphql.HandlerExtension) extensions { 54 e := extensions{ 55 operationMiddleware: func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { 56 return next(ctx) 57 }, 58 responseMiddleware: func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { 59 return next(ctx) 60 }, 61 fieldMiddleware: func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { 62 return next(ctx) 63 }, 64 } 65 66 // this loop goes backwards so the first extension is the outer most middleware and runs first. 67 for i := len(exts) - 1; i >= 0; i-- { 68 p := exts[i] 69 if p, ok := p.(graphql.OperationInterceptor); ok { 70 previous := e.operationMiddleware 71 e.operationMiddleware = func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { 72 return p.InterceptOperation(ctx, func(ctx context.Context) graphql.ResponseHandler { 73 return previous(ctx, next) 74 }) 75 } 76 } 77 78 if p, ok := p.(graphql.ResponseInterceptor); ok { 79 previous := e.responseMiddleware 80 e.responseMiddleware = func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { 81 return p.InterceptResponse(ctx, func(ctx context.Context) *graphql.Response { 82 return previous(ctx, next) 83 }) 84 } 85 } 86 87 if p, ok := p.(graphql.FieldInterceptor); ok { 88 previous := e.fieldMiddleware 89 e.fieldMiddleware = func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { 90 return p.InterceptField(ctx, func(ctx context.Context) (res interface{}, err error) { 91 return previous(ctx, next) 92 }) 93 } 94 } 95 } 96 97 for _, p := range exts { 98 if p, ok := p.(graphql.OperationParameterMutator); ok { 99 e.operationParameterMutators = append(e.operationParameterMutators, p) 100 } 101 102 if p, ok := p.(graphql.OperationContextMutator); ok { 103 e.operationContextMutators = append(e.operationContextMutators, p) 104 } 105 } 106 107 return e 108 } 109 110 type aroundOpFunc func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler 111 112 func (r aroundOpFunc) ExtensionName() string { 113 return "InlineOperationFunc" 114 } 115 116 func (r aroundOpFunc) Validate(schema graphql.ExecutableSchema) error { 117 if r == nil { 118 return fmt.Errorf("OperationFunc can not be nil") 119 } 120 return nil 121 } 122 123 func (r aroundOpFunc) InterceptOperation(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler { 124 return r(ctx, next) 125 } 126 127 type aroundRespFunc func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response 128 129 func (r aroundRespFunc) ExtensionName() string { 130 return "InlineResponseFunc" 131 } 132 133 func (r aroundRespFunc) Validate(schema graphql.ExecutableSchema) error { 134 if r == nil { 135 return fmt.Errorf("ResponseFunc can not be nil") 136 } 137 return nil 138 } 139 140 func (r aroundRespFunc) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response { 141 return r(ctx, next) 142 } 143 144 type aroundFieldFunc func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) 145 146 func (f aroundFieldFunc) ExtensionName() string { 147 return "InlineFieldFunc" 148 } 149 150 func (f aroundFieldFunc) Validate(schema graphql.ExecutableSchema) error { 151 if f == nil { 152 return fmt.Errorf("FieldFunc can not be nil") 153 } 154 return nil 155 } 156 157 func (f aroundFieldFunc) InterceptField(ctx context.Context, next graphql.Resolver) (res interface{}, err error) { 158 return f(ctx, next) 159 }