github.com/TykTechnologies/tyk/apidef/adapter/gqlengineadapter
No package summary is available.
Package
Files: 5. Third party imports: 0. Imports from organisation: 5. Tests: 0. Benchmarks: 0.
Vars
var (
ErrGraphQLConfigIsMissingOperation = errors.New("graphql data source config is missing an operation")
)
Types
ProxyOnly
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| ApiDefinition |
|
No comment on field. |
| HttpClient |
|
No comment on field. |
| StreamingClient |
|
No comment on field. |
| Schema |
|
No comment on field. |
| subscriptionClientFactory |
|
No comment on field. |
type ProxyOnly struct {
ApiDefinition *apidef.APIDefinition
HttpClient *http.Client
StreamingClient *http.Client
Schema *graphql.Schema
subscriptionClientFactory graphqldatasource.GraphQLSubscriptionClientFactory
}
Supergraph
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| ApiDefinition |
|
No comment on field. |
| HttpClient |
|
No comment on field. |
| StreamingClient |
|
No comment on field. |
| subscriptionClientFactory |
|
No comment on field. |
type Supergraph struct {
ApiDefinition *apidef.APIDefinition
HttpClient *http.Client
StreamingClient *http.Client
subscriptionClientFactory graphqldatasource.GraphQLSubscriptionClientFactory
}
UniversalDataGraph
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| ApiDefinition |
|
No comment on field. |
| HttpClient |
|
No comment on field. |
| StreamingClient |
|
No comment on field. |
| Schema |
|
No comment on field. |
| subscriptionClientFactory |
|
No comment on field. |
type UniversalDataGraph struct {
ApiDefinition *apidef.APIDefinition
HttpClient *http.Client
StreamingClient *http.Client
Schema *graphql.Schema
subscriptionClientFactory graphqldatasource.GraphQLSubscriptionClientFactory
}
createGraphQLDataSourceFactoryParams
This type doesn't have documentation.
| Field name | Field type | Comment |
|---|---|---|
| graphqlConfig |
|
No comment on field. |
| subscriptionClientFactory |
|
No comment on field. |
| httpClient |
|
No comment on field. |
| streamingClient |
|
No comment on field. |
type createGraphQLDataSourceFactoryParams struct {
graphqlConfig apidef.GraphQLEngineDataSourceConfigGraphQL
subscriptionClientFactory graphqldatasource.GraphQLSubscriptionClientFactory
httpClient *http.Client
streamingClient *http.Client
}
Functions
func ConvertApiDefinitionHeadersToHttpHeaders
func ConvertApiDefinitionHeadersToHttpHeaders(apiDefHeaders map[string]string) http.Header {
if len(apiDefHeaders) == 0 {
return nil
}
engineV2Headers := make(http.Header)
for apiDefHeaderKey, apiDefHeaderValue := range apiDefHeaders {
engineV2Headers.Add(apiDefHeaderKey, apiDefHeaderValue)
}
return engineV2Headers
}
Cognitive complexity: 5, Cyclomatic complexity: 3
func RemoveDuplicateApiDefinitionHeaders
func RemoveDuplicateApiDefinitionHeaders(headers ...map[string]string) map[string]string {
hdr := make(map[string]string)
// headers priority depends on the order of arguments
for _, header := range headers {
for k, v := range header {
keyCanonical := http.CanonicalHeaderKey(k)
if _, ok := hdr[keyCanonical]; ok {
// skip because header is present
continue
}
hdr[keyCanonical] = v
}
}
return hdr
}
Cognitive complexity: 8, Cyclomatic complexity: 4
func (*ProxyOnly) EngineConfig
func (p *ProxyOnly) EngineConfig() (*graphql.EngineV2Configuration, error) {
var err error
if p.Schema == nil {
p.Schema, err = parseSchema(p.ApiDefinition.GraphQL.Schema)
if err != nil {
return nil, err
}
}
staticHeaders := make(http.Header)
for key, value := range p.ApiDefinition.GraphQL.Proxy.RequestHeaders {
staticHeaders.Set(key, value)
}
url := p.ApiDefinition.Proxy.TargetURL
if strings.HasPrefix(url, "tyk://") {
url = strings.ReplaceAll(url, "tyk://", "http://")
staticHeaders.Set(apidef.TykInternalApiHeader, "true")
}
upstreamConfig := graphql.ProxyUpstreamConfig{
URL: url,
StaticHeaders: staticHeaders,
SubscriptionType: graphqlSubscriptionType(p.ApiDefinition.GraphQL.Proxy.SubscriptionType),
}
v2Config, err := graphql.NewProxyEngineConfigFactory(
p.Schema,
upstreamConfig,
graphqldatasource.NewBatchFactory(),
graphql.WithProxyHttpClient(p.HttpClient),
graphql.WithProxyStreamingClient(p.StreamingClient),
graphql.WithProxySubscriptionClientFactory(subscriptionClientFactoryOrDefault(p.subscriptionClientFactory)),
).EngineV2Configuration()
v2Config.EnableSingleFlight(false)
return &v2Config, err
}
Cognitive complexity: 9, Cyclomatic complexity: 5
func (*Supergraph) EngineConfig
func (s *Supergraph) EngineConfig() (*graphql.EngineV2Configuration, error) {
dataSourceConfs := s.subgraphDataSourceConfigs()
var federationConfigV2Factory *graphql.FederationEngineConfigFactory
if s.ApiDefinition.GraphQL.Supergraph.DisableQueryBatching {
federationConfigV2Factory = graphql.NewFederationEngineConfigFactory(
dataSourceConfs,
nil,
graphql.WithFederationHttpClient(s.HttpClient),
graphql.WithFederationStreamingClient(s.StreamingClient),
graphql.WithFederationSubscriptionClientFactory(subscriptionClientFactoryOrDefault(s.subscriptionClientFactory)),
)
} else {
federationConfigV2Factory = graphql.NewFederationEngineConfigFactory(
dataSourceConfs,
graphqldatasource.NewBatchFactory(),
graphql.WithFederationHttpClient(s.HttpClient),
graphql.WithFederationStreamingClient(s.StreamingClient),
graphql.WithFederationSubscriptionClientFactory(subscriptionClientFactoryOrDefault(s.subscriptionClientFactory)),
)
}
err := federationConfigV2Factory.SetMergedSchemaFromString(s.ApiDefinition.GraphQL.Supergraph.MergedSDL)
if err != nil {
return nil, err
}
conf, err := federationConfigV2Factory.EngineV2Configuration()
if err != nil {
return nil, err
}
conf.EnableSingleFlight(true)
if !s.ApiDefinition.GraphQL.Supergraph.DisableQueryBatching {
conf.EnableDataLoader(true)
}
return &conf, nil
}
Cognitive complexity: 10, Cyclomatic complexity: 5
func (*UniversalDataGraph) EngineConfig
func (u *UniversalDataGraph) EngineConfig() (*graphql.EngineV2Configuration, error) {
var err error
if u.Schema == nil {
u.Schema, err = parseSchema(u.ApiDefinition.GraphQL.Schema)
if err != nil {
return nil, err
}
}
conf := graphql.NewEngineV2Configuration(u.Schema)
conf.EnableSingleFlight(false)
fieldConfigs := u.engineConfigV2FieldConfigs()
datsSources, err := u.engineConfigV2DataSources()
if err != nil {
return nil, err
}
conf.SetFieldConfigurations(fieldConfigs)
conf.SetDataSources(datsSources)
return &conf, nil
}
Cognitive complexity: 6, Cyclomatic complexity: 4
Private functions
func appendApiDefQueriesConfigToEngineV2Queries
appendApiDefQueriesConfigToEngineV2Queries (engineV2Queries *[]restdatasource.QueryConfiguration, apiDefQueries []apidef.QueryVariable)
References: restdatasource.QueryConfiguration.
func appendURLQueryParamsToEngineV2Queries
appendURLQueryParamsToEngineV2Queries (engineV2Queries *[]restdatasource.QueryConfiguration, queryValues neturl.Values)
References: restdatasource.QueryConfiguration, sort.Slice, strings.Join.
func createArgumentConfigurationsForArgumentNames
createArgumentConfigurationsForArgumentNames (argumentNames ...string) plan.ArgumentsConfigurations
References: plan.ArgumentConfiguration, plan.ArgumentsConfigurations, plan.FieldArgumentSource.
func createGraphQLDataSourceFactory
createGraphQLDataSourceFactory (params createGraphQLDataSourceFactoryParams) (*graphqldatasource.Factory, error)
References: errors.New, graphqldatasource.Factory, graphqldatasource.SubscriptionClient, graphqldatasource.WithWSSubProtocol.
func extractURLQueryParamsForEngineV2
extractURLQueryParamsForEngineV2 (url string, providedApiDefQueries []apidef.QueryVariable) (string, []restdatasource.QueryConfiguration, error)
References: neturl.ParseQuery, restdatasource.QueryConfiguration, strings.Split.
func generateRestDataSourceFromGraphql
generateRestDataSourceFromGraphql (config apidef.GraphQLEngineDataSourceConfigGraphQL) (json.RawMessage, error)
References: graphql.MarshalRequestString, graphql.Request, restdatasource.ConfigJSON, restdatasource.Configuration, restdatasource.FetchConfiguration.
func graphqlDataSourceConfiguration
graphqlDataSourceConfiguration (url string, method string, headers map[string]string, subscriptionType apidef.SubscriptionType) graphqldatasource.Configuration
References: apidef.GQLSubscriptionSSE, apidef.TykInternalApiHeader, graphqldatasource.Configuration, graphqldatasource.FetchConfiguration, graphqldatasource.SubscriptionConfiguration, strings.HasPrefix, strings.ReplaceAll.
func graphqlDataSourceWebSocketProtocol
graphqlDataSourceWebSocketProtocol (subscriptionType apidef.SubscriptionType) string
References: apidef.GQLSubscriptionTransportWS, graphqldatasource.ProtocolGraphQLTWS, graphqldatasource.ProtocolGraphQLWS.
func graphqlSubscriptionType
graphqlSubscriptionType (subscriptionType apidef.SubscriptionType) graphql.SubscriptionType
References: apidef.GQLSubscriptionSSE, apidef.GQLSubscriptionTransportWS, apidef.GQLSubscriptionWS, graphql.SubscriptionTypeGraphQLTransportWS, graphql.SubscriptionTypeGraphQLWS, graphql.SubscriptionTypeSSE, graphql.SubscriptionTypeUnknown.
func parseSchema
parseSchema (schemaAsString string) (*graphql.Schema, error)
References: graphql.NewSchemaFromString.
func subscriptionClientFactoryOrDefault
subscriptionClientFactoryOrDefault (providedSubscriptionClientFactory graphqldatasource.GraphQLSubscriptionClientFactory) graphqldatasource.GraphQLSubscriptionClientFactory
References: graphqldatasource.DefaultSubscriptionClientFactory.
func subgraphDataSourceConfigs
subgraphDataSourceConfigs () []graphqldatasource.Configuration
References: graphqldatasource.Configuration, graphqldatasource.FederationConfiguration, http.MethodPost.
func determineChildNodes
determineChildNodes (planDataSources []plan.DataSourceConfiguration) error
References: graphql.NewIsDataSourceConfigV2RootFieldSkipFunc, plan.TypeField, restdatasource.Factory.
func engineConfigV2Arguments
engineConfigV2Arguments (fieldConfs *plan.FieldConfigurations, generatedArgs map[graphql.TypeFieldLookupKey]graphql.TypeFieldArguments)
References: graphql.CreateTypeFieldLookupKey, plan.FieldConfiguration.
func engineConfigV2DataSources
engineConfigV2DataSources () ([]plan.DataSourceConfiguration, error)
References: apidef.GraphQLEngineDataSourceConfigGraphQL, apidef.GraphQLEngineDataSourceConfigKafka, apidef.GraphQLEngineDataSourceConfigREST, apidef.GraphQLEngineDataSourceKindGraphQL, apidef.GraphQLEngineDataSourceKindKafka, apidef.GraphQLEngineDataSourceKindREST, graphqldatasource.ConfigJson, json.Unmarshal, kafkadatasource.ConfigJSON, kafkadatasource.Configuration, kafkadatasource.Factory, kafkadatasource.SASL, kafkadatasource.SubscriptionConfiguration, plan.DataSourceConfiguration, plan.TypeField, restdatasource.ConfigJSON, restdatasource.Configuration, restdatasource.Factory, restdatasource.FetchConfiguration.
func engineConfigV2FieldConfigs
engineConfigV2FieldConfigs () plan.FieldConfigurations
References: graphql.CreateTypeFieldArgumentsLookupMap, graphql.NewSkipReservedNamesFunc, plan.FieldConfiguration.
Tests
Files: 5. Third party imports: 2. Imports from organisation: 5. Tests: 19. Benchmarks: 0.
Constants
const federationAccountsServiceSDL = `extend type Query {me: User} type User @key(fields: "id"){ id: ID! username: String!}`
const federationMergedSDL = `type Query { me: User topProducts(first: Int = 5): [Product] } type User { id: ID! username: String! reviews: [Review] } type Product { upc: String! name: String! price: Int! reviews: [Review] } type Review { body: String! author: User! product: Product! }`
const federationProductsServiceSDL = `extend type Query {topProducts(first: Int = 5): [Product]} type Product @key(fields: "upc") {upc: String! name: String! price: Int!}`
const federationReviewsServiceSDL = `type Review { body: String! author: User! @provides(fields: "username") product: Product! } extend type User @key(fields: "id") { id: ID! @external reviews: [Review] } extend type Product @key(fields: "upc") { upc: String! @external reviews: [Review] }`
const graphqlSubgraphSchema = `scalar _Any scalar _FieldSet union _Entity = User type _Service { sdl: String } type Query { me: User _entities(representations: [_Any!]!): [_Entity]! _service: _Service! } type User { id: ID! username: String! }`
Vars
var graphqlEngineV2ConfigJson = `{
"enabled": true,
"execution_mode": "executionEngine",
"version": "2",
"schema": ` + v2Schema + `,
"last_schema_update": "2020-11-11T11:11:11.000+01:00",
"engine": {
"field_configs": [
{
"type_name": "Query",
"field_name": "rest",
"disable_default_mapping": false,
"path": ["my_rest"]
}
],
"data_sources": [
{
"kind": "REST",
"name": "",
"internal": true,
"root_fields": [
{ "type": "Query", "fields": ["rest"] }
],
"config": {
"url": "tyk://rest-example",
"method": "POST",
"headers": {
"Authorization": "123",
"X-Custom": "A, B"
},
"query": [
{
"name": "q",
"value": "val1,val2"
},
{
"name": "repeat",
"value": "val1"
},
{
"name": "repeat",
"value": "val2"
}
],
"body": "body"
}
},
{
"kind": "GraphQL",
"internal": true,
"root_fields": [
{ "type": "Query", "fields": ["gql"] }
],
"config": {
"url": "tyk://graphql-example",
"method": "POST",
"subscription_type": "sse"
}
},
{
"kind": "REST",
"name": "",
"internal": true,
"root_fields": [
{ "type": "Query", "fields": ["withChildren"] }
],
"config": {
"url": "https://rest.example.com",
"method": "POST",
"headers": {},
"query": [],
"body": ""
}
},
{
"kind": "REST",
"name": "",
"internal": true,
"root_fields": [
{ "type": "WithChildren", "fields": ["nested"] }
],
"config": {
"url": "https://rest.example.com",
"method": "POST",
"headers": {},
"query": [],
"body": ""
}
},
{
"kind": "GraphQL",
"internal": false,
"root_fields": [
{ "type": "Query", "fields": ["multiRoot1","multiRoot2"] }
],
"config": {
"url": "https://graphql.example.com",
"method": "POST",
"headers": {
"Auth": "123"
}
}
},
{
"kind": "REST",
"name": "restWithQueryParams",
"internal": true,
"root_fields": [
{ "type": "Query", "fields": ["restWithQueryParams"] }
],
"config": {
"url": "https://rest-with-query-params.example.com?q={{.arguments.q}}&order={{.arguments.order}}",
"method": "POST",
"headers": {},
"query": [
{
"name": "limit",
"value": "{{.arguments.limit}}"
}
],
"body": ""
}
},
{
"kind": "REST",
"name": "restWithPathParams",
"internal": true,
"root_fields": [
{ "type": "Query", "fields": ["restWithPathParams"] }
],
"config": {
"url": "https://rest-with-path-params.example.com/{{.arguments.id}}",
"method": "POST",
"headers": {},
"query": [],
"body": ""
}
},
{
"kind": "REST",
"name": "restWithFullUrlAsParam",
"internal": true,
"root_fields": [
{ "type": "Query", "fields": ["restWithFullUrlAsParam"] }
],
"config": {
"url": "{{.arguments.url}}",
"method": "POST",
"headers": {},
"query": [],
"body": ""
}
},
{
"kind": "GraphQL",
"internal": false,
"root_fields": [
{ "type": "Query", "fields": ["idType"] }
],
"config": {
"url": "https://graphql.example.com",
"method": "POST",
"headers": {
"Auth": "123"
}
}
},
{
"kind": "GraphQL",
"internal": false,
"root_fields": [
{ "type": "Nested", "fields": ["nestedGql"] }
],
"config": {
"url": "https://graphql.example.com",
"method": "POST",
"headers": {
"Auth": "123"
},
"has_operation": true,
"operation": "{ fromNested }",
"variables": ""
}
},
{
"kind": "Kafka",
"name": "kafka-consumer-group",
"internal": false,
"root_fields": [{
"type": "Subscription",
"fields": [
"foobar"
]
}],
"config": {
"broker_addresses": ["localhost:9092"],
"topics": ["test.topic"],
"group_id": "test.consumer.group",
"client_id": "test.client.id",
"kafka_version": "V2_8_0_0",
"start_consuming_latest": true,
"balance_strategy": "BalanceStrategySticky",
"isolation_level": "ReadCommitted",
"sasl": {
"enable": true,
"user": "admin",
"password": "admin-secret"
}
}
},
{
"kind": "Kafka",
"name": "kafka-consumer-group-with-variable",
"internal": false,
"root_fields": [{
"type": "Subscription",
"fields": [
"foobarTopicWithVariable"
]
}],
"config": {
"broker_addresses": ["localhost:9092"],
"topics": ["test.topic.{{.arguments.name}}"],
"group_id": "test.consumer.group",
"client_id": "test.client.id",
"kafka_version": "V2_8_0_0",
"start_consuming_latest": true,
"balance_strategy": "BalanceStrategySticky",
"isolation_level": "ReadCommitted",
"sasl": {
"enable": true,
"user": "admin",
"password": "admin-secret"
}
}
}
]
},
"playground": {}
}`
var graphqlEngineV2SupergraphConfigJson = `{
"enabled": true,
"execution_mode": "supergraph",
"version": "2",
"schema": "",
"last_schema_update": "2020-11-11T11:11:11.000+01:00",
"engine": {
"field_configs": [],
"data_sources": []
},
"supergraph": {
"subgraphs": [
{
"api_id": "",
"url": "tyk://accounts.service",
"sdl": ` + strconv.Quote(federationAccountsServiceSDL) + `,
"headers": {
"header1": "override_global",
"Auth": "appended_header"
},
"subscription_type": "sse"
},
{
"api_id": "",
"url": "http://products.service",
"sdl": ` + strconv.Quote(federationProductsServiceSDL) + `
},
{
"api_id": "",
"url": "http://ignored.service",
"sdl": ""
},
{
"api_id": "",
"url": "http://reviews.service",
"sdl": ` + strconv.Quote(federationReviewsServiceSDL) + `,
"headers": {
"header1": "override_global",
"header2": "value2",
"Auth": "appended_header"
}
}
],
"global_headers": {
"header1": "value1",
"header2": "value2"
},
"merged_sdl": "` + federationMergedSDL + `"
},
"playground": {}
}`
var graphqlProxyOnlyConfig = `{
"enabled": true,
"execution_mode": "proxyOnly",
"version": "2",
"schema": "type Query { hello(name: String!): String! }",
"last_schema_update": "2020-11-11T11:11:11.000+01:00",
"proxy": {
"auth_headers": {
"Authorization": "123abc"
},
"subscription_type": "sse"
},
"engine": {
"field_configs": [],
"data_sources": []
},
"supergraph": {
"subgraphs": [],
"global_headers": {},
"merged_sdl": ""
},
"playground": {}
}`
var graphqlSubgraphConfig = `{
"enabled": true,
"execution_mode": "subgraph",
"version": "2",
"schema": ` + strconv.Quote(graphqlSubgraphSchema) + `,
"last_schema_update": "2020-11-11T11:11:11.000+01:00",
"proxy": {
"auth_headers": {
"Authorization": "123abc"
}
},
"engine": {
"field_configs": [],
"data_sources": []
},
"subgraph": {
"sdl": ` + strconv.Quote(federationAccountsServiceSDL) + `,
"subscription_type": "graphql-transport-ws"
},
"playground": {}
}`
var mockSubscriptionClient = &graphqldatasource.SubscriptionClient{}
var v2Schema = strconv.Quote(`type Query {
rest: String
gql(id: ID!, name: String): String
deepGQL: DeepGQL
withChildren: WithChildren
multiRoot1: MultiRoot1
multiRoot2: MultiRoot2
restWithQueryParams(q: String, order: String, limit: Int): [String]
restWithPathParams(id: String): [String]
restWithFullUrlAsParam(url: String): [String]
idType: IDType!
}
interface IDType {
id: ID!
}
type WithChildren implements IDType {
id: ID!
name: String
nested: Nested
}
type Nested {
id: ID!
name: String!
nestedGql: String!
}
type MultiRoot1 {
id: ID!
}
type MultiRoot2 {
name: String!
}
type DeepGQL {
query(code: String!): String
}
type Subscription {
foobar: Int
foobarTopicWithVariable(name: String): Int
}`)
Types
MockSubscriptionClientFactory
This type doesn't have documentation.
type MockSubscriptionClientFactory struct{}