Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TT-11737] [PoC] custom Tyk directive @uppercase #428

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pkg/customdirective/customdirective.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package customdirective

type CustomDirective interface {
Name() string
DataType() string
Execute([]byte) ([]byte, error)
}
16 changes: 12 additions & 4 deletions pkg/engine/datasource/graphql_datasource/graphql_datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ import (
"io"
"net/http"

"github.com/buger/jsonparser"
"github.com/tidwall/sjson"

"github.com/TykTechnologies/graphql-go-tools/internal/pkg/unsafebytes"
"github.com/TykTechnologies/graphql-go-tools/pkg/ast"
"github.com/TykTechnologies/graphql-go-tools/pkg/astnormalization"
"github.com/TykTechnologies/graphql-go-tools/pkg/astparser"
"github.com/TykTechnologies/graphql-go-tools/pkg/astprinter"
"github.com/TykTechnologies/graphql-go-tools/pkg/asttransform"
"github.com/TykTechnologies/graphql-go-tools/pkg/astvalidation"
"github.com/TykTechnologies/graphql-go-tools/pkg/customdirective"
"github.com/TykTechnologies/graphql-go-tools/pkg/engine/datasource/httpclient"
"github.com/TykTechnologies/graphql-go-tools/pkg/engine/plan"
"github.com/TykTechnologies/graphql-go-tools/pkg/engine/resolve"
"github.com/TykTechnologies/graphql-go-tools/pkg/federation"
"github.com/TykTechnologies/graphql-go-tools/pkg/lexer/literal"
"github.com/TykTechnologies/graphql-go-tools/pkg/operationreport"
"github.com/buger/jsonparser"
"github.com/tidwall/sjson"
)

const removeNullVariablesDirectiveName = "removeNullVariables"
Expand Down Expand Up @@ -60,7 +60,8 @@ type Planner struct {
customScalarFieldRef int
unnulVariables bool

parentTypeNodes []ast.Node
parentTypeNodes []ast.Node
customDirectives map[string]customdirective.CustomDirective
}

