Working with Router

Configuring GraphOS Router for Apollo Connectors


In this guide, you'll learn how to configure GraphOS Router for Apollo Connectors by configuring connectors and other options in your router's configuration. Once you configure it, GraphOS Router enables connectors to orchestrate calls to REST endpoints.

tip
  • Just getting start with Apollo Connectors? Try out the quickstart to build your first connector.
  • Love developer tooling? Explore Apollo's IDE plugins for GraphQL development, including connectors support.

Configuring router for connectorsSince 2.0.0

Configuring a self-hosted router for connectors requires setting options in the router's YAML configuration file. When using Rover, you can call rover dev to start a router locally and use its --router-config option to pass your configuration file. For example:

terminal
APOLLO_KEY=... \
APOLLO_GRAPH_REF=... \
APOLLO_ROVER_DEV_ROUTER_VERSION=2.0.0 \
rover dev --supergraph-config supergraph.yaml
--router-config router.yaml

Connectors configuration are nested under the connectors key. Some configurations are applicable globally to all connectors, some are applicable to specific connector sources, and some can be configured for both. For example, you can apply request limits both globally across all connectors and on specific connector sources.

YAML
router.yaml
connectors:
  # This applies globally to all connectors
  max_requests_per_operation_per_source: 100
  # This applies to connectors with the "v1" source in the "example" subgraph
  sources:
    example.v1:
      max_requests_per_operation: 50

To specify a source, you must include the subgraph name and source name, separated by a .—for example, subgraph_name.connector_name.

note
The example configurations on this page use the configuration format and names in the General Availability release. If you are using a preview release, see the section on migrating your configuration.

To learn more about other router configurations, go to the router configuration reference.

Request limits

You can configure the maximum number of REST API requests for each GraphQL operation in the router. This can help avoid overwhelming upstream services. For requests that exceed the limit, the router returns a null value in the GraphQL result for any fields with @connect directives. Additionally, the router returns a GraphQL error in the errors array of the response. Partial data may still be returned for portions of the operation that weren't affected by the limit.

You set request limits in the router config YAML:

YAML
router.yaml
connectors:
  max_requests_per_operation_per_source: 100

This configuration limits the number of requests made to each connector source for a given GraphQL operation. If a connector doesn't define a source, then this limit is applied at the connector level.

The limit can also be configured for each individual connector source:

YAML
router.yaml
connectors:
  sources:
    example.v1:
      max_requests_per_operation: 50

Limits set on an individual source override the general max_requests_per_operation_per_source limit.

The limit can also be configured by setting the environment variable APOLLO_CONNECTORS_MAX_REQUESTS_PER_OPERATION. Any configuration in the YAML file overrides the environment variable setting.

Overriding baseURL for environment-specific API hosts

When using a self-hosted router, the baseURL of a @source directive can be overridden in the router configuration file.

For example, by configuring connectors.sources, you can override the baseURL for all @connect directives in the subgraph that reference the v1 source in the example subgraph.

YAML
router.yaml
connectors:
  sources:
    example.v1:
      # These configurations apply to connectors with the "v1" source in the "example" subgraph
      override_url: "https://api.example.com/v1/beta"
note
If a @connect directive doesn't specify the source attribute, its URL can't be overridden.

Configuration and environment variables

You may want to use a configuration value or environment variable as part of a request. You can do this per source in the router configuration using the $config section.

YAML
router.yaml
connectors:
  sources:
    example.v1:
      # These configurations apply to connectors with the "v1" source in the "example" subgraph
      $config:
        my.config.value: true
    example.v2:
      # These configurations apply to connectors with the "v2" source in the "example" subgraph
      $config:
        another.config.value: true # Applies to the "v2" source

You can then access the value using the $config variable in the schema, for example in the URL template or header of a connector:

GraphQL
type Query {
  something: String!
    @connect(
      http: {
        GET: "https://api.example.com/products/{$config.name_of_the_variable}"
        headers: [
          {
            name: "Authorization"
            value: "Bearer {$config.name_of_variable_containing_token}"
          }
        ]
      }
      selection: ""
    )
}