func (p *Planner) parentNodeIsAbstract() bool {
Expand Down Expand Up @@ -90,6 +91,11 @@ func (p *Planner) EnterDirective(ref int) {

func (p *Planner) addDirectiveToNode(directiveRef int, node ast.Node) {
directiveName := p.visitor.Operation.DirectiveNameString(directiveRef)
if _, ok := p.customDirectives[directiveName]; ok {
// Custom directive
return
}

operationType := ast.OperationTypeQuery
if !p.isNested {
operationType = p.visitor.Operation.OperationDefinitions[p.visitor.Walker.Ancestors[0].Ref].OperationType
Expand Down Expand Up @@ -1308,6 +1314,7 @@ type Factory struct {
StreamingClient *http.Client
OnWsConnectionInitCallback *OnWsConnectionInitCallback
SubscriptionClient *SubscriptionClient
CustomDirectives map[string]customdirective.CustomDirective
}

func (f *Factory) Planner(ctx context.Context) plan.DataSourcePlanner {
Expand All @@ -1325,6 +1332,7 @@ func (f *Factory) Planner(ctx context.Context) plan.DataSourcePlanner {
batchFactory: f.BatchFactory,
fetchClient: f.HTTPClient,
subscriptionClient: f.SubscriptionClient,
customDirectives: f.CustomDirectives,
}
}

Expand Down
16 changes: 16 additions & 0 deletions pkg/engine/plan/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/TykTechnologies/graphql-go-tools/pkg/customdirective"
"reflect"
"regexp"
"strings"
Expand Down Expand Up @@ -37,6 +38,7 @@ type Configuration struct {
// In production, this should be set to false so that error messages are easier to understand
DisableResolveFieldPositions bool
CustomResolveMap map[string]resolve.CustomResolve
CustomDirectives map[string]customdirective.CustomDirective
}

type DirectiveConfigurations []DirectiveConfiguration
Expand Down Expand Up @@ -247,6 +249,7 @@ func NewPlanner(ctx context.Context, config Configuration) *Planner {
Walker: &planningWalker,
fieldConfigs: map[int]*FieldConfiguration{},
disableResolveFieldPositions: config.DisableResolveFieldPositions,
CustomDirectives: config.CustomDirectives,
}

p := &Planner{
Expand Down Expand Up @@ -384,6 +387,7 @@ type Visitor struct {
exportedVariables map[string]struct{}
skipIncludeFields map[int]skipIncludeField
disableResolveFieldPositions bool
CustomDirectives map[string]customdirective.CustomDirective
}

type skipIncludeField struct {
Expand Down Expand Up @@ -748,11 +752,23 @@ func (v *Visitor) resolveFieldValue(fieldRef, typeRef int, nullable bool, path [
fieldExport := v.resolveFieldExport(fieldRef)
switch typeName {
case "String":

// Start TT-11737 - [PoC] custom Tyk directive @uppercase
var customDirectives []customdirective.CustomDirective
for _, ref := range v.Operation.Fields[fieldRef].Directives.Refs {
directiveName := v.Operation.Input.ByteSliceString(v.Operation.Directives[ref].Name)
if customDirective, ok := v.CustomDirectives[directiveName]; ok {
customDirectives = append(customDirectives, customDirective)
}
}
// End

return &resolve.String{
Path: path,
Nullable: nullable,
Export: fieldExport,
UnescapeResponseJson: unescapeResponseJson,
CustomDirectives: customDirectives,
}
case "Boolean":
return &resolve.Boolean{
Expand Down
18 changes: 14 additions & 4 deletions pkg/engine/resolve/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import (
"sync"
"time"

"github.com/buger/jsonparser"
"github.com/cespare/xxhash/v2"
"github.com/tidwall/gjson"

"github.com/TykTechnologies/graphql-go-tools/internal/pkg/unsafebytes"
"github.com/TykTechnologies/graphql-go-tools/pkg/customdirective"
"github.com/TykTechnologies/graphql-go-tools/pkg/fastbuffer"
"github.com/TykTechnologies/graphql-go-tools/pkg/lexer/literal"
"github.com/TykTechnologies/graphql-go-tools/pkg/pool"
"github.com/buger/jsonparser"
"github.com/cespare/xxhash/v2"
"github.com/tidwall/gjson"
)

var (
Expand Down Expand Up @@ -1016,6 +1016,15 @@ func (r *Resolver) resolveString(ctx *Context, str *String, data []byte, stringB
)

value, valueType, _, err = jsonparser.Get(data, str.Path...)
// Start - TT-11737 - [PoC] custom Tyk directive @uppercase
for _, dir := range str.CustomDirectives {
value, err = dir.Execute(value)
if err != nil {
return err
}
}
// End - TT-11737

if err != nil || valueType != jsonparser.String {
if err == nil && str.UnescapeResponseJson {
switch valueType {
Expand Down Expand Up @@ -1561,6 +1570,7 @@ type String struct {
Export *FieldExport `json:"export,omitempty"`
UnescapeResponseJson bool `json:"unescape_response_json,omitempty"`
IsTypeName bool `json:"is_type_name,omitempty"`
CustomDirectives []customdirective.CustomDirective
}

func (_ *String) NodeKind() NodeKind {
Expand Down
13 changes: 13 additions & 0 deletions pkg/graphql/config_factory_proxy.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package graphql

import (
"github.com/TykTechnologies/graphql-go-tools/pkg/customdirective"
"net/http"
"time"

Expand All @@ -13,10 +14,17 @@ type proxyEngineConfigFactoryOptions struct {
httpClient *http.Client
streamingClient *http.Client
subscriptionClientFactory graphqlDataSource.GraphQLSubscriptionClientFactory
customDirectives map[string]customdirective.CustomDirective
}

type ProxyEngineConfigFactoryOption func(options *proxyEngineConfigFactoryOptions)

func WithProxyCustomDirectives(customDirectives map[string]customdirective.CustomDirective) ProxyEngineConfigFactoryOption {
return func(options *proxyEngineConfigFactoryOptions) {
options.customDirectives = customDirectives
}
}

func WithProxyHttpClient(client *http.Client) ProxyEngineConfigFactoryOption {
return func(options *proxyEngineConfigFactoryOptions) {
options.httpClient = client
Expand Down Expand Up @@ -51,6 +59,7 @@ type ProxyEngineConfigFactory struct {
proxyUpstreamConfig ProxyUpstreamConfig
batchFactory resolve.DataSourceBatchFactory
subscriptionClientFactory graphqlDataSource.GraphQLSubscriptionClientFactory
customDirectives map[string]customdirective.CustomDirective
}

func NewProxyEngineConfigFactory(schema *Schema, proxyUpstreamConfig ProxyUpstreamConfig, batchFactory resolve.DataSourceBatchFactory, opts ...ProxyEngineConfigFactoryOption) *ProxyEngineConfigFactory {
Expand Down Expand Up @@ -79,6 +88,7 @@ func NewProxyEngineConfigFactory(schema *Schema, proxyUpstreamConfig ProxyUpstre
proxyUpstreamConfig: proxyUpstreamConfig,
batchFactory: batchFactory,
subscriptionClientFactory: options.subscriptionClientFactory,
customDirectives: options.customDirectives,
}
}

Expand All @@ -97,6 +107,8 @@ func (p *ProxyEngineConfigFactory) EngineV2Configuration() (EngineV2Configuratio

conf := NewEngineV2Configuration(p.schema)

conf.SetCustomDirectives(p.customDirectives)

rawDoc, report := astparser.ParseGraphqlDocumentBytes(p.schema.rawInput)
if report.HasErrors() {
return EngineV2Configuration{}, report
Expand All @@ -108,6 +120,7 @@ func (p *ProxyEngineConfigFactory) EngineV2Configuration() (EngineV2Configuratio
p.httpClient,
WithDataSourceV2GeneratorSubscriptionConfiguration(p.streamingClient, p.proxyUpstreamConfig.SubscriptionType),
WithDataSourceV2GeneratorSubscriptionClientFactory(p.subscriptionClientFactory),
WithDataSourceV2GeneratorCustomDirectives(p.customDirectives),
)
if err != nil {
return EngineV2Configuration{}, err
Expand Down
24 changes: 21 additions & 3 deletions pkg/graphql/engine_config_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package graphql

import (
"errors"
"github.com/TykTechnologies/graphql-go-tools/pkg/customdirective"
"net/http"

"github.com/TykTechnologies/graphql-go-tools/pkg/ast"
Expand All @@ -19,6 +20,7 @@ type EngineV2Configuration struct {
plannerConfig plan.Configuration
websocketBeforeStartHook WebsocketBeforeStartHook
dataLoaderConfig dataLoaderConfig
customDirectives map[string]customdirective.CustomDirective
}

func NewEngineV2Configuration(schema *Schema) EngineV2Configuration {
Expand All @@ -41,6 +43,14 @@ type dataLoaderConfig struct {
EnableDataLoader bool
}

func (e *EngineV2Configuration) SetCustomDirectives(customDirectives map[string]customdirective.CustomDirective) {
e.plannerConfig.CustomDirectives = customDirectives
}

func (e *EngineV2Configuration) CustomDirectives() map[string]customdirective.CustomDirective {
return e.plannerConfig.CustomDirectives
}

func (e *EngineV2Configuration) SetCustomResolveMap(customResolveMap map[string]resolve.CustomResolve) {
e.plannerConfig.CustomResolveMap = customResolveMap
}
Expand Down Expand Up @@ -86,10 +96,17 @@ type dataSourceV2GeneratorOptions struct {
streamingClient *http.Client
subscriptionType SubscriptionType
subscriptionClientFactory graphqlDataSource.GraphQLSubscriptionClientFactory
customDirectives map[string]customdirective.CustomDirective
}

type DataSourceV2GeneratorOption func(options *dataSourceV2GeneratorOptions)

func WithDataSourceV2GeneratorCustomDirectives(customDirectives map[string]customdirective.CustomDirective) DataSourceV2GeneratorOption {
return func(options *dataSourceV2GeneratorOptions) {
options.customDirectives = customDirectives
}
}

func WithDataSourceV2GeneratorSubscriptionConfiguration(streamingClient *http.Client, subscriptionType SubscriptionType) DataSourceV2GeneratorOption {
return func(options *dataSourceV2GeneratorOptions) {
options.streamingClient = streamingClient
Expand Down Expand Up @@ -129,9 +146,10 @@ func (d *graphqlDataSourceV2Generator) Generate(config graphqlDataSource.Configu
}

factory := &graphqlDataSource.Factory{
HTTPClient: httpClient,
StreamingClient: definedOptions.streamingClient,
BatchFactory: batchFactory,
HTTPClient: httpClient,
StreamingClient: definedOptions.streamingClient,
BatchFactory: batchFactory,
CustomDirectives: definedOptions.customDirectives,
}

subscriptionClient, err := d.generateSubscriptionClient(httpClient, definedOptions)
Expand Down
Loading