You can also access nested values using dot notation. For example $config.nested.value would refer to:

YAML
router.yaml
connectors:
  sources:
    example.v1:
      $config:
        nested:
          value: "some value"

Router configuration also lets you inject environment variables like this:

YAML
router.yaml
connectors:
  sources:
    example.v1:
      $config:
        name_of_the_variable: ${env.VARIABLE_NAME}

Telemetry

Router telemetry can be configured for connectors. See the connector troubleshooting guide's debugging section for information on how to add debug information to telemetry.

Attributes

Attributes can be attached to telemetry such as instruments and events. These attributes are used to filter and group data in your application performance monitor (APM).

The following standard attributes are available for connectors:

AttributeDescription
subgraph.nameThe name of the subgraph containing the connector
connector.source.nameThe name of the @source associated with this connector, if any
connector.http.methodThe HTTP method for the connector (GET or POST, for example)
connector.url.templateThe URL template for the connector
Selectors

A selector is used to extract data from connectors requests and responses and attach the data to telemetry such as instruments and events.

Apollo Connectors for REST APIs make HTTP calls to the upstream HTTP API. The selectors in the following table let you extract metrics from these HTTP requests and responses.

SelectorDefaultableValuesDescription
subgraph_nameNotrue|falseThe name of the subgraph containing the connector
connector_source NonameThe name of the @source associated with this connector, if any
connector_http_request_headerYesThe name of a connector request header
connector_http_response_headerYesThe name of a connector response header
connector_http_response_statusNocode|reasonThe status of a connector response
connector_http_methodNotrue|falseThe HTTP method of a connector request
connector_url_templateNotrue|falseThe URL template of a connector request
connector_request_mapping_problemsNoproblems|countAny mapping problems with the connector request
connector_response_mapping_problemsNoproblems|countAny mapping problems with the connector response
staticNoA static string value
errorNoreasonA string value containing error reason when it's a critical error

Instruments

An instrument in the router collects data and reports measurements to a metric backend. Supported instruments include standard instruments from OpenTelemetry, standard instruments for the router request lifecycle, and custom instruments. Supported instrument kinds are counters and histograms.

You can configure instruments in router.yaml with telemetry.instrumentation.instruments.

OpenTelemetry standard instruments

OpenTelemetry specifies multiple standard metric instruments that are available for connectors HTTP requests and responses:

  • http.client.request.body.size - A histogram of request body sizes for connectors HTTP requests.

  • http.client.request.duration - A histogram of request durations for connectors HTTP requests.

  • http.client.response.body.size - A histogram of response body sizes for connectors HTTP responses.

These instruments are configurable in router.yaml:

YAML
router.yaml
telemetry:
  instrumentation:
    instruments:
      connector:
        http.client.request.body.size: true
        http.client.request.duration: true
        http.client.response.body.size: true

The default_requirement_level setting configures whether or not these instruments are enabled by default. They can be customized by attaching or removing attributes. See attributes to learn more about configuring attributes.

YAML
router.yaml
telemetry:
  instrumentation:
    instruments:
      connector:
        http.client.request.duration:
          attributes:
            connector.source.name: true
Custom instruments
plan required
This feature is only available with a GraphOS plan. You can test it out by signing up for a Free plan. To compare GraphOS feature support across all plan types, see the pricing page.

You can define custom instruments on connectors HTTP requests and responses.

For example, the following custom instrument provides the number of 404 response statuses from a specific REST API:

YAML
router.yaml
telemetry:
  instrumentation:
    instruments:
      connector:
        acme.user.not.found:
          value: unit
          type: counter
          unit: count
          description: "Count of 404 responses from the user API"
          condition:
            all:
              - eq:
                  - 404
                  - connector_http_response_status: code
              - eq:
                  - "user_api"
                  - connector_source: name

See the router documentation for more details about configuring instruments.

Events

An event is used to signal when something of note happens, such as a connector request or response.

You can configure events for each service in router.yaml. Events can be standard or custom, and they can be triggered by configurable conditions.

See the router documentation for more details about configuring events.

Standard events

Standard events can be configured for connectors. The following enables standard connector HTTP response events at the INFO level:

YAML
router.yaml
events:
  connector:
    request: off
    response: info
    error: error
Custom events

Custom events can also be configured for connectors. The following example defines a custom event for each connector HTTP response at the INFO level:

YAML
router.yaml
events:
  connector:
    connector.response:
      message: "Connector response"
      level: info
      on: response
      attributes:
        connector.http.method: true
        connector.url.template: true
        response_status:
          connector_http_response_status: code

If you have a stdout logging exporter, the router logs each connector response with the attributes defined above:

Text
1INFO  connector.http.method=GET connector.url.template=/users response_status=200 Connector response kind=connector.response
2INFO  connector.http.method=GET connector.url.template=/users/{$this.id}/posts response_status=200 Connector response kind=connector.response

Authentication

Apollo Connectors can be used to call AWS HTTP APIs using AWS Signature Version 4 (SigV4). For example, you can use Apollo Connectors to invoke an AWS Lambda function and select fields from the JSON result to include in your GraphQL response:

GraphQL
@source(
  name: "lambda"
  http: { baseURL: "https://lambda.us-east-1.amazonaws.com" }
)
...
  @connect(
    source: "lambda"
    http: {
      POST: "/2015-03-31/functions/function_name/invocations"
      body: "argument: $this.function_argument"
    }
    selection: "$.function_output"
  )

SigV4 authentication is configured separately for each connector source, allowing you to specify a role with the least-privilege necessary to invoke the AWS API for that source:

YAML
router.yaml
authentication:
  connector:
    sources:
      subgraph_name.connector_source_name:
        aws_sig_v4:
          default_chain:
            profile_name: "default"
            region: "us-east-1"
            service_name: "lambda"
            assume_role:
              role_arn: "arn:aws:iam::XXXXXXXXXXXX:role/lambaexecute"
              session_name: "connector"

Authentication with coprocessors

You can use coprocessors to fetch authentication tokens for connectors. This is useful when you need to fetch a token from a different source, such as a database or a third-party service, before making a request to an API.

Start by configuring the coprocessor for the Execution Request stage and enabling the expose_sources_in_context feature of connectors:

YAML
router.yaml
connectors:
  expose_sources_in_context: true
coprocessor:
  url: http://localhost:4001
  execution:
    request:
      context: true

In the context of the coprocessor request, you will find a list of subgraph and source names from the query plan. You can use this information to determine which identity providers (IDPs) to query for tokens.

JSON
Coprocessor request
{
  "version": 1,
  "stage": "ExecutionRequest",
  "control": "continue",
  "id": "d0a8245df0efe8aa38a80dba1147fb2e",
  "context": {
    "entries": {
      "apollo_connectors::sources_in_query_plan": [
        { "subgraph_name": "products", "source_name": "v1" }
      ]
    }
  }
}

In the coprocessor response, you can add the API keys for each source to the context:

JSON
Coprocessor response
{
  "version": 1,
  "stage": "ExecutionRequest",
  "control": "continue",
  "id": "d0a8245df0efe8aa38a80dba1147fb2e",
  "context": {
    "entries": {
      "apollo_connectors::sources_in_query_plan": [
        { "subgraph_name": "products", "source_name": "v1" }
      ],
      "api_keys": {
        "products_v1": "abcd1234"
      }
    }
  }
}

Then in the configuration for your connector source, you can use the keys from the context as header values:

GraphQL
products.graphql
extend schema
  @source(
    name: "v1"
    http: {
      baseURL: "https://api.example.com/v1"
      headers: [
        {
          name: "Authorization"
          value: "Bearer {$context.api_keys.products_v1}"
        }
      ]
    }
  )

Limitations

See the limitations reference for a list of unsupported router features.

Feedback

Forums