diff --git a/docs/shared/config/apq.mdx b/docs/shared/config/apq.mdx new file mode 100644 index 0000000000..fab7cb309f --- /dev/null +++ b/docs/shared/config/apq.mdx @@ -0,0 +1,30 @@ +### `apq` + +```yaml title="apq" +apq: + enabled: true + router: + cache: + in_memory: + limit: 1 + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: null + urls: + - http://example.com/urls_item + username: example_username + subgraph: + all: + enabled: false + subgraphs: {} +``` diff --git a/docs/shared/config/authentication.mdx b/docs/shared/config/authentication.mdx new file mode 100644 index 0000000000..323ef3c8d0 --- /dev/null +++ b/docs/shared/config/authentication.mdx @@ -0,0 +1,44 @@ +### `authentication` + + + +```yaml title="authentication" +authentication: + connector: + sources: {} + router: + jwt: + header_name: authorization + header_value_prefix: Bearer + ignore_other_prefixes: false + jwks: + - algorithms: null + headers: + - name: example_name + value: example_value + issuer: example_issuer + poll_interval: + nanos: 0 + secs: 60 + url: http://service.example.com/url + on_error: Continue + sources: + - name: authorization + type: header + value_prefix: Bearer + subgraph: + all: + aws_sig_v4: + hardcoded: + access_key_id: example_access_key_id + assume_role: + external_id: example_external_id + role_arn: example_role_arn + session_name: example_session_name + region: example_region + secret_access_key: example_secret_access_key + service_name: example_service_name + subgraphs: {} +``` + + diff --git a/docs/shared/config/authorization.mdx b/docs/shared/config/authorization.mdx new file mode 100644 index 0000000000..a26d2b8a93 --- /dev/null +++ b/docs/shared/config/authorization.mdx @@ -0,0 +1,13 @@ +### `authorization` + +```yaml title="authorization" +authorization: + directives: + dry_run: false + enabled: true + errors: + log: true + response: errors + reject_unauthorized: false + require_authentication: false +``` diff --git a/docs/shared/config/batching.mdx b/docs/shared/config/batching.mdx new file mode 100644 index 0000000000..6f2bea7318 --- /dev/null +++ b/docs/shared/config/batching.mdx @@ -0,0 +1,12 @@ +### `batching` + +```yaml title="batching" +batching: + enabled: false + maximum_size: null + mode: batch_http_link + subgraph: + all: + enabled: false + subgraphs: {} +``` diff --git a/docs/shared/config/connectors.mdx b/docs/shared/config/connectors.mdx new file mode 100644 index 0000000000..a4a679902b --- /dev/null +++ b/docs/shared/config/connectors.mdx @@ -0,0 +1,10 @@ +### `connectors` + +```yaml title="connectors" +connectors: + debug_extensions: false + expose_sources_in_context: false + max_requests_per_operation_per_source: null + sources: {} + subgraphs: {} +``` diff --git a/docs/shared/config/coprocessor.mdx b/docs/shared/config/coprocessor.mdx new file mode 100644 index 0000000000..49c37e5fea --- /dev/null +++ b/docs/shared/config/coprocessor.mdx @@ -0,0 +1,98 @@ +### `coprocessor` + + + +```yaml title="coprocessor" +coprocessor: + client: + dns_resolution_strategy: ipv4_only + experimental_http2: enable + execution: + request: + body: false + context: false + headers: false + method: false + query_plan: false + sdl: false + response: + body: false + context: false + headers: false + sdl: false + status_code: false + router: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + path: false + sdl: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + sdl: false + status_code: false + subgraph: + all: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + service_name: false + subgraph_request_id: false + uri: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + service_name: false + status_code: false + subgraph_request_id: false + supergraph: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + sdl: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + sdl: false + status_code: false + timeout: + nanos: 0 + secs: 1 + url: http://service.example.com/url +``` + + diff --git a/docs/shared/config/cors.mdx b/docs/shared/config/cors.mdx new file mode 100644 index 0000000000..69a0bf05e5 --- /dev/null +++ b/docs/shared/config/cors.mdx @@ -0,0 +1,17 @@ +### `cors` + +```yaml title="cors" +cors: + allow_any_origin: false + allow_credentials: false + allow_headers: [] + expose_headers: null + match_origins: null + max_age: null + methods: + - GET + - POST + - OPTIONS + origins: + - https://studio.apollographql.com +``` diff --git a/docs/shared/config/csrf.mdx b/docs/shared/config/csrf.mdx new file mode 100644 index 0000000000..9591056a28 --- /dev/null +++ b/docs/shared/config/csrf.mdx @@ -0,0 +1,9 @@ +### `csrf` + +```yaml title="csrf" +csrf: + required_headers: + - x-apollo-operation-name + - apollo-require-preflight + unsafe_disabled: false +``` diff --git a/docs/shared/config/demand_control.mdx b/docs/shared/config/demand_control.mdx new file mode 100644 index 0000000000..b94def2bf3 --- /dev/null +++ b/docs/shared/config/demand_control.mdx @@ -0,0 +1,11 @@ +### `demand_control` + +```yaml title="demand_control" +demand_control: + enabled: false + mode: measure + strategy: + static_estimated: + list_size: 0 + max: 0.0 +``` diff --git a/docs/shared/config/experimental_chaos.mdx b/docs/shared/config/experimental_chaos.mdx new file mode 100644 index 0000000000..0b50502cfd --- /dev/null +++ b/docs/shared/config/experimental_chaos.mdx @@ -0,0 +1,6 @@ +### `experimental_chaos` + +```yaml title="experimental_chaos" +experimental_chaos: + force_reload: null +``` diff --git a/docs/shared/config/experimental_type_conditioned_fetching.mdx b/docs/shared/config/experimental_type_conditioned_fetching.mdx new file mode 100644 index 0000000000..2902967d69 --- /dev/null +++ b/docs/shared/config/experimental_type_conditioned_fetching.mdx @@ -0,0 +1,5 @@ +### `experimental_type_conditioned_fetching` + +```yaml title="experimental_type_conditioned_fetching" +experimental_type_conditioned_fetching: false +``` diff --git a/docs/shared/config/fleet_detector.mdx b/docs/shared/config/fleet_detector.mdx new file mode 100644 index 0000000000..eb30000b57 --- /dev/null +++ b/docs/shared/config/fleet_detector.mdx @@ -0,0 +1,5 @@ +### `fleet_detector` + +```yaml title="fleet_detector" +fleet_detector: {} +``` diff --git a/docs/shared/config/forbid_mutations.mdx b/docs/shared/config/forbid_mutations.mdx new file mode 100644 index 0000000000..ffab6b2f68 --- /dev/null +++ b/docs/shared/config/forbid_mutations.mdx @@ -0,0 +1,5 @@ +### `forbid_mutations` + +```yaml title="forbid_mutations" +forbid_mutations: false +``` diff --git a/docs/shared/config/headers.mdx b/docs/shared/config/headers.mdx new file mode 100644 index 0000000000..8ae504126d --- /dev/null +++ b/docs/shared/config/headers.mdx @@ -0,0 +1,11 @@ +### `headers` + +```yaml title="headers" +headers: + all: + request: + - insert: + name: example_name + value: example_value + subgraphs: {} +``` diff --git a/docs/shared/config/health_check.mdx b/docs/shared/config/health_check.mdx new file mode 100644 index 0000000000..7e49924a48 --- /dev/null +++ b/docs/shared/config/health_check.mdx @@ -0,0 +1,13 @@ +### `health_check` + +```yaml title="health_check" +health_check: + enabled: true + listen: example_listen + path: /health + readiness: + allowed: 100 + interval: + sampling: 0s + unready: null +``` diff --git a/docs/shared/config/homepage.mdx b/docs/shared/config/homepage.mdx new file mode 100644 index 0000000000..3bfe701c5a --- /dev/null +++ b/docs/shared/config/homepage.mdx @@ -0,0 +1,7 @@ +### `homepage` + +```yaml title="homepage" +homepage: + enabled: true + graph_ref: null +``` diff --git a/docs/shared/config/include_subgraph_errors.mdx b/docs/shared/config/include_subgraph_errors.mdx new file mode 100644 index 0000000000..34d3a2a2a5 --- /dev/null +++ b/docs/shared/config/include_subgraph_errors.mdx @@ -0,0 +1,7 @@ +### `include_subgraph_errors` + +```yaml title="include_subgraph_errors" +include_subgraph_errors: + all: false + subgraphs: {} +``` diff --git a/docs/shared/config/license_enforcement.mdx b/docs/shared/config/license_enforcement.mdx new file mode 100644 index 0000000000..d926504cb1 --- /dev/null +++ b/docs/shared/config/license_enforcement.mdx @@ -0,0 +1,5 @@ +### `license_enforcement` + +```yaml title="license_enforcement" +license_enforcement: {} +``` diff --git a/docs/shared/config/limits.mdx b/docs/shared/config/limits.mdx new file mode 100644 index 0000000000..b617c36d7c --- /dev/null +++ b/docs/shared/config/limits.mdx @@ -0,0 +1,16 @@ +### `limits` + +```yaml title="limits" +limits: + http1_max_request_buf_size: null + http1_max_request_headers: null + http_max_request_bytes: 2000000 + introspection_max_depth: true + max_aliases: null + max_depth: null + max_height: null + max_root_fields: null + parser_max_recursion: 500 + parser_max_tokens: 15000 + warn_only: false +``` diff --git a/docs/shared/config/override_subgraph_url.mdx b/docs/shared/config/override_subgraph_url.mdx new file mode 100644 index 0000000000..cb42d11fe9 --- /dev/null +++ b/docs/shared/config/override_subgraph_url.mdx @@ -0,0 +1,5 @@ +### `override_subgraph_url` + +```yaml title="override_subgraph_url" +override_subgraph_url: {} +``` diff --git a/docs/shared/config/persisted_queries.mdx b/docs/shared/config/persisted_queries.mdx new file mode 100644 index 0000000000..2661245424 --- /dev/null +++ b/docs/shared/config/persisted_queries.mdx @@ -0,0 +1,15 @@ +### `persisted_queries` + +```yaml title="persisted_queries" +persisted_queries: + enabled: false + experimental_prewarm_query_plan_cache: + on_reload: true + on_startup: false + hot_reload: false + local_manifests: null + log_unknown: false + safelist: + enabled: false + require_id: false +``` diff --git a/docs/shared/config/plugins.mdx b/docs/shared/config/plugins.mdx new file mode 100644 index 0000000000..39c73550c9 --- /dev/null +++ b/docs/shared/config/plugins.mdx @@ -0,0 +1,5 @@ +### `plugins` + +```yaml title="plugins" +plugins: unknown_type_plugins +``` diff --git a/docs/shared/config/preview_entity_cache.mdx b/docs/shared/config/preview_entity_cache.mdx new file mode 100644 index 0000000000..4a0ad27456 --- /dev/null +++ b/docs/shared/config/preview_entity_cache.mdx @@ -0,0 +1,45 @@ +### `preview_entity_cache` + + + +```yaml title="preview_entity_cache" +preview_entity_cache: + enabled: false + expose_keys_in_context: false + invalidation: + concurrent_requests: 10 + listen: example_listen + path: example_path + scan_count: 1000 + metrics: + enabled: false + separate_per_type: false + ttl: 30s + subgraph: + all: + enabled: true + invalidation: + enabled: false + shared_key: '' + private_id: null + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: null + urls: + - http://example.com/urls_item + username: example_username + ttl: 30s + subgraphs: {} +``` + + diff --git a/docs/shared/config/preview_file_uploads.mdx b/docs/shared/config/preview_file_uploads.mdx new file mode 100644 index 0000000000..b598822fab --- /dev/null +++ b/docs/shared/config/preview_file_uploads.mdx @@ -0,0 +1,13 @@ +### `preview_file_uploads` + +```yaml title="preview_file_uploads" +preview_file_uploads: + enabled: false + protocols: + multipart: + enabled: true + limits: + max_file_size: example_max_file_size + max_files: 0 + mode: stream +``` diff --git a/docs/shared/config/progressive_override.mdx b/docs/shared/config/progressive_override.mdx new file mode 100644 index 0000000000..5265cb86a1 --- /dev/null +++ b/docs/shared/config/progressive_override.mdx @@ -0,0 +1,5 @@ +### `progressive_override` + +```yaml title="progressive_override" +progressive_override: {} +``` diff --git a/docs/shared/config/rhai.mdx b/docs/shared/config/rhai.mdx new file mode 100644 index 0000000000..a4e44353d3 --- /dev/null +++ b/docs/shared/config/rhai.mdx @@ -0,0 +1,7 @@ +### `rhai` + +```yaml title="rhai" +rhai: + main: example_main + scripts: example_scripts +``` diff --git a/docs/shared/config/sandbox.mdx b/docs/shared/config/sandbox.mdx new file mode 100644 index 0000000000..0cf620f23d --- /dev/null +++ b/docs/shared/config/sandbox.mdx @@ -0,0 +1,6 @@ +### `sandbox` + +```yaml title="sandbox" +sandbox: + enabled: false +``` diff --git a/docs/shared/config/subscription.mdx b/docs/shared/config/subscription.mdx new file mode 100644 index 0000000000..33b1fa84ad --- /dev/null +++ b/docs/shared/config/subscription.mdx @@ -0,0 +1,22 @@ +### `subscription` + +```yaml title="subscription" +subscription: + enable_deduplication: true + enabled: true + max_opened_subscriptions: null + mode: + callback: + heartbeat_interval: disabled + listen: example_listen + path: example_path + public_url: http://service.example.com/public_url + subgraphs: [] + passthrough: + all: + heartbeat_interval: disabled + path: null + protocol: graphql_ws + subgraphs: {} + queue_capacity: null +``` diff --git a/docs/shared/config/supergraph.mdx b/docs/shared/config/supergraph.mdx new file mode 100644 index 0000000000..289f8660cc --- /dev/null +++ b/docs/shared/config/supergraph.mdx @@ -0,0 +1,42 @@ +### `supergraph` + + + +```yaml title="supergraph" +supergraph: + defer_support: true + early_cancel: false + experimental_log_on_broken_pipe: false + generate_query_fragments: true + introspection: false + listen: example_listen + path: / + query_planning: + cache: + in_memory: + limit: 1 + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: + nanos: 0 + secs: 2592000 + urls: + - http://example.com/urls_item + username: example_username + experimental_paths_limit: null + experimental_plans_limit: null + experimental_reuse_query_plans: false + warmed_up_queries: null +``` + + diff --git a/docs/shared/config/telemetry.mdx b/docs/shared/config/telemetry.mdx new file mode 100644 index 0000000000..715b3d5c66 --- /dev/null +++ b/docs/shared/config/telemetry.mdx @@ -0,0 +1,698 @@ +### `telemetry` + + + +```yaml title="telemetry" +telemetry: + apollo: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + buffer_size: 10000 + client_name_header: apollographql-client-name + client_version_header: apollographql-client-version + endpoint: https://usage-reporting.api.apollographql.com/api/ingress/traces + errors: + preview_extended_error_metrics: disabled + subgraph: + all: + redact: true + redaction_policy: strict + send: true + subgraphs: {} + experimental_local_field_metrics: false + experimental_otlp_endpoint: https://usage-reporting.api.apollographql.com/ + experimental_otlp_tracing_protocol: grpc + field_level_instrumentation_sampler: 0.0 + metrics_reference_mode: extended + otlp_tracing_sampler: 0.0 + send_headers: + only: + - example_only_item + send_variable_values: + only: + - example_only_item + signature_normalization_algorithm: legacy + exporters: + logging: + common: + resource: {} + service_name: null + service_namespace: null + stdout: + enabled: true + format: + json: + display_current_span: false + display_filename: false + display_level: true + display_line_number: false + display_resource: true + display_span_id: true + display_span_list: true + display_target: true + display_thread_id: false + display_thread_name: false + display_timestamp: true + display_trace_id: hexadecimal + span_attributes: [] + rate_limit: + capacity: 1 + enabled: false + interval: + nanos: 0 + secs: 1 + tty_format: + json: + display_current_span: false + display_filename: false + display_level: true + display_line_number: false + display_resource: true + display_span_id: true + display_span_list: true + display_target: true + display_thread_id: false + display_thread_name: false + display_timestamp: true + display_trace_id: hexadecimal + span_attributes: [] + metrics: + common: + buckets: + - 0.001 + - 0.005 + - 0.015 + - 0.05 + - 0.1 + - 0.2 + - 0.3 + - 0.4 + - 0.5 + - 1.0 + - 5.0 + - 10.0 + resource: {} + service_name: null + service_namespace: null + views: + - aggregation: + histogram: + buckets: + - 0.0 + allowed_attribute_keys: + - example_allowed_attribute_keys_item + description: example_description + name: example_name + unit: example_unit + otlp: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enabled: false + endpoint: example_endpoint + grpc: + ca: null + cert: null + domain_name: null + key: null + metadata: {} + http: + headers: {} + protocol: grpc + temporality: cumulative + prometheus: + enabled: false + listen: example_listen + path: /metrics + tracing: + common: + max_attributes_per_event: 128 + max_attributes_per_link: 128 + max_attributes_per_span: 128 + max_events_per_span: 128 + max_links_per_span: 128 + parent_based_sampler: true + preview_datadog_agent_sampling: null + resource: {} + sampler: 0.0 + service_name: null + service_namespace: null + datadog: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enable_span_mapping: true + enabled: false + endpoint: example_endpoint + fixed_span_names: true + resource_mapping: {} + span_metrics: + connect: true + connect_request: true + execution: true + http_request: true + parse_query: true + query_planning: true + request: true + router: true + subgraph: true + subgraph_request: true + supergraph: true + experimental_response_trace_id: + enabled: false + format: hexadecimal + header_name: example_header_name + otlp: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enabled: false + endpoint: example_endpoint + grpc: + ca: null + cert: null + domain_name: null + key: null + metadata: {} + http: + headers: {} + protocol: grpc + temporality: cumulative + propagation: + aws_xray: false + baggage: false + datadog: false + jaeger: false + request: + format: hexadecimal + header_name: example_header_name + trace_context: false + zipkin: false + zipkin: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enabled: false + endpoint: example_endpoint + instrumentation: + events: + connector: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + router: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + subgraph: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + supergraph: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + instruments: + cache: + apollo.router.operations.entity.cache: + attributes: + graphql.type.name: + alias: example_alias + connector: + http.client.request.body.size: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.request.duration: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.response.body.size: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + default_requirement_level: none + graphql: + field.execution: + attributes: + graphql.field.name: + alias: example_alias + graphql.field.type: + alias: example_alias + graphql.list.length: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.type.name: + alias: example_alias + list.length: + attributes: + graphql.field.name: + alias: example_alias + graphql.field.type: + alias: example_alias + graphql.list.length: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.type.name: + alias: example_alias + router: + http.server.active_requests: + attributes: + http.request.method: false + server.address: false + server.port: false + url.scheme: false + http.server.request.body.size: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + http.server.request.duration: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + http.server.response.body.size: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + subgraph: + http.client.request.body.size: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.request.duration: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.response.body.size: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + supergraph: + cost.actual: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + cost.delta: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + cost.estimated: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + spans: + connector: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + default_attribute_requirement_level: none + mode: deprecated + router: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + subgraph: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + supergraph: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias +``` + + diff --git a/docs/shared/config/tls.mdx b/docs/shared/config/tls.mdx new file mode 100644 index 0000000000..562517fd75 --- /dev/null +++ b/docs/shared/config/tls.mdx @@ -0,0 +1,23 @@ +### `tls` + +```yaml title="tls" +tls: + connector: + all: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + sources: {} + subgraph: + all: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + subgraphs: {} + supergraph: + certificate: example_certificate + certificate_chain: example_certificate_chain + key: example_key +``` diff --git a/docs/shared/config/traffic_shaping.mdx b/docs/shared/config/traffic_shaping.mdx new file mode 100644 index 0000000000..202aba9661 --- /dev/null +++ b/docs/shared/config/traffic_shaping.mdx @@ -0,0 +1,32 @@ +### `traffic_shaping` + +```yaml title="traffic_shaping" +traffic_shaping: + all: + compression: gzip + deduplicate_query: false + dns_resolution_strategy: ipv4_only + experimental_http2: enable + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + connector: + all: + compression: gzip + dns_resolution_strategy: ipv4_only + experimental_http2: enable + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + sources: {} + deduplicate_variables: null + router: + concurrency_limit: 0 + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + subgraphs: {} +``` diff --git a/docs/shared/router-config-properties-table.mdx b/docs/shared/router-config-properties-table.mdx new file mode 100644 index 0000000000..784305e315 --- /dev/null +++ b/docs/shared/router-config-properties-table.mdx @@ -0,0 +1,1469 @@ +### `apq` + +Automatic Persisted Queries (APQ) configuration + +- **Type:** `object` + +```yaml title="apq" +apq: + enabled: true + router: + cache: + in_memory: + limit: 1 + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: null + urls: + - http://example.com/urls_item + username: example_username + subgraph: + all: + enabled: false + subgraphs: {} +``` + + +--- + +### `authentication` + +Authentication + +- **Type:** `object` + +```yaml title="authentication" +authentication: + connector: + sources: {} + router: + jwt: + header_name: authorization + header_value_prefix: Bearer + ignore_other_prefixes: false + jwks: + - algorithms: null + headers: + - name: example_name + value: example_value + issuer: example_issuer + poll_interval: + nanos: 0 + secs: 60 + url: http://service.example.com/url + on_error: Continue + sources: + - name: authorization + type: header + value_prefix: Bearer + subgraph: + all: + aws_sig_v4: + hardcoded: + access_key_id: example_access_key_id + assume_role: + external_id: example_external_id + role_arn: example_role_arn + session_name: example_session_name + region: example_region + secret_access_key: example_secret_access_key + service_name: example_service_name + subgraphs: {} +``` + + +--- + +### `authorization` + +Authorization plugin + +- **Type:** `object` + +```yaml title="authorization" +authorization: + directives: + dry_run: false + enabled: true + errors: + log: true + response: errors + reject_unauthorized: false + require_authentication: false +``` + + +--- + +### `batching` + +Configuration for Batching + +- **Type:** `object` + +```yaml title="batching" +batching: + enabled: false + maximum_size: null + mode: batch_http_link + subgraph: + all: + enabled: false + subgraphs: {} +``` + + +--- + +### `connectors` + +- **Type:** `object` + +```yaml title="connectors" +connectors: + debug_extensions: false + expose_sources_in_context: false + max_requests_per_operation_per_source: null + sources: {} + subgraphs: {} +``` + + +--- + +### `coprocessor` + +Configures the externalization plugin + +- **Type:** `object` + +```yaml title="coprocessor" +coprocessor: + client: + dns_resolution_strategy: ipv4_only + experimental_http2: enable + execution: + request: + body: false + context: false + headers: false + method: false + query_plan: false + sdl: false + response: + body: false + context: false + headers: false + sdl: false + status_code: false + router: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + path: false + sdl: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + sdl: false + status_code: false + subgraph: + all: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + service_name: false + subgraph_request_id: false + uri: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + service_name: false + status_code: false + subgraph_request_id: false + supergraph: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + sdl: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + sdl: false + status_code: false + timeout: + nanos: 0 + secs: 1 + url: http://service.example.com/url +``` + + +--- + +### `cors` + +Cross origin request configuration. + +- **Type:** `object` + +```yaml title="cors" +cors: + allow_any_origin: false + allow_credentials: false + allow_headers: [] + expose_headers: null + match_origins: null + max_age: null + methods: + - GET + - POST + - OPTIONS + origins: + - https://studio.apollographql.com +``` + + +--- + +### `csrf` + +CSRF protection configuration. + +See https://owasp.org/www-community/attacks/csrf for an explanation on CSRF attacks. + +- **Type:** `object` + +```yaml title="csrf" +csrf: + required_headers: + - x-apollo-operation-name + - apollo-require-preflight + unsafe_disabled: false +``` + + +--- + +### `demand_control` + +Demand control configuration + +- **Type:** `object` + +```yaml title="demand_control" +demand_control: + enabled: false + mode: measure + strategy: + static_estimated: + list_size: 0 + max: 0.0 +``` + + +--- + +### `experimental_chaos` + +Configuration for chaos testing, trying to reproduce bugs that require uncommon conditions. You probably don’t want this in production! + +- **Type:** `object` + +```yaml title="experimental_chaos" +experimental_chaos: + force_reload: null +``` + + +--- + +### `experimental_type_conditioned_fetching` + +Type conditioned fetching configuration. + +- **Type:** `boolean` +- **Default:** `False` + +```yaml title="experimental_type_conditioned_fetching" +experimental_type_conditioned_fetching: false +``` + + +--- + +### `fleet_detector` + +- **Type:** `object` + +```yaml title="fleet_detector" +fleet_detector: {} +``` + + +--- + +### `forbid_mutations` + +Forbid mutations configuration + +- **Type:** `boolean` + +```yaml title="forbid_mutations" +forbid_mutations: false +``` + + +--- + +### `headers` + +Configuration for header propagation + +- **Type:** `object` + +```yaml title="headers" +headers: + all: + request: + - insert: + name: example_name + value: example_value + subgraphs: {} +``` + + +--- + +### `health_check` + +Configuration options pertaining to the health component. + +- **Type:** `object` + +```yaml title="health_check" +health_check: + enabled: true + listen: example_listen + path: /health + readiness: + allowed: 100 + interval: + sampling: 0s + unready: null +``` + + +--- + +### `homepage` + +Configuration options pertaining to the home page. + +- **Type:** `object` + +```yaml title="homepage" +homepage: + enabled: true + graph_ref: null +``` + + +--- + +### `include_subgraph_errors` + +Configuration for exposing errors that originate from subgraphs + +- **Type:** `object` + +```yaml title="include_subgraph_errors" +include_subgraph_errors: + all: false + subgraphs: {} +``` + + +--- + +### `license_enforcement` + +- **Type:** `object` + +```yaml title="license_enforcement" +license_enforcement: {} +``` + + +--- + +### `limits` + +Configuration for operation limits, parser limits, HTTP limits, etc. + +- **Type:** `object` + +```yaml title="limits" +limits: + http1_max_request_buf_size: null + http1_max_request_headers: null + http_max_request_bytes: 2000000 + introspection_max_depth: true + max_aliases: null + max_depth: null + max_height: null + max_root_fields: null + parser_max_recursion: 500 + parser_max_tokens: 15000 + warn_only: false +``` + + +--- + +### `override_subgraph_url` + +Subgraph URL mappings + +- **Type:** `any` + +```yaml title="override_subgraph_url" +override_subgraph_url: {} +``` + + +--- + +### `persisted_queries` + +Persisted Queries (PQ) configuration + +- **Type:** `object` + +```yaml title="persisted_queries" +persisted_queries: + enabled: false + experimental_prewarm_query_plan_cache: + on_reload: true + on_startup: false + hot_reload: false + local_manifests: null + log_unknown: false + safelist: + enabled: false + require_id: false +``` + + +--- + +### `plugins` + +- **Type:** `any` + +```yaml title="plugins" +plugins: unknown_type_plugins +``` + + +--- + +### `preview_entity_cache` + +Configuration for entity caching + +- **Type:** `object` + +```yaml title="preview_entity_cache" +preview_entity_cache: + enabled: false + expose_keys_in_context: false + invalidation: + concurrent_requests: 10 + listen: example_listen + path: example_path + scan_count: 1000 + metrics: + enabled: false + separate_per_type: false + ttl: 30s + subgraph: + all: + enabled: true + invalidation: + enabled: false + shared_key: '' + private_id: null + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: null + urls: + - http://example.com/urls_item + username: example_username + ttl: 30s + subgraphs: {} +``` + + +--- + +### `preview_file_uploads` + +Configuration for File Uploads plugin + +- **Type:** `object` + +```yaml title="preview_file_uploads" +preview_file_uploads: + enabled: false + protocols: + multipart: + enabled: true + limits: + max_file_size: example_max_file_size + max_files: 0 + mode: stream +``` + + +--- + +### `progressive_override` + +Configuration for the progressive override plugin + +- **Type:** `object` + +```yaml title="progressive_override" +progressive_override: {} +``` + + +--- + +### `rhai` + +Configuration for the Rhai Plugin + +- **Type:** `object` + +```yaml title="rhai" +rhai: + main: example_main + scripts: example_scripts +``` + + +--- + +### `sandbox` + +Configuration options pertaining to the sandbox page. + +- **Type:** `object` + +```yaml title="sandbox" +sandbox: + enabled: false +``` + + +--- + +### `subscription` + +Subscriptions configuration + +- **Type:** `object` + +```yaml title="subscription" +subscription: + enable_deduplication: true + enabled: true + max_opened_subscriptions: null + mode: + callback: + heartbeat_interval: disabled + listen: example_listen + path: example_path + public_url: http://service.example.com/public_url + subgraphs: [] + passthrough: + all: + heartbeat_interval: disabled + path: null + protocol: graphql_ws + subgraphs: {} + queue_capacity: null +``` + + +--- + +### `supergraph` + +Configuration options pertaining to the supergraph server component. + +- **Type:** `object` + +```yaml title="supergraph" +supergraph: + defer_support: true + early_cancel: false + experimental_log_on_broken_pipe: false + generate_query_fragments: true + introspection: false + listen: example_listen + path: / + query_planning: + cache: + in_memory: + limit: 1 + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: + nanos: 0 + secs: 2592000 + urls: + - http://example.com/urls_item + username: example_username + experimental_paths_limit: null + experimental_plans_limit: null + experimental_reuse_query_plans: false + warmed_up_queries: null +``` + + +--- + +### `telemetry` + +Telemetry configuration + +- **Type:** `object` + +```yaml title="telemetry" +telemetry: + apollo: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + buffer_size: 10000 + client_name_header: apollographql-client-name + client_version_header: apollographql-client-version + endpoint: https://usage-reporting.api.apollographql.com/api/ingress/traces + errors: + preview_extended_error_metrics: disabled + subgraph: + all: + redact: true + redaction_policy: strict + send: true + subgraphs: {} + experimental_local_field_metrics: false + experimental_otlp_endpoint: https://usage-reporting.api.apollographql.com/ + experimental_otlp_tracing_protocol: grpc + field_level_instrumentation_sampler: 0.0 + metrics_reference_mode: extended + otlp_tracing_sampler: 0.0 + send_headers: + only: + - example_only_item + send_variable_values: + only: + - example_only_item + signature_normalization_algorithm: legacy + exporters: + logging: + common: + resource: {} + service_name: null + service_namespace: null + stdout: + enabled: true + format: + json: + display_current_span: false + display_filename: false + display_level: true + display_line_number: false + display_resource: true + display_span_id: true + display_span_list: true + display_target: true + display_thread_id: false + display_thread_name: false + display_timestamp: true + display_trace_id: hexadecimal + span_attributes: [] + rate_limit: + capacity: 1 + enabled: false + interval: + nanos: 0 + secs: 1 + tty_format: + json: + display_current_span: false + display_filename: false + display_level: true + display_line_number: false + display_resource: true + display_span_id: true + display_span_list: true + display_target: true + display_thread_id: false + display_thread_name: false + display_timestamp: true + display_trace_id: hexadecimal + span_attributes: [] + metrics: + common: + buckets: + - 0.001 + - 0.005 + - 0.015 + - 0.05 + - 0.1 + - 0.2 + - 0.3 + - 0.4 + - 0.5 + - 1.0 + - 5.0 + - 10.0 + resource: {} + service_name: null + service_namespace: null + views: + - aggregation: + histogram: + buckets: + - 0.0 + allowed_attribute_keys: + - example_allowed_attribute_keys_item + description: example_description + name: example_name + unit: example_unit + otlp: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enabled: false + endpoint: example_endpoint + grpc: + ca: null + cert: null + domain_name: null + key: null + metadata: {} + http: + headers: {} + protocol: grpc + temporality: cumulative + prometheus: + enabled: false + listen: example_listen + path: /metrics + tracing: + common: + max_attributes_per_event: 128 + max_attributes_per_link: 128 + max_attributes_per_span: 128 + max_events_per_span: 128 + max_links_per_span: 128 + parent_based_sampler: true + preview_datadog_agent_sampling: null + resource: {} + sampler: 0.0 + service_name: null + service_namespace: null + datadog: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enable_span_mapping: true + enabled: false + endpoint: example_endpoint + fixed_span_names: true + resource_mapping: {} + span_metrics: + connect: true + connect_request: true + execution: true + http_request: true + parse_query: true + query_planning: true + request: true + router: true + subgraph: true + subgraph_request: true + supergraph: true + experimental_response_trace_id: + enabled: false + format: hexadecimal + header_name: example_header_name + otlp: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enabled: false + endpoint: example_endpoint + grpc: + ca: null + cert: null + domain_name: null + key: null + metadata: {} + http: + headers: {} + protocol: grpc + temporality: cumulative + propagation: + aws_xray: false + baggage: false + datadog: false + jaeger: false + request: + format: hexadecimal + header_name: example_header_name + trace_context: false + zipkin: false + zipkin: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + nanos: 0 + secs: 30 + max_queue_size: 2048 + scheduled_delay: + nanos: 0 + secs: 5 + enabled: false + endpoint: example_endpoint + instrumentation: + events: + connector: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + router: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + subgraph: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + supergraph: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + instruments: + cache: + apollo.router.operations.entity.cache: + attributes: + graphql.type.name: + alias: example_alias + connector: + http.client.request.body.size: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.request.duration: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.response.body.size: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + default_requirement_level: none + graphql: + field.execution: + attributes: + graphql.field.name: + alias: example_alias + graphql.field.type: + alias: example_alias + graphql.list.length: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.type.name: + alias: example_alias + list.length: + attributes: + graphql.field.name: + alias: example_alias + graphql.field.type: + alias: example_alias + graphql.list.length: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.type.name: + alias: example_alias + router: + http.server.active_requests: + attributes: + http.request.method: false + server.address: false + server.port: false + url.scheme: false + http.server.request.body.size: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + http.server.request.duration: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + http.server.response.body.size: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + subgraph: + http.client.request.body.size: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.request.duration: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.response.body.size: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + supergraph: + cost.actual: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + cost.delta: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + cost.estimated: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + spans: + connector: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + default_attribute_requirement_level: none + mode: deprecated + router: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + subgraph: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + supergraph: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias +``` + + +--- + +### `tls` + +TLS related configuration options. + +- **Type:** `object` + +```yaml title="tls" +tls: + connector: + all: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + sources: {} + subgraph: + all: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + subgraphs: {} + supergraph: + certificate: example_certificate + certificate_chain: example_certificate_chain + key: example_key +``` + + +--- + +### `traffic_shaping` + +Configuration for the experimental traffic shaping plugin + +- **Type:** `object` + +```yaml title="traffic_shaping" +traffic_shaping: + all: + compression: gzip + deduplicate_query: false + dns_resolution_strategy: ipv4_only + experimental_http2: enable + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + connector: + all: + compression: gzip + dns_resolution_strategy: ipv4_only + experimental_http2: enable + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + sources: {} + deduplicate_variables: null + router: + concurrency_limit: 0 + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + subgraphs: {} +``` diff --git a/docs/shared/router-yaml-complete.mdx b/docs/shared/router-yaml-complete.mdx new file mode 100644 index 0000000000..95e42e1376 --- /dev/null +++ b/docs/shared/router-yaml-complete.mdx @@ -0,0 +1,1096 @@ +```yaml +apq: + enabled: true + router: + cache: + in_memory: + limit: 1 + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: null + urls: + - http://example.com/urls_item + username: example_username + subgraph: + all: + enabled: false + subgraphs: {} +authentication: + connector: + sources: {} + router: + jwt: + header_name: authorization + header_value_prefix: Bearer + ignore_other_prefixes: false + jwks: + - algorithms: null + headers: + - name: example_name + value: example_value + issuer: example_issuer + poll_interval: + secs: 60 + nanos: 0 + url: http://service.example.com/url + on_error: Continue + sources: + - name: authorization + type: header + value_prefix: Bearer + subgraph: + all: + aws_sig_v4: + hardcoded: + access_key_id: example_access_key_id + assume_role: + external_id: example_external_id + role_arn: example_role_arn + session_name: example_session_name + region: example_region + secret_access_key: example_secret_access_key + service_name: example_service_name + subgraphs: {} +authorization: + directives: + dry_run: false + enabled: true + errors: + log: true + response: errors + reject_unauthorized: false + require_authentication: false +batching: + enabled: false + maximum_size: null + mode: batch_http_link + subgraph: + all: + enabled: false + subgraphs: {} +connectors: + debug_extensions: false + expose_sources_in_context: false + max_requests_per_operation_per_source: null + sources: {} + subgraphs: {} +coprocessor: + client: + dns_resolution_strategy: ipv4_only + experimental_http2: enable + execution: + request: + body: false + context: false + headers: false + method: false + query_plan: false + sdl: false + response: + body: false + context: false + headers: false + sdl: false + status_code: false + router: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + path: false + sdl: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + sdl: false + status_code: false + subgraph: + all: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + service_name: false + subgraph_request_id: false + uri: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + service_name: false + status_code: false + subgraph_request_id: false + supergraph: + request: + body: false + condition: + eq: + - false + - false + context: false + headers: false + method: false + sdl: false + response: + body: false + condition: + eq: + - false + - false + context: false + headers: false + sdl: false + status_code: false + timeout: + secs: 1 + nanos: 0 + url: http://service.example.com/url +cors: + allow_any_origin: false + allow_credentials: false + allow_headers: [] + expose_headers: null + match_origins: null + max_age: null + methods: + - GET + - POST + - OPTIONS + origins: + - https://studio.apollographql.com +csrf: + required_headers: + - x-apollo-operation-name + - apollo-require-preflight + unsafe_disabled: false +demand_control: + enabled: false + mode: measure + strategy: + static_estimated: + list_size: 0 + max: 0.0 +experimental_chaos: + force_reload: null +experimental_type_conditioned_fetching: false +fleet_detector: {} +forbid_mutations: false +headers: + all: + request: + - insert: + name: example_name + value: example_value + subgraphs: {} +health_check: + enabled: true + listen: example_listen + path: /health + readiness: + allowed: 100 + interval: + sampling: 0s + unready: null +homepage: + enabled: true + graph_ref: null +include_subgraph_errors: + all: false + subgraphs: {} +license_enforcement: {} +limits: + http1_max_request_buf_size: null + http1_max_request_headers: null + http_max_request_bytes: 2000000 + introspection_max_depth: true + max_aliases: null + max_depth: null + max_height: null + max_root_fields: null + parser_max_recursion: 500 + parser_max_tokens: 15000 + warn_only: false +override_subgraph_url: {} +persisted_queries: + enabled: false + experimental_prewarm_query_plan_cache: + on_reload: true + on_startup: false + hot_reload: false + local_manifests: null + log_unknown: false + safelist: + enabled: false + require_id: false +plugins: unknown_type_plugins +preview_entity_cache: + enabled: false + expose_keys_in_context: false + invalidation: + concurrent_requests: 10 + listen: example_listen + path: example_path + scan_count: 1000 + metrics: + enabled: false + separate_per_type: false + ttl: 30s + subgraph: + all: + enabled: true + invalidation: + enabled: false + shared_key: "" + private_id: null + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: null + urls: + - http://example.com/urls_item + username: example_username + ttl: 30s + subgraphs: {} +preview_file_uploads: + enabled: false + protocols: + multipart: + enabled: true + limits: + max_file_size: example_max_file_size + max_files: 0 + mode: stream +progressive_override: {} +rhai: + main: example_main + scripts: example_scripts +sandbox: + enabled: false +subscription: + enable_deduplication: true + enabled: true + max_opened_subscriptions: null + mode: + callback: + heartbeat_interval: disabled + listen: example_listen + path: example_path + public_url: http://service.example.com/public_url + subgraphs: [] + passthrough: + all: + heartbeat_interval: disabled + path: null + protocol: graphql_ws + subgraphs: {} + queue_capacity: null +supergraph: + defer_support: true + early_cancel: false + experimental_log_on_broken_pipe: false + generate_query_fragments: true + introspection: false + listen: example_listen + path: / + query_planning: + cache: + in_memory: + limit: 1 + redis: + namespace: example_namespace + password: example_password + pool_size: 1 + required_to_start: false + reset_ttl: true + timeout: null + tls: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + ttl: + secs: 2592000 + nanos: 0 + urls: + - http://example.com/urls_item + username: example_username + experimental_paths_limit: null + experimental_plans_limit: null + experimental_reuse_query_plans: false + warmed_up_queries: null +telemetry: + apollo: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + secs: 30 + nanos: 0 + max_queue_size: 2048 + scheduled_delay: + secs: 5 + nanos: 0 + buffer_size: 10000 + client_name_header: apollographql-client-name + client_version_header: apollographql-client-version + endpoint: https://usage-reporting.api.apollographql.com/api/ingress/traces + errors: + preview_extended_error_metrics: disabled + subgraph: + all: + redact: true + redaction_policy: strict + send: true + subgraphs: {} + experimental_local_field_metrics: false + experimental_otlp_endpoint: https://usage-reporting.api.apollographql.com/ + experimental_otlp_tracing_protocol: grpc + field_level_instrumentation_sampler: 0.0 + metrics_reference_mode: extended + otlp_tracing_sampler: 0.0 + send_headers: + only: + - example_only_item + send_variable_values: + only: + - example_only_item + signature_normalization_algorithm: legacy + exporters: + logging: + common: + resource: {} + service_name: null + service_namespace: null + stdout: + enabled: true + format: + json: + display_current_span: false + display_filename: false + display_level: true + display_line_number: false + display_resource: true + display_span_id: true + display_span_list: true + display_target: true + display_thread_id: false + display_thread_name: false + display_timestamp: true + display_trace_id: hexadecimal + span_attributes: [] + rate_limit: + capacity: 1 + enabled: false + interval: + secs: 1 + nanos: 0 + tty_format: + json: + display_current_span: false + display_filename: false + display_level: true + display_line_number: false + display_resource: true + display_span_id: true + display_span_list: true + display_target: true + display_thread_id: false + display_thread_name: false + display_timestamp: true + display_trace_id: hexadecimal + span_attributes: [] + metrics: + common: + buckets: + - 0.001 + - 0.005 + - 0.015 + - 0.05 + - 0.1 + - 0.2 + - 0.3 + - 0.4 + - 0.5 + - 1.0 + - 5.0 + - 10.0 + resource: {} + service_name: null + service_namespace: null + views: + - aggregation: + histogram: + buckets: + - 0.0 + allowed_attribute_keys: + - example_allowed_attribute_keys_item + description: example_description + name: example_name + unit: example_unit + otlp: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + secs: 30 + nanos: 0 + max_queue_size: 2048 + scheduled_delay: + secs: 5 + nanos: 0 + enabled: false + endpoint: example_endpoint + grpc: + ca: null + cert: null + domain_name: null + key: null + metadata: {} + http: + headers: {} + protocol: grpc + temporality: cumulative + prometheus: + enabled: false + listen: example_listen + path: /metrics + tracing: + common: + max_attributes_per_event: 128 + max_attributes_per_link: 128 + max_attributes_per_span: 128 + max_events_per_span: 128 + max_links_per_span: 128 + parent_based_sampler: true + preview_datadog_agent_sampling: null + resource: {} + sampler: 0.0 + service_name: null + service_namespace: null + datadog: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + secs: 30 + nanos: 0 + max_queue_size: 2048 + scheduled_delay: + secs: 5 + nanos: 0 + enable_span_mapping: true + enabled: false + endpoint: example_endpoint + fixed_span_names: true + resource_mapping: {} + span_metrics: + parse_query: true + connect: true + execution: true + http_request: true + request: true + query_planning: true + connect_request: true + subgraph: true + router: true + supergraph: true + subgraph_request: true + experimental_response_trace_id: + enabled: false + format: hexadecimal + header_name: example_header_name + otlp: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + secs: 30 + nanos: 0 + max_queue_size: 2048 + scheduled_delay: + secs: 5 + nanos: 0 + enabled: false + endpoint: example_endpoint + grpc: + ca: null + cert: null + domain_name: null + key: null + metadata: {} + http: + headers: {} + protocol: grpc + temporality: cumulative + propagation: + aws_xray: false + baggage: false + datadog: false + jaeger: false + request: + format: hexadecimal + header_name: example_header_name + trace_context: false + zipkin: false + zipkin: + batch_processor: + max_concurrent_exports: 1 + max_export_batch_size: 512 + max_export_timeout: + secs: 30 + nanos: 0 + max_queue_size: 2048 + scheduled_delay: + secs: 5 + nanos: 0 + enabled: false + endpoint: example_endpoint + instrumentation: + events: + connector: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + router: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + subgraph: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + supergraph: + error: + condition: + eq: + - false + - false + level: info + request: + condition: + eq: + - false + - false + level: info + response: + condition: + eq: + - false + - false + level: info + instruments: + cache: + apollo.router.operations.entity.cache: + attributes: + graphql.type.name: + alias: example_alias + connector: + http.client.request.body.size: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.request.duration: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.response.body.size: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + default_requirement_level: none + graphql: + field.execution: + attributes: + graphql.field.name: + alias: example_alias + graphql.field.type: + alias: example_alias + graphql.list.length: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.type.name: + alias: example_alias + list.length: + attributes: + graphql.field.name: + alias: example_alias + graphql.field.type: + alias: example_alias + graphql.list.length: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.type.name: + alias: example_alias + router: + http.server.active_requests: + attributes: + http.request.method: false + server.address: false + server.port: false + url.scheme: false + http.server.request.body.size: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + http.server.request.duration: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + http.server.response.body.size: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + subgraph: + http.client.request.body.size: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.request.duration: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + http.client.response.body.size: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + supergraph: + cost.actual: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + cost.delta: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + cost.estimated: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias + spans: + connector: + attributes: + connector.http.method: + alias: example_alias + connector.source.name: + alias: example_alias + connector.url.template: + alias: example_alias + subgraph.name: + alias: example_alias + default_attribute_requirement_level: none + mode: deprecated + router: + attributes: + baggage: null + dd.trace_id: + alias: example_alias + error.type: + alias: example_alias + http.request.body.size: + alias: example_alias + http.request.method: + alias: example_alias + http.response.body.size: + alias: example_alias + http.response.status_code: + alias: example_alias + http.route: + alias: example_alias + network.local.address: + alias: example_alias + network.local.port: + alias: example_alias + network.peer.address: + alias: example_alias + network.peer.port: + alias: example_alias + network.protocol.name: + alias: example_alias + network.protocol.version: + alias: example_alias + network.transport: + alias: example_alias + network.type: + alias: example_alias + server.address: + alias: example_alias + server.port: + alias: example_alias + trace_id: + alias: example_alias + url.path: + alias: example_alias + url.query: + alias: example_alias + url.scheme: + alias: example_alias + user_agent.original: + alias: example_alias + subgraph: + attributes: + http.request.resend_count: + alias: example_alias + subgraph.graphql.document: + alias: example_alias + subgraph.graphql.operation.name: + alias: example_alias + subgraph.graphql.operation.type: + alias: example_alias + subgraph.name: + alias: example_alias + supergraph: + attributes: + cost.actual: + alias: example_alias + cost.delta: + alias: example_alias + cost.estimated: + alias: example_alias + cost.result: + alias: example_alias + graphql.document: + alias: example_alias + graphql.operation.name: + alias: example_alias + graphql.operation.type: + alias: example_alias +tls: + connector: + all: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + sources: {} + subgraph: + all: + certificate_authorities: null + client_authentication: + certificate_chain: example_certificate_chain + key: example_key + subgraphs: {} + supergraph: + certificate: example_certificate + certificate_chain: example_certificate_chain + key: example_key +traffic_shaping: + all: + compression: gzip + deduplicate_query: false + dns_resolution_strategy: ipv4_only + experimental_http2: enable + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + connector: + all: + compression: gzip + dns_resolution_strategy: ipv4_only + experimental_http2: enable + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + sources: {} + deduplicate_variables: null + router: + concurrency_limit: 0 + global_rate_limit: + capacity: 1 + interval: 30s + timeout: null + subgraphs: {} +``` \ No newline at end of file diff --git a/docs/source/config.json b/docs/source/config.json index 8e481a369b..4fd0c6569c 100644 --- a/docs/source/config.json +++ b/docs/source/config.json @@ -2,9 +2,6 @@ "title": "Self-Hosted Router", "algoliaFilters": ["docset:router"], "sidebar": { - "Routing": { - "About Router": "/routing/about-router" - }, "Reference": { "Migration": { "From Gateway": "/reference/migration/from-gateway" diff --git a/docs/source/images/router-quickstart-sandbox.jpg b/docs/source/images/router-quickstart-sandbox.jpg new file mode 100644 index 0000000000..c26adceed6 Binary files /dev/null and b/docs/source/images/router-quickstart-sandbox.jpg differ diff --git a/docs/source/routing/about-router.mdx b/docs/source/routing/about-router.mdx deleted file mode 100644 index c2365f7307..0000000000 --- a/docs/source/routing/about-router.mdx +++ /dev/null @@ -1,177 +0,0 @@ ---- -title: Supergraph Routing with GraphOS Router -subtitle: Learn the basics about router features and deployment types -description: Apollo provides cloud and self-hosted GraphOS Router options. The router acts as an entry point to your GraphQL APIs and provides a unified interface for clients to interact with. -redirectFrom: - - /graphos/routing ---- - -## What is GraphOS Router? - -GraphOS Router is the runtime of the GraphOS platform. It executes client operations by planning and executing subgraph queries, then merging them into client responses. It's also the single entry point and gateway to your federated GraphQL API. - - - - -### Runtime of GraphOS platform - -As the runtime of the [GraphOS platform](/graphos/get-started/concepts/graphos), a GraphOS Router gets the supergraph schema—the blueprint of the federated graphs—from the GraphOS control plane. It then executes incoming clients operations based on that schema. - -Unlike API gateways that offer capabilities to manage API endpoints, the router isn't based on URLs or REST endpoints. Rather, the router is a GraphQL-native solution for handling client APIs. - -### Enables Apollo Connectors - -Apollo Connectors are a core part of the router, enabling API orchestration with REST APIs. - - - - -### Subgraph query planner - -Whenever your router receives an incoming GraphQL operation, it needs to figure out how to use your subgraphs to populate data for each of that operation's fields. To do this, the router generates a _query plan_: - - - - -A query plan is a blueprint for dividing a single incoming operation into one or more operations that are each resolvable by a single subgraph. Some of these operations depend on the results of other operations, so the query plan also defines any required ordering for their execution. The router's query planner determines the optimal set of subgraph queries for each client operation, then it merges the subgraph responses into a single response for the client. - -You can use the following tools for inspecting query plans: - -- Use the [Explorer IDE](/graphos/platform/explorer/) to view dynamically calculated example query plans for your operations in its right-hand panel. -- Use the [Apollo Solutions command line utility](https://github.com/apollosolutions/generate-query-plan) for generating a query plan locally. - - - -### Entry point to federated GraphQL API - -The GraphOS Router is the gateway and entry point to a federated supergraph. Clients send GraphQL operations to your router's public endpoint instead of directly to your APIs. - - -## GraphOS Router deployment types - -As the entry point to your supergraph, a GraphOS Router must be able to process the expected load of client operations. The scalability and performance of a router, or a fleet or router instances, can be influenced by their deployment infrastructure. - -### Cloud-hosted routers - -You can choose for Apollo to provision and manage the runtime infrastructure for your routers. Apollo hosts and deploys each instance of router in the cloud. Each _cloud-hosted router_ instance is fully integrated and configurable within GraphOS. - - - - - - -While cloud routers are hosted in the cloud, GraphQL subgraph servers are still hosted in your infrastructure. - - - -### Self-hosted routers - -You can choose to manage the runtime infrastructure for your routers by yourself. Using container images of router, you can host and deploy your router instances from your own infrastructure. These _self-hosted router_ instances allow you full control over their deployment. - - - - - - -Self-hosted routers running on the [Free plan](https://www.apollographql.com/pricing) are rate limited to 60 requests per minute. - -For requests in excess of this limit, the router returns an HTTP 503 (Service Unavailable) response. - - - -### Common router core - -Both cloud-hosted and self-hosted routers are powered by the [Apollo Router Core](https://github.com/apollographql/router)—a high-performance router packaged as a standalone binary. - -### Router type comparison - -Apollo offers the following router options, in increasing order of configurability: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Router typeDescriptionConfigurabilityPlan availability
Shared cloud routerApollo provisions and manages routers on shared infrastructure. - Basic configurability, including HTTP header rules, CORS settings, and - subgraph error inclusion - - Serverless** -
Dedicated cloud router - Apollo provisions and manages routers on dedicated infrastructure that - you control and scale. - - Highly configurable, including all options for shared cloud routers and - additional configurations - - Dedicated** -
Self-hosted routerYou host and manage the router on your own infrastructure. - Highly configurable and customizable, including all options for Cloud - Dedicated routers and additional [customization - options](/graphos/routing/customization/overview). - - The Apollo Router Core is available as a free and source-available - router. Connecting your self-hosted router to GraphOS requires a{" "} - GraphOS plan. -
- - - -**We've paused new sign-ups for Serverless and Dedicated plans while -we improve our offerings based on user feedback. This means cloud routing is -temporarily unavailable to new users. In the meantime, you can explore other -GraphOS features with our [Free -plan](https://studio.apollographql.com/signup?referrer=docs-content). - - - -## GraphOS Router features - -Although powered by the source-available Apollo Router Core binary, GraphOS Routers offer an expanded feature set that isn't available when running the Apollo Router Core without connecting it to GraphOS. - -Cloud-hosted routers automatically have access to additional GraphOS Router features, while self-hosted routers must be authenticated with a GraphOS Enterprise license to gain access to these features. Refer to the [pricing page](https://www.apollographql.com/pricing#graphos-router) to compare GraphOS Router features across plan types. - -## Next steps - -- Learn more about deploying router instances in your own infrastructure in [self-hosted router](/graphos/routing/self-hosted/) - -- Learn the basics about configuring a router in [Configuring a Router](/graphos/routing/configure-your-router) - -- For all available configuration options, go to [Router configuration](/graphos/reference/router/configuration) reference docs - -- To learn more about the intricacies of query plans, see the [example graph](/graphos/reference/federation/query-plans#example-graph) and [query plan](/graphos/reference/federation/query-plans#example-graph) in reference docs - -- Learn more about Apollo-managed routers in [cloud-hosted router](/graphos/routing/cloud/) diff --git a/docs/source/routing/about-v2.mdx b/docs/source/routing/about-v2.mdx index fb7a57d36c..f16009b596 100644 --- a/docs/source/routing/about-v2.mdx +++ b/docs/source/routing/about-v2.mdx @@ -37,7 +37,7 @@ The router v2.x introduces Apollo Connectors for REST, a declarative way to inte The router is powered by a new **Native Query Planner** that achieves performance at scale with demonstrable improvement in CPU and memory utilization. It's written in Rust and replaces the legacy query planner written in JavaScript, thereby utilizing a simplified architecture and ensuring more efficient and performant query execution. -> Learn more about the [native query planner](graphos/routing/query-planning/native-query-planner). +> Learn more about the [native query planner](/graphos/routing/query-planning/native-query-planner). ### Predictable resource utilization and availability with back-pressure management diff --git a/docs/source/routing/changelog.mdx b/docs/source/routing/changelog.mdx new file mode 100644 index 0000000000..29fb4991f7 --- /dev/null +++ b/docs/source/routing/changelog.mdx @@ -0,0 +1,16 @@ +--- +title: Apollo Router Changelogs +subtitle: "" +description: Changelog of latest Apollo Router release +--- + +This page contains the changelog for the latest release of Apollo Router. + +> Go to [GitHub](https://github.com/apollographql/router/releases) to view changelogs for all router releases. + + + +## {release.version} + + + diff --git a/docs/source/routing/configuration.mdx b/docs/source/routing/configuration.mdx deleted file mode 100644 index 62f5cdf49f..0000000000 --- a/docs/source/routing/configuration.mdx +++ /dev/null @@ -1,1311 +0,0 @@ ---- -title: Router Configuration -subtitle: Configure a router via environment variables, command-line options, and YAML -description: Learn how to configure the Apollo GraphOS Router or Apollo Router Core with environment variables, command-line options and commands, and YAML configuration files. -redirectFrom: - - /router/configuration/overview/ ---- - -Learn how to customize the behavior of your GraphOS Router or Apollo Router Core with environment variables, command-line commands and options, and YAML file configuration. - -## Self-hosted and cloud configuration differences - -You can configure a router in multiple ways. Because cloud-hosted and self-hosted routers share the common foundation of Apollo Router Core, all routers support declarative configuration with a YAML file, usually named `router.yaml`. Differences between configuring cloud-hosted and self-hosted routers: - -- A cloud-hosted router is managed by Apollo and fully integrated with GraphOS, so its configuration is provided via the GraphOS Studio IDE. -- A self-hosted router is launched via command line, so its configuration includes command-line options and environment variables. - -| | Cloud-Hosted Router | Self-Hosted Router | -| --- | :---: | :---: | -| Studio IDE | ✅ | ❌ | -| YAML file | ✅ | ✅ | -| Command-line options | ❌ | ✅ | -| Environment variables | ❌ | ✅ | - -## Environment variables - -If you're using the GraphOS Router with [managed federation](/federation/managed-federation/overview/) and GraphOS Studio, set these environment variables in the startup command: - -```bash -APOLLO_KEY="..." APOLLO_GRAPH_REF="..." ./router -``` - - - - - - - - - - - - - - - - - - - - - - - - - -
Environment VariableDescription
- -##### `APOLLO_GRAPH_REF` - - - -The graph ref for the GraphOS graph and variant that the router fetches its supergraph schema from (e.g., `docs-example-graph@staging`). - -**Required** when using [managed federation](/federation/managed-federation/overview/), except when using an [offline license](#--license) to run the router. - -
- -##### `APOLLO_KEY` - - - -The [graph API key](/graphos/api-keys/#graph-api-keys) that the router should use to authenticate with GraphOS when fetching its supergraph schema. - -**Required** when using [managed federation](/federation/managed-federation/overview/), except when using an [offline license](#--license) to run the router or when using `APOLLO_KEY_PATH`. - -
- -##### `APOLLO_KEY_PATH` - - - -⚠️ **This is not available on Windows.** - -A path to a file containing the [graph API key](/graphos/api-keys/#graph-api-keys) that the router should use to authenticate with GraphOS when fetching its supergraph schema. - -**Required** when using [managed federation](/federation/managed-federation/overview/), except when using an [offline license](#--license) to run the router or when using `APOLLO_KEY`. - -
- -## Command-line options - -After [installing the Apollo Router Core](/router/quickstart) in your current working directory, you can run the router with the following example command: - -```bash -./router --config router.yaml --supergraph supergraph-schema.graphql -``` - -This reference lists and describes the options supported by the `router` binary. Where indicated, some of these options can also be provided via an environment variable. If an option is provided _both_ ways, the command-line value takes precedence. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Option / Environment VariableDescription
- -##### `-s` / `--supergraph` - -`APOLLO_ROUTER_SUPERGRAPH_PATH`, `APOLLO_ROUTER_SUPERGRAPH_URLS` - - - -The [supergraph schema](/federation/federated-types/overview#supergraph-schema) of a router. Specified by absolute or relative path (`-s` / `--supergraph `, or `APOLLO_ROUTER_SUPERGRAPH_PATH`), or a comma-separated list of URLs (`--supergraph-urls `, or `APOLLO_ROUTER_SUPERGRAPH_URLS`). - -> 💡 Avoid embedding tokens in `APOLLO_ROUTER_SUPERGRAPH_URLS` because the URLs may appear in log messages. - -Setting this option disables polling from Apollo Uplink to fetch the latest supergraph schema. - -To learn how to compose your supergraph schema with the Rover CLI, see the [Federation quickstart](/federation/quickstart). - -**Required** if you are _not_ using managed federation. If you _are_ using managed federation, you may need to set this option when following [advanced deployment workflows](/federation/managed-federation/deployment/#advanced-deployment-workflows). - -
- -##### `-c` / `--config` - -`APOLLO_ROUTER_CONFIG_PATH` - - - -The absolute or relative path to the router's optional [YAML configuration file](#yaml-config-file). - -
- -##### `--apollo-key-path` - -`APOLLO_KEY_PATH` - - - -⚠️ **This is not available on Windows.** - -The absolute or relative path to a file containing the Apollo graph API key for use with managed federation. - -
- -##### `--dev` - - - -⚠️ **Do not set this option in production!** - -If set, a router runs in dev mode to help with local development. - -[Learn more about dev mode.](#dev-mode-defaults) - -
- -##### `--hr` / `--hot-reload` - -`APOLLO_ROUTER_HOT_RELOAD` - - - -If set, the router watches for changes to its configuration file and any supergraph file passed with `--supergraph` and reloads them automatically without downtime. This setting only affects local files provided to the router. The supergraph and configuration provided from GraphOS via Launches (and delivered via Uplink) are _always_ loaded automatically, regardless of this setting. - -
- -##### `--log` - -`APOLLO_ROUTER_LOG` - - - -The log level, indicating the _most_ severe log message type to include. In ascending order of verbosity, can be one of: `off`, `error`, `warn`, `info`, `debug`, or `trace`. - -The default value is `info`. - -
- -##### `--license` - -`APOLLO_ROUTER_LICENSE_PATH`, `APOLLO_ROUTER_LICENSE` - - - -An offline GraphOS Enterprise license. Enables Enterprise router features when disconnected from GraphOS. - -An offline license is specified either as an absolute or relative path to a license file (`--license ` or `APOLLO_ROUTER_LICENSE_PATH`), or as the stringified contents of a license (`APOLLO_ROUTER_LICENSE`). - -When not set, the router retrieves an Enterprise license [from GraphOS via Apollo Uplink](/router/enterprise-features/#the-enterprise-license). - -For information about fetching an offline license and configuring the router, see [Offline Enterprise license](/router/enterprise-features/#offline-enterprise-license). - -
- -##### `--apollo-uplink-endpoints` - -`APOLLO_UPLINK_ENDPOINTS` - - - -If using [managed federation](/federation/managed-federation/overview/), the Apollo Uplink URL(s) that the router should poll to fetch its latest configuration. Almost all managed router instances should _omit_ this option to use the default set of Uplink URLs. - -If you specify multiple URLs, separate them with commas (no whitespace). - -For default behavior and possible values, see [Apollo Uplink](/federation/managed-federation/uplink/). - -
- -##### `--apollo-uplink-timeout` - -`APOLLO_UPLINK_TIMEOUT` - - - -The request timeout for each poll sent to Apollo Uplink. - -The default value is `30s` (thirty seconds). - -
- -##### `--anonymous-telemetry-disabled` - -`APOLLO_TELEMETRY_DISABLED` - - - -If set, disables sending anonymous usage information to Apollo. - -
- -##### `--listen` - -`APOLLO_ROUTER_LISTEN_ADDRESS` - - - -If set, the listen address of the router. - -
- -##### `-V` / `--version` - - - -If set, the router prints its version number, then exits. - -
- -### Dev mode defaults - - - -**Do not set the `--dev` option in production.** If you want to replicate any specific dev mode functionality in production, instead make the corresponding modifications to your [YAML config file](#yaml-config-file). - - - -Setting the [`--dev`](#--dev) flag is equivalent to running `./router --hot-reload` with the following configuration options: - -```yaml -sandbox: - enabled: true -homepage: - enabled: false -supergraph: - introspection: true -include_subgraph_errors: - all: true -plugins: - # Enable with the header, Apollo-Expose-Query-Plan: true - experimental.expose_query_plan: true -``` - -## Configuration awareness in your text editor - -The router can generate a JSON schema for config validation in your text editor. This schema helps you format the YAML file correctly and also provides content assist. - -Generate the schema with the following command: - -```bash -./router config schema > configuration_schema.json -``` - -After you generate the schema, configure your text editor. Here are the instructions for some commonly used editors: - -- [Visual Studio Code](https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings) -- [Emacs](https://emacs-lsp.github.io/lsp-mode/page/lsp-yaml) -- [IntelliJ](https://www.jetbrains.com/help/idea/json.html#ws_json_using_schemas) -- [Sublime](https://github.com/sublimelsp/LSP-yaml) -- [Vim](https://github.com/Quramy/vison) - -## Upgrading your router configuration - -New releases of the router might introduce breaking changes to the [YAML config file's](#yaml-config-file) expected format, usually to extend existing functionality or improve usability. - -**If you run a new version of your router with a configuration file that it no longer supports, it emits a warning on startup and terminates.** - -If you encounter this warning, you can use the `router config upgrade` command to see the new expected format for your existing configuration file: - -```bash -./router config upgrade -``` - -You can also view a diff of exactly which changes are necessary to upgrade your existing configuration file: - -```bash -./router config upgrade --diff -``` - -## Validating your Router configuration - -The Router can be used to validate an existing configuration file. This can be useful if you want to have a validate step as part of your CI pipeline. - -``` -./router config validate -``` - -This command takes a config file and validates it against the router's full supported configuration format. - - - -This is a static validation that checks if it is syntactically correct using the JSON schema. The router does additional logical checks on startup against the config that this command does not capture. - - - -## YAML config file - -GraphOS Router and Apollo Router Core take an optional YAML configuration file as input via the [`--config`](#-c----config) option: - -```bash -./router --config router.yaml -``` - -This file enables you to customize numerous aspects of your router's behavior, covered in the subsections below. - -If you pass the [`--hot-reload`](#--hr----hot-reload) flag to the `router` command, your router automatically restarts whenever changes are made to its configuration file. - - - -Enable your text editor to validate the format and content of your router YAML configuration file by [configuring it with the router's configuration schema](#configuration-awareness-in-your-text-editor). - - - -### Listen address - -By default, the router starts an HTTP server that listens on `127.0.0.1:4000`. You can specify a different address by setting `supergraph.listen`: - -#### IPv4 - -```yaml title="router.yaml" -supergraph: - # The socket address and port to listen on - listen: 127.0.0.1:4000 -``` - -#### IPv6 - -```yaml title="router.yaml" -supergraph: - # The socket address and port to listen on. - # Note that this must be quoted to avoid interpretation as an array in YAML. - listen: "[::1]:4000" -``` - -#### Unix socket - - - -Listening on a Unix socket is not supported on Windows. - - - -```yaml title="router_unix.yaml" -supergraph: - # Absolute path to a Unix socket - listen: /tmp/router.sock -``` - -### Endpoint path - -By default, the router starts an HTTP server that exposes a `POST`/`GET` endpoint at path `/`. - -You can specify a different path by setting `supergraph.path`: - -```yaml title="router.yaml" -supergraph: - # The path for GraphQL execution - # (Defaults to /) - path: /graphql -``` - -The path must start with `/`. - -A path can contain parameters and wildcards: - -- `/{parameter}` matches a single segment. For example: - - - `/abc/{my_param}/def` matches `/abc/1/def` and `/abc/whatever/def`, but it doesn't match `/abc/1/2/def` or `/abc/def` - -- `/{*parameter}` matches all segments in the rest of a path. For example: - - `/abc/{*wildcard}` matches `/abc/1/def` and `/abc/w/h/a/t/e/v/e/r`, but it doesn't match `/abc/` or `/not_abc_at_all` - - - -- Both parameters and wildcards require a name, even though you can’t use those names anywhere. - -- The router doesn't support wildcards in the _middle_ of a path (e.g., `/{*wild}/graphql`). Instead, use a path parameter (e.g., `/{parameter}/graphql`). - - - -### Introspection - -By default, the router does _not_ resolve introspection queries. You can enable introspection like so: - -```yaml title="router.yaml" -# Do not enable introspection in production! -supergraph: - introspection: true -``` - -The [schema-intropsection schema](https://spec.graphql.org/draft/#sec-Schema-Introspection.Schema-Introspection-Schema) is recursive: a client can query the fields of the types of some other fields, and so on arbitrarily deep. This can produce responses that grow much faster than the size of the request. - -To protect against abusive Router now refuses to execute introspection queries that nest list fields too deep and returns an error instead. The criteria matches `MaxIntrospectionDepthRule` in graphql-js, but may change in future versions. - -In case it rejects legitimate queries, this check can be disabled in Router configuration: - -```yaml title="router.yaml" -# Do not enable introspection in production! -supergraph: - introspection: true -limits: - introspection_max_depth: false -``` - -### Debugging - -- To configure logging, see [Logging in the router](/router/configuration/telemetry/exporters/logging/overview). - -- To configure the inclusion of subgraph errors, see [Subgraph error inclusion](/router/configuration/subgraph-error-inclusion). - -### Landing pages - -The router can serve any of the following landing pages to browsers that visit its [endpoint path](#endpoint-path): - -- A basic landing page that displays an example query `curl` command (default) - - ```yaml title="router.yaml" - # This is the default behavior. You don't need to include this config. - homepage: - enabled: true - ``` - -- _No_ landing page - - ```yaml title="router.yaml" - homepage: - enabled: false - ``` - -- [Apollo Sandbox](/graphos/explorer/sandbox), which enables you to explore your schema and compose operations against it using the Explorer - - Note the additional configuration required to use Sandbox: - - ```yaml title="router.yaml" - sandbox: - enabled: true - - # Sandbox uses introspection to obtain your router's schema. - supergraph: - introspection: true - - # Sandbox requires the default landing page to be disabled. - homepage: - enabled: false - ``` - - - - **Do not enable Sandbox in production.** Sandbox requires enabling introspection, which is strongly discouraged in production environments. - - - -### Subgraph routing URLs - -By default, the router obtains the routing URL for each of your subgraphs from the composed supergraph schema you provide it. In most cases, no additional configuration is required. The URL can use HTTP and HTTPS for network access to subgraph, or have the following shape for Unix sockets usage: `unix:///path/to/subgraph.sock` - -However, if you _do_ need to override a particular subgraph's routing URL (for example, to handle changing network topography), you can do so with the `override_subgraph_url` option: - -```yaml -override_subgraph_url: - organizations: http://localhost:8080 - accounts: "${env.ACCOUNTS_SUBGRAPH_HOST_URL}" -``` - -In this example, the `organizations` subgraph URL is overridden to point to `http://localhost:8080`, and the `accounts` subgraph URL is overridden to point to a new URL using [variable expansion](#variable-expansion). The URL specified in the supergraph schema is ignored. - -Any subgraphs that are _omitted_ from `override_subgraph_url` continue to use the routing URL specified in the supergraph schema. - -If you need to override the subgraph URL at runtime on a per-request basis, you can use [request customizations](/router/customizations/overview/#request-path) in the `SubgraphService` layer. - -### Caching - -By default, the router stores the following data in its in-memory cache to improve performance: - -- Generated query plans -- Automatic persisted queries (APQ) -- Introspection responses - -You can configure certain caching behaviors for generated query plans and APQ (but not introspection responses). For details, see [In-Memory Caching in the router](/router/configuration/in-memory-caching/). - -**If you have a GraphOS Enterprise plan:** - -- You can configure a Redis-backed _distributed_ cache that enables multiple router instances to share cached values. For details, see [Distributed caching in the GraphOS Router](/router/configuration/distributed-caching/). -- You can configure a Redis-backed _entity_ cache that enables a client query to retrieve cached entity data split between subgraph reponses. For details, see [Subgraph entity caching in the GraphOS Router](/router/configuration/entity-caching/). - - - -### Enhanced operation signature normalization - - - - - -The router supports enhanced operation signature normalization in the following versions: - -- [General availability](/resources/product-launch-stages/#general-availability) in v1.54.0 and later -- [Experimental](/resources/product-launch-stages/#experimental-features) in v1.49.0 to v1.53.0 - - - -Apollo's legacy operation signature algorithm removes information about certain fields, such as input objects and aliases. -This removal means some operations may have the same normalized signature though they are distinct operations. - -Enhanced normalization incorporates [input types](#input-types) and [aliases](#aliases) in signature generation. -It also includes other improvements that make it more likely that two operations that only vary slightly have the same signature. - -Configure enhanced operation signature normalization in `router.yaml` with the `telemetry.apollo.signature_normalization_algorithm` option: - -```yaml title="router.yaml" -telemetry: - apollo: - signature_normalization_algorithm: enhanced # Default is legacy -``` - -Once you enable this configuration, operations with enhanced signatures might appear with different operation IDs than they did previously in GraphOS Studio. - -#### Input types - -Enhanced signatures include input object type shapes, while still redacting any actual values. -Legacy signatures [replace input object type with `{}`](/graphos/metrics/operation-signatures/#1-transform-in-line-argument-values). - -Given the following example operation: - -```graphql showLineNumbers=false -query InlineInputTypeQuery { - inputTypeQuery( - input: { - inputString: "foo" - inputInt: 42 - inputBoolean: null - nestedType: { someFloat: 4.2 } - enumInput: SOME_VALUE_1 - nestedTypeList: [{ someFloat: 4.2, someNullableFloat: null }] - listInput: [1, 2, 3] - } - ) { - enumResponse - } -} -``` - -The legacy normalization algorithm generates the following signature: - -```graphql showLineNumbers=false -query InlineInputTypeQuery { - inputTypeQuery(input: {}) { - enumResponse - } -} -``` - -The enhanced normalization algorithm generates the following signature: - -```graphql {3-11} showLineNumbers=false -query InlineInputTypeQuery { - inputTypeQuery( - input: { - inputString: "" - inputInt: 0 - inputBoolean: null - nestedType: { someFloat: 0 } - enumInput: SOME_VALUE_1 - nestedTypeList: [{ someFloat: 0, someNullableFloat: null }] - listInput: [] - } - ) { - enumResponse - } -} -``` - -#### Aliases - -Enhanced signatures include any field aliases used in an operation. -Legacy signatures [remove aliases completely](/graphos/metrics/operation-signatures/#field-aliases), meaning the signature may be invalid if the same field was used with multiple aliases. - -Given the following example operation: - -```graphql showLineNumbers=false -query AliasedQuery { - noInputQuery { - interfaceAlias1: interfaceResponse { - sharedField - } - interfaceAlias2: interfaceResponse { - ... on InterfaceImplementation1 { - implementation1Field - } - ... on InterfaceImplementation2 { - implementation2Field - } - } - inputFieldAlias1: objectTypeWithInputField(boolInput: true) { - stringField - } - inputFieldAlias2: objectTypeWithInputField(boolInput: false) { - intField - } - } -} -``` - -The legacy normalization algorithm generates the following signature: - -```graphql showLineNumbers=false -query AliasedQuery { - noInputQuery { - interfaceResponse { - sharedField - } - interfaceResponse { - ... on InterfaceImplementation1 { - implementation1Field - } - ... on InterfaceImplementation2 { - implementation2Field - } - } - objectTypeWithInputField(boolInput: true) { - stringField - } - objectTypeWithInputField(boolInput: false) { - intField - } - } -} -``` - -The enhanced normalization algorithm generates the following signature: - -```graphql showLineNumbers=false -query AliasedQuery { - noInputQuery { - interfaceAlias1: interfaceResponse { - sharedField - } - interfaceAlias2: interfaceResponse { - ... on InterfaceImplementation1 { - implementation1Field - } - ... on InterfaceImplementation2 { - implementation2Field - } - } - inputFieldAlias1: objectTypeWithInputField(boolInput: true) { - stringField - } - inputFieldAlias2: objectTypeWithInputField(boolInput: false) { - intField - } - } -} -``` - - - -### Extended reference reporting - - - - - -The router supports extended reference reporting in the following versions: - -- [General availability](/resources/product-launch-stages/#general-availability) in v1.54.0 and later -- [Experimental](/resources/product-launch-stages/#experimental-features) in v1.50.0 to v1.53.0 - - - - - -You can configure the router to report enum and input object references for enhanced insights and operation checks. -Apollo's legacy reference reporting doesn't include data about enum values and input object fields, meaning you can't view enum and input object field usage in GraphOS Studio. -Legacy reporting can also cause [inaccurate operation checks](#enhanced-operation-checks). - -Configure extended reference reporting in `router.yaml` with the `telemetry.apollo.metrics_reference_mode` option like so: - -```yaml title="router.yaml" -telemetry: - apollo: - metrics_reference_mode: extended # Default is legacy -``` - - - -### Extended error reporting - - - - - - - -The router supports extended error reporting in the following versions: - -- [Preview](/resources/product-launch-stages/#preview) in v2.1.2 and later -- [Experimental](/resources/product-launch-stages/#experimental-features) in v2.0.0 - - - -You can configure the router to report extended error information for improved diagnostics. -Apollo's legacy error reporting doesn't include the service or error code, meaning you can't easily attribute errors to their root cause in GraphOS Studio. - -Configure extended reference reporting in `router.yaml` with the `telemetry.apollo.errors.preview_extended_error_metrics` option like so: - -```yaml title="router.yaml" -telemetry: - apollo: - errors: - preview_extended_error_metrics: enabled # Default is disabled -``` - -[Learn more.](/graphos/routing/graphos-reporting#errors) - -#### Configuration effect timing - -Once you configure extended reference reporting, you can view enum value and input field usage alongside object [field usage in GraphOS Studio](/graphos/metrics/field-usage) for all subsequent operations. - -Configuring extended reference reporting automatically turns on [enhanced operation checks](#enhanced-operation-checks), though you won't see an immediate change in your operations check behavior. - -This delay is because operation checks rely on historical operation data. -To ensure sufficient data to distinguish between genuinely unused values and those simply not reported in legacy data, enhanced checks require some operations with extended reference reporting turned on. - -#### Enhanced operation checks - -Thanks to extended reference reporting, operation checks can more accurately flag issues for changes to enum values and input object fields. See the comparison table below for differences between standard operation checks based on legacy reference reporting and enhanced checks based on extended reference reporting. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Standard Check Behavior
- (Legacy reference reporting) -
- Enhanced Check Behavior
- (Extended reference reporting) -
- -##### Enum value removal - - Removing any enum values is considered a breaking change if any operations use the enum.Removing enum values is only a breaking change if historical operations use the specific enum value(s) that were removed.
- -##### Default argument changes for input object fields - - - Changing or removing a default argument is generally considered a breaking change, but changing or removing default values for input object fields isn't. - - Changing or removing default values for input object fields is considered a breaking change. - -You can [configure checks to ignore default values changes](/graphos/platform/schema-management/checks#ignored-conditions-settings). - -
- -##### Nullable input object field removal - - Removing a nullable input object field is always considered a breaking change.Removing a nullable input object field is only considered a breaking change if the nullable field is present in historical operations. If the nullable field is always omitted in historical operations, its removal isn't considered a breaking change.
- -##### Changing nullable input object fields to non-nullable - - Changing a nullable input object field to non-nullable is considered a breaking change.Changing a nullable input object field to non-nullable is only considered a breaking change if the field had a null value in historical operations. If the field was always a non-null value in historical operations, changing it to non-nullable isn't considered a breaking change.
- - - -You won't see an immediate change in checks behavior when you first turn on extended reference reporting. -[Learn more.](#configuration-effect-timing) - - - -### Safelisting with persisted queries - -You can enhance your graph's security with GraphOS Router by maintaining a persisted query list (PQL), an operation safelist made by your first-party apps. As opposed to automatic persisted queries (APQ) where operations are automatically cached, operations must be preregistered to the PQL. Once configured, the router checks incoming requests against the PQL. - -See [Safelisting with persisted queries](/router/configuration/persisted-queries) for more information. - -### HTTP header rules - -See [Sending HTTP headers to subgraphs](/graphos/routing/header-propagation/). - -### Traffic shaping - -To configure the shape of traffic between clients, routers, and subgraphs, see [Traffic shaping in the router](/router/configuration/traffic-shaping). - -### Cross-Origin Resource Sharing (CORS) - -See [Configuring CORS in the router](/router/configuration/cors). - -### Connectors support - -See [Working with Router](/graphos/schema-design/connectors/router) in the Apollo Connectors documentation. - -### Defer support - -See [router support for `@defer`](/router/executing-operations/defer-support/#disabling-defer). - -### Query batching support - -See [GraphOS Router's support for query batching](/router/executing-operations/query-batching). - -### Subscription support - -See [GraphQL subscriptions in the GraphOS Router](/router/executing-operations/subscription-support/#router-setup). - -### Authorization support - -- To configure authorization directives, see [Authorization directives](/router/configuration/authorization/#authorization-directives). - -- To configure the authorization plugin, see [Configuration options](/router/configuration/authorization/#configuration-options). - -### JWT authentication - -To enable and configure JWT authentication, see [JWT authentication in the GraphOS Router](/router/configuration/authn-jwt). - -### Cross-site request forgery (CSRF) prevention - -To configure CSRF prevention, see [CSRF prevention in the router](/router/configuration/csrf). - -### Subgraph authentication - -To configure subgraph authentication with AWS SigV4, see a [configuration example](/router/configuration/authn-subgraph/#configuration-example). - -### External coprocessing - -See [External coprocessing in the GraphOS Router](/router/customizations/coprocessor/). - -### Telemetry and monitoring - -The router supports standard and custom instrumentation to collect telemetry data from its request and response processing pipeline to produce logs, metrics and traces to export. - -See the [router telemetry overview](/router/configuration/telemetry/overview). - -### TLS - -The router supports TLS to authenticate and encrypt communications, both on the client side and the subgraph side. It works automatically on the subgraph side if the subgraph URL starts with `https://`. - -TLS support is configured in the `tls` section, under the `supergraph` key for the client side, and the `subgraph` key for the subgraph side, with configuration possible for all subgraphs and overriding per subgraph. - -The list of supported TLS versions and algorithms is static, it cannot be configured. - -Supported TLS versions: - -- TLS 1.2 -- TLS 1.3 - -Supported cipher suites: - -- TLS13_AES_256_GCM_SHA384 -- TLS13_AES_128_GCM_SHA256 -- TLS13_CHACHA20_POLY1305_SHA256 -- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 - -Supported key exchange groups: - -- X25519 -- SECP256R1 -- SECP384R1 - -#### TLS termination - -Clients can connect to the router directly over HTTPS, without terminating TLS in an intermediary. You can configure this in the `tls` configuration section: - -```yaml -tls: - supergraph: - certificate: ${file./path/to/certificate.pem} - certificate_chain: ${file./path/to/certificate_chain.pem} - key: ${file./path/to/key.pem} -``` - -To set the file paths in your configuration with Unix-style expansion, you can follow the examples in the [variable expansion](#variable-expansion) guide. - -The router expects the file referenced in the `certificate_chain` value to be a combination of several PEM certificates concatenated together into a single file (as is commonplace with Apache TLS configuration). - -#### Overriding certificate authorities for subgraphs - -The router verifies TLS connections to subgraphs using the list of certificate authorities the system provides. You can override this list with a combination of global and per-subgraph settings: - -```yaml -tls: - subgraph: - # Use these certificate authorities unless overridden per-subgraph - all: - certificate_authorities: "${file./path/to/ca.crt}" - # Override global setting for individual subgraphs - subgraphs: - products: - certificate_authorities: "${file./path/to/product_ca.crt}" -``` - -The router expects the file referenced in the `certificate_chain` value to be a combination of several PEM certificates concatenated together into a single file (as is commonplace with Apache TLS configuration). - -You can only configure these certificates via the router's configuration since using `SSL_CERT_FILE` also overrides certificates for sending telemetry and communicating with Apollo Uplink. - -If the subgraph is presenting a self-signed certificate, it must be generated with the proper file extension and with `basicConstraints` disabled. You can generate it with the following command line command from a certificate signing request, in this example, `server.csr`: - -``` -openssl x509 -req -in server.csr -signkey server.key -out server.crt -extfile v3.ext -``` - -You can generate a `v3.ext` extension file like so: - -``` -subjectKeyIdentifier = hash -authorityKeyIdentifier = keyid:always,issuer:always -# this has to be disabled -# basicConstraints = CA:TRUE -keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign -subjectAltName = DNS:local.apollo.dev -issuerAltName = issuer:copy -``` - - - -Make sure to change the `subjectAltName` field to the subgraph's name. - - - -This produces the file as `server.crt` which can be used in `certificate_authorities`. - -#### TLS client authentication for subgraph requests - -The router supports mutual TLS authentication (mTLS) with the subgraphs. This means that it can authenticate itself to the subgraph using a certificate chain and a cryptographic key. It can be configured as follows: - -```yaml -tls: - subgraph: - # Use these certificates and key unless overridden per-subgraph - all: - client_authentication: - certificate_chain: ${file./path/to/certificate_chain.pem} - key: ${file./path/to/key.pem} - # Override global setting for individual subgraphs - subgraphs: - products: - client_authentication: - certificate_chain: ${file./path/to/certificate_chain.pem} - key: ${file./path/to/key.pem} -``` - -#### Redis TLS configuration - -For Redis TLS connections, you can set up a client certificate or override the root certificate authority by configuring `tls` in your router's [YAML config file](https://www.apollographql.com/docs/router/overview/#yaml-config-file). For example: - -```yaml -apq: - router: - cache: - redis: - urls: ["rediss://redis.example.com:6379"] - #highlight-start - tls: - certificate_authorities: ${file./path/to/ca.crt} - client_authentication: - certificate_chain: ${file./path/to/certificate_chain.pem} - key: ${file./path/to/key.pem} - #highlight-end -``` - -### Request limits - -The GraphOS Router supports enforcing three types of request limits for enhanced security: - -- Network-based limits -- Lexical, parser-based limits -- Semantic, operation-based limits (this is an [Enterprise feature](/router/enterprise-features/)) - -The router rejects any request that violates at least one of these limits. - -```yaml title="router.yaml" -limits: - # Network-based limits - http_max_request_bytes: 2000000 # Default value: 2 MB - http1_max_request_headers: 200 # Default value: 100 - http1_max_request_buf_size: 800kib # Default value: 400kib - - # Parser-based limits - parser_max_tokens: 15000 # Default value - parser_max_recursion: 500 # Default value - - # Operation-based limits (Enterprise only) - max_depth: 100 - max_height: 200 - max_aliases: 30 - max_root_fields: 20 -``` - -#### Operation-based limits (Enterprise only) - -See [this article](/router/configuration/operation-limits/). - -#### Network-based limits - -##### `http_max_request_bytes` - -Limits the amount of data read from the network for the body of HTTP requests, -to protect against unbounded memory consumption. -This limit is checked before JSON parsing. -Both the GraphQL document and associated variables count toward it. - -The default value is `2000000` bytes, 2 MB. - -Before increasing this limit significantly consider testing performance -in an environment similar to your production, especially if some clients are untrusted. -Many concurrent large requests could cause the router to run out of memory. - -##### `http1_max_request_headers` - -Limit the maximum number of headers of incoming HTTP1 requests. -The default value is 100 headers. - -If router receives more headers than the buffer size, it responds to the client with `431 Request Header Fields Too Large`. - -##### `http1_max_request_buf_size` - -Limit the maximum buffer size for the HTTP1 connection. Default is ~400kib. - -#### Parser-based limits - -##### `parser_max_tokens` - -Limits the number of tokens a query document can include. This counts _all_ tokens, including both [lexical and ignored tokens](https://spec.graphql.org/October2021/#sec-Language.Source-Text.Lexical-Tokens). - -The default value is `15000`. - -##### `parser_max_recursion` - -Limits the deepest level of recursion allowed by the router's GraphQL parser to prevent stack overflows. This corresponds to the deepest nesting level of any single GraphQL operation or fragment defined in a query document. - -The default value is `500`. - -In the example below, the `GetProducts` operation has a recursion of three, and the `ProductVariation` fragment has a recursion of two. Therefore, the _max_ recursion of the query document is three. - -```graphql -query GetProducts { - allProducts { - #1 - ...productVariation - delivery { - #2 - fastestDelivery #3 - } - } -} - -fragment ProductVariation on Product { - variation { - #1 - name #2 - } -} -``` - -Note that the router calculates the recursion depth for each operation and fragment _separately_. Even if a fragment is included in an operation, that fragment's recursion depth does not contribute to the _operation's_ recursion depth. - -### Demand control - -See [Demand Control](/router/executing-operations/demand-control) to learn how to analyze the cost of operations and to reject requests with operations that exceed customizable cost limits. - -### Early cancel - -Up until [Apollo Router Core v1.43.1](https://github.com/apollographql/router/releases/tag/v1.43.1), when the client closed the connection without waiting for the response, the entire request was cancelled and did not go through the entire pipeline. Since this causes issues with request monitoring, the router introduced a new behavior in 1.43.1. Now, the entire pipeline is executed if the request is detected as cancelled, but subgraph requests are not actually done. The response will be reported with the `499` status code, but not actually sent to the client. -To go back to the previous behavior of immediately cancelling the request, the following configuration can be used: - -```yaml -supergraph: - early_cancel: true -``` - -Additionally, since v1.43.1, the router can show a log when it detects that the client canceled the request. This log can be activated with: - -```yaml title="router.yaml" -supergraph: - experimental_log_on_broken_pipe: true -``` - -### Connection shutdown timeout - -When the Router schema or configuration updates all connections must be closed for resources to be freed. -To ensure that long-lived connections do not hang on to resources, a maximum graceful shutdown timeout can be configured. - -```yaml title="router.yaml" -supergraph: - connection_shutdown_timeout: 60s -``` - -The default value is 60 seconds. - -Note that if `early_cancel` is `false` (default), then requests in progress will still hold onto pipeline resources. -Traffic shaping request timeouts should be used to prevent long-running requests. - -```yaml title="router.yaml" -traffic_shaping: - router: - timeout: 60s -``` - -### Header Read Timeout - -The header read timeout is the amount of time the Router will wait to receive the complete request headers from a client before timing out. It applies both when the connection is fully idle and when a request has been started but sending the headers has not been completed. - -By default, the header read timeout is set to 10 seconds. A longer timeout can be configured using the `server.http.header_read_timeout` configuration option. - -```yaml title="router.yaml" -server: - http: - header_read_timeout: 30s -``` - -### Plugins - -You can customize the router's behavior with [plugins](/router/customizations/overview). Each plugin can have its own section in the configuration file with arbitrary values: - -```yaml {4,8} title="example-plugin-router.yaml" -plugins: - example.plugin: - var1: "hello" - var2: 1 -``` - -### Variable expansion - -You can reference variables directly in your YAML config file. This is useful for referencing secrets without including them in the file. - -Currently, the router supports expansion of environment variables and file paths. Corresponding variables are prefixed with `env.` and `file.`, respectively. - -The router uses Unix-style expansion. Here are some examples: - -- `${env.ENV_VAR_NAME}` expands to the value of environment variable `ENV_VAR_NAME`. -- `${env.ENV_VAR_NAME:-some_default}` expands to the value of environment variable `ENV_VAR_NAME`, or falls back to the value `some_default` if the environment variable is not defined. -- `${file.a.txt}` expands to the contents of the file `a.txt`. -- `${file.a.txt:-some_default}` expands to the contents of the file `a.txt`, or falls back to the value `some_default` if the file does not exist. - -Variable expansions are valid only for YAML _values_, not keys: - - - -```yaml -supergraph: - listen: "${env.MY_LISTEN_ADDRESS}" #highlight-line -example: - password: "${env.MY_PASSWORD}" #highlight-line -``` - - - - -### Automatic fragment generation - -By default, the router compresses subgraph requests by generating fragment -definitions based on the shape of the subgraph operation. In many cases this -significantly reduces the size of the query sent to subgraphs. - -You can explicitly opt-out of this behavior by specifying: - -```yaml -supergraph: - generate_query_fragments: false -``` - -### Reusing configuration - -You can reuse parts of your configuration file in multiple places using standard YAML aliasing syntax: - -```yaml title="router.yaml" -headers: - subgraphs: - products: - request: - - insert: &insert_custom_header - name: "custom-header" - value: "something" - reviews: - request: - - insert: *insert_custom_header -``` - -Here, the `name` and `value` entries under `&insert_custom_header` are reused under `*insert_custom_header`. - -## Related topics - -- [Checklist for configuring the router for production](/technotes/TN0008-production-readiness-checklist/#apollo-router) \ No newline at end of file diff --git a/docs/source/routing/configuration/cli.mdx b/docs/source/routing/configuration/cli.mdx new file mode 100644 index 0000000000..f0dcc9d821 --- /dev/null +++ b/docs/source/routing/configuration/cli.mdx @@ -0,0 +1,315 @@ +--- +title: Router CLI Configuration Reference +subtitle: "" +description: Reference of command-line options for Apollo GraphOS Router and Apollo Router Core. +--- +import RouterYaml from '../../../shared/router-yaml-complete.mdx'; +import RouterConfigTable from '../../../shared/router-config-properties-table.mdx'; + +This reference covers the command-line options for configuring an Apollo Router. + +## Command-line options + +This reference lists and describes the options supported by the `router` binary via command-line options. Where indicated, some of these options can also be provided via an environment variable. + + + +For options available as both a command-line option and an environment variable, the command-line value takes precedence. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Option / Environment VariableDescription
+ +##### `-s` / `--supergraph` + +`APOLLO_ROUTER_SUPERGRAPH_PATH`, `APOLLO_ROUTER_SUPERGRAPH_URLS` + + + +The [supergraph schema](/federation/federated-types/overview#supergraph-schema) of a router. Specified by absolute or relative path (`-s` / `--supergraph `, or `APOLLO_ROUTER_SUPERGRAPH_PATH`), or a comma-separated list of URLs (`--supergraph-urls `, or `APOLLO_ROUTER_SUPERGRAPH_URLS`).

+ +> 💡 Avoid embedding tokens in `APOLLO_ROUTER_SUPERGRAPH_URLS` because the URLs may appear in log messages.

+ +Setting this option disables polling from Apollo Uplink to fetch the latest supergraph schema.
+ +To learn how to compose your supergraph schema with the Rover CLI, see the [Federation quickstart](/federation/quickstart).

+ +**Required** if you are _not_ using managed federation. If you _are_ using managed federation, you may need to set this option when following [advanced deployment workflows](/federation/managed-federation/deployment/#advanced-deployment-workflows). + +
+ +##### `-c` / `--config` + +`APOLLO_ROUTER_CONFIG_PATH` + + + +The absolute or relative path to the router's optional [YAML configuration file](#yaml-config-file). + +
+ +##### `--apollo-key-path` + +`APOLLO_KEY_PATH` + + + +The absolute or relative path to a file containing the Apollo graph API key for use with managed federation. + +⚠️ **This is not available on Windows.** + +
+ +##### `--dev` + + + +⚠️ **Do not set this option in production!** +
+If set, a router runs in dev mode to help with local development. + +[Learn more about dev mode.](/graphos/routing/configuration/yaml#dev-mode-defaults) + +
+ +##### `--hr` / `--hot-reload` + +`APOLLO_ROUTER_HOT_RELOAD` + + + +If set, the router watches for changes to its configuration file and any supergraph file passed with `--supergraph` and reloads them automatically without downtime. This setting only affects local files provided to the router. The supergraph and configuration provided from GraphOS via Launches (and delivered via Uplink) are _always_ loaded automatically, regardless of this setting. + +
+ +##### `--log` + +`APOLLO_ROUTER_LOG` + + + +The log level, indicating the _most_ severe log message type to include. In ascending order of verbosity, can be one of: `off`, `error`, `warn`, `info`, `debug`, or `trace`. + +The default value is `info`. + +
+ +##### `--license` + +`APOLLO_ROUTER_LICENSE_PATH`, `APOLLO_ROUTER_LICENSE` + + + +An offline GraphOS Enterprise license. Enables Enterprise router features when disconnected from GraphOS.
+ +An offline license is specified either as an absolute or relative path to a license file (`--license ` or `APOLLO_ROUTER_LICENSE_PATH`), or as the stringified contents of a license (`APOLLO_ROUTER_LICENSE`).
+ +When not set, the router retrieves an Enterprise license [from GraphOS via Apollo Uplink](/router/enterprise-features/#the-enterprise-license).
+ +For information about fetching an offline license and configuring the router, see [Offline Enterprise license](/router/enterprise-features/#offline-enterprise-license). + +
+ +##### `--apollo-uplink-endpoints` + +`APOLLO_UPLINK_ENDPOINTS` + + + +If using [managed federation](/federation/managed-federation/overview/), the Apollo Uplink URL(s) that the router should poll to fetch its latest configuration. Almost all managed router instances should _omit_ this option to use the default set of Uplink URLs.
+ +If you specify multiple URLs, separate them with commas (no whitespace).
+ +For default behavior and possible values, see [Apollo Uplink](/federation/managed-federation/uplink/). + +
+ +##### `--apollo-uplink-timeout` + +`APOLLO_UPLINK_TIMEOUT` + + + +The request timeout for each poll sent to Apollo Uplink. + +The default value is `30s` (thirty seconds). + +
+ +##### `--anonymous-telemetry-disabled` + +`APOLLO_TELEMETRY_DISABLED` + + + +If set, disables sending anonymous usage information to Apollo. + +
+ +##### `--listen` + +`APOLLO_ROUTER_LISTEN_ADDRESS` + + + +If set, the listen address of the router. + +
+ +##### `-V` / `--version` + + + +If set, the router prints its version number, then exits. + +
+ +### Development mode + +The router can be run in development mode by using the `--dev` command-line option. + +The `--dev` option is equivalent to running the router with the `--hot-reload` option the following configuration options: + +```yaml +sandbox: + enabled: true +homepage: + enabled: false +supergraph: + introspection: true +include_subgraph_errors: + all: true +plugins: + # Enable with the header, Apollo-Expose-Query-Plan: true + experimental.expose_query_plan: true +``` + + + +**Don't set the `--dev` option in production.** If you want to replicate any specific dev mode functionality in production, set the corresponding option in your [YAML config file](#yaml-config-file). + + + + +## Configuration schema for IDE validation + +The router can generate a JSON schema for config validation in your text editor. This schema helps you format the YAML file correctly and also provides content assistance. + +Generate the schema with the following command: + +```bash +./router config schema > configuration_schema.json +``` + +After you generate the schema, configure your text editor. Here are the instructions for some commonly used editors: + +- [Visual Studio Code](https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings) +- [Emacs](https://emacs-lsp.github.io/lsp-mode/page/lsp-yaml) +- [IntelliJ](https://www.jetbrains.com/help/idea/json.html#ws_json_using_schemas) +- [Sublime](https://github.com/sublimelsp/LSP-yaml) +- [Vim](https://github.com/Quramy/vison) + +## Upgrading your router configuration + +New releases of the router might introduce breaking changes to the [YAML config file's](#yaml-config-file) expected format, usually to extend existing functionality or improve usability. + +**If you run a new version of your router with a configuration file that it no longer supports, it emits a warning on startup and terminates.** + +If you encounter this warning, you can use the `router config upgrade` command to see the new expected format for your existing configuration file: + +```bash +./router config upgrade +``` + +You can also view a diff of exactly which changes are necessary to upgrade your existing configuration file: + +```bash +./router config upgrade --diff +``` + +## Validating your router configuration + +The router can be used to validate an existing configuration file. This can be useful if you want to have a validate step as part of your CI pipeline. + +``` +./router config validate +``` + +This command takes a config file and validates it against the router's full supported configuration format. + + + +This is a static validation that checks if it is syntactically correct using the JSON schema. The router does additional logical checks on startup against the config that this command does not capture. + + diff --git a/docs/source/routing/configuration/envvars.mdx b/docs/source/routing/configuration/envvars.mdx new file mode 100644 index 0000000000..fab56321dd --- /dev/null +++ b/docs/source/routing/configuration/envvars.mdx @@ -0,0 +1,83 @@ +--- +title: Router Environment Variable Configuration Reference +subtitle: "" +description: Reference of YAML configuration properties for Apollo GraphOS Router and Apollo Router Core. +--- + +This reference covers the environment variables for configuring an Apollo Router. + +## Environment variables + +This section lists and describes the environment variables you can set when running the `router` binary. + + + +These environment variables apply only if your supergraph schema is managed by GraphOS. + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Environment VariableDescription
+ +##### `APOLLO_GRAPH_REF` + + + +The graph ref for the GraphOS graph and variant that the router fetches its supergraph schema from (e.g., `docs-example-graph@staging`). + +**Required** when using [managed federation](/federation/managed-federation/overview/), except when using an [offline license](#--license) to run the router. + +
+ +##### `APOLLO_KEY` + + + +The [graph API key](/graphos/api-keys/#graph-api-keys) that the router should use to authenticate with GraphOS when fetching its supergraph schema. + +**Required** when using [managed federation](/federation/managed-federation/overview/), except when using an [offline license](#--license) to run the router or when using `APOLLO_KEY_PATH`. + +
+ +##### `APOLLO_KEY_PATH` + + + +⚠️ **This is not available on Windows.** + +A path to a file containing the [graph API key](/graphos/api-keys/#graph-api-keys) that the router should use to authenticate with GraphOS when fetching its supergraph schema. + +**Required** when using [managed federation](/federation/managed-federation/overview/), except when using an [offline license](#--license) to run the router or when using `APOLLO_KEY`. + +
+ +## Example command + +To use environment variables when running router, you must set them before the `router` command: + +```bash +APOLLO_KEY="..." APOLLO_GRAPH_REF="..." ./router +``` diff --git a/docs/source/routing/configuration/overview.mdx b/docs/source/routing/configuration/overview.mdx new file mode 100644 index 0000000000..c26c5fb777 --- /dev/null +++ b/docs/source/routing/configuration/overview.mdx @@ -0,0 +1,38 @@ +--- +title: Router Configuration Overview +subtitle: Overview and reference for router configuration +description: Learn how to configure the Apollo GraphOS Router or Apollo Router Core with environment variables, command-line options and commands, and YAML configuration files. +redirectFrom: + - /router/configuration/overview +--- + +Running an Apollo Router instance involves some key steps: +- Getting the schema of the federated supergraph that your router is running +- Configuring runtime features declaratively in YAML +- Deploying to different environments (dev, prod, etc.) +- Providing configuration command-line options, YAML, and environment variables at startup + +## Getting supergraph schema + +As the runtime for a federated graph, a router needs to know the schema of the graph it's running. We call the schema for a federated graph a _supergraph schema_. + +You need to configure the router at startup to know where to get its supergraph schema. That configuration depends on whether or not its supergraph schema is managed by GraphOS: + +- If your supergraph schema is managed by GraphOS, you can configure your router with the GraphOS graph ref and API key as environment variables (`APOLLO_GRAPH_REF` and `APOLLO_KEY`). Based on these, the router can automatically fetch the supergraph schema from GraphOS. +- Otherwise, you can provide the router a supergraph schema file [via command line or environment variable](/graphos/routing/configuration/cli#-s----supergraph). + +## Configuring features in YAML + +Configuring the router's features happens primarily via a YAML configuration file. Named `router.yaml` by default, the router's YAML configuration file lets you configure all of a router's runtime features declaratively. + +## Passing configuration at startup + +Command-line options, a YAML config, and environment variables are passed to the router at startup. + +This example command would be for a router with a GraphOS-managed graph and a custom named `myrouter.yaml` config file: + +```bash showLineNumbers=false +APOLLO_KEY="..." APOLLO_GRAPH_REF="..." router --config myrouter.yaml +``` + +> The router can hot-reload updated configuration. When enabled, changes in `router.yaml` trigger the router to restart with its updated configuration. diff --git a/docs/source/routing/configuration/yaml.mdx b/docs/source/routing/configuration/yaml.mdx new file mode 100644 index 0000000000..ed21f96c6e --- /dev/null +++ b/docs/source/routing/configuration/yaml.mdx @@ -0,0 +1,818 @@ +--- +title: Router YAML Configuration Reference +subtitle: "" +description: Reference of YAML configuration properties for Apollo GraphOS Router and Apollo Router Core. +--- +import RouterYaml from '../../../shared/router-yaml-complete.mdx'; +import RouterConfigTable from '../../../shared/router-config-properties-table.mdx'; + +import Apq from '../../../shared/config/apq.mdx'; +import Authn from '../../../shared/config/authentication.mdx'; +import Authz from '../../../shared/config/authorization.mdx'; +import Batching from '../../../shared/config/batching.mdx'; +import Connectors from '../../../shared/config/connectors.mdx'; +import Coproc from '../../../shared/config/coprocessor.mdx'; +import Cors from '../../../shared/config/cors.mdx'; +import Csrf from '../../../shared/config/csrf.mdx'; +import DemandCtrl from '../../../shared/config/demand_control.mdx'; +import ExperimentalChaos from '../../../shared/config/experimental_chaos.mdx'; +import ExperimentalType from '../../../shared/config/experimental_type_conditioned_fetching.mdx'; +import FleetDetector from '../../../shared/config/fleet_detector.mdx'; +import ForbidMut from '../../../shared/config/forbid_mutations.mdx'; +import Headers from '../../../shared/config/headers.mdx'; +import HealthChk from '../../../shared/config/health_check.mdx'; +import Homepage from '../../../shared/config/homepage.mdx'; +import IncludeSubErr from '../../../shared/config/include_subgraph_errors.mdx'; +import LicenseEnf from '../../../shared/config/license_enforcement.mdx'; +import Limits from '../../../shared/config/limits.mdx'; +import OverrideSubUrl from '../../../shared/config/override_subgraph_url.mdx'; +import PersistedQueries from '../../../shared/config/persisted_queries.mdx'; +import Plugins from '../../../shared/config/plugins.mdx'; +import PreviewEntityCache from '../../../shared/config/preview_entity_cache.mdx'; +import PreviewFileUploads from '../../../shared/config/preview_file_uploads.mdx'; +import ProgOverride from '../../../shared/config/progressive_override.mdx'; +import Rhai from '../../../shared/config/rhai.mdx'; +import Sandbox from '../../../shared/config/sandbox.mdx'; +import Subscription from '../../../shared/config/subscription.mdx'; +import Supergraph from '../../../shared/config/supergraph.mdx'; +import Telemetry from '../../../shared/config/telemetry.mdx'; +import Tls from '../../../shared/config/tls.mdx'; +import TrafficShaping from '../../../shared/config/traffic_shaping.mdx'; + +This reference covers the YAML configuration file properties for configuring an Apollo Router. + +## YAML configuration properties + +The router can be configured by a YAML configuration file. This file enables you to declaratively configure various runtime properties of your router's behavior. + +At startup, you set the config file for your router by providing its path with the [`--config`](#-c----config) option: + +```bash +./router --config router.yaml +``` + + + +Enable your text editor to validate the format and content of your router YAML configuration file by [configuring it with the router's configuration schema](/graphos/routing/configuration/cli#configuration-schema-for-ide-validation). + + + +## Example YAML with all properties + +Expand the code block to view an example YAML config file containing all properties. + + + + + + + +## Properties + +--- + + + +Learn more in [Caching Automatic Persisted Queries](/graphos/routing/performance/caching/in-memory#caching-automatic-persisted-queries-apq). + +--- + + + +- To learn about JWT authentication, go to [JWT authentication in the GraphOS Router](/router/configuration/authn-jwt). + +- To learn about subgraph authentication with AWS SigV4, go to a [subgraph authentication configuration example](/router/configuration/authn-subgraph/#configuration-example). + +--- + + + +- To configure authorization directives, see [Authorization directives](/router/configuration/authorization/#authorization-directives). + +- To configure the authorization plugin, see [Configuration options](/router/configuration/authorization/#configuration-options). + +--- + + + +Learn more in [query batching](/router/executing-operations/query-batching). + +--- + + + +Learn more in [Working with router for Apollo Connectors](/graphos/connectors/router). + +--- + + + +Learn more in [External coprocessing in the GraphOS Router](/router/customizations/coprocessor/). + +--- + + + +By default, the router only allows GraphOS Studio to initiate browser connections to it. If your supergraph serves data to other browser-based applications, you need to update its Cross-Origin Resource Sharing (CORS) configuration. + +Learn more in [CORS](/graphos/routing/security/cors). + +--- + + + +Learn more in [CSRF prevention in the router](/router/configuration/csrf). + +--- + + + +With demand control, the router analyzes the cost of operations and rejects requests with operations that exceed customizable cost limits. + +Learn more in [Demand Control](/router/executing-operations/demand-control) + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +Learn more in [Sending HTTP headers to subgraphs](/graphos/routing/header-propagation/). + +--- + + + +Learn more in [Health Checks](/graphos/routing/self-hosted/health-checks). + +--- + + + +The router can serve a landing page to browsers that visit its endpoint path (`supergraph.path`): + +- A basic landing page that displays an example query `curl` command (default) + + ```yaml title="router.yaml" + # This is the default behavior. You don't need to include this config. + homepage: + enabled: true + ``` + +- _No_ landing page + + ```yaml title="router.yaml" + homepage: + enabled: false + ``` + +--- + + + +--- + + + +--- + + + +Learn more in [Request Limits](/graphos/routing/security/request-limits). + +--- + + + +By default, the router obtains the routing URL for each of your subgraphs from the composed supergraph schema you provide it. In most cases, no additional configuration is required. The URL can use HTTP and HTTPS for network access to subgraph, or have the following shape for Unix sockets usage: `unix:///path/to/subgraph.sock` + +However, if you _do_ need to override a particular subgraph's routing URL (for example, to handle changing network topography), you can do so with the `override_subgraph_url` option: + +```yaml +override_subgraph_url: + organizations: http://localhost:8080 + accounts: "${env.ACCOUNTS_SUBGRAPH_HOST_URL}" +``` + +In this example, the `organizations` subgraph URL is overridden to point to `http://localhost:8080`, and the `accounts` subgraph URL is overridden to point to a new URL using [variable expansion](#variable-expansion). The URL specified in the supergraph schema is ignored. + +Any subgraphs that are _omitted_ from `override_subgraph_url` continue to use the routing URL specified in the supergraph schema. + +If you need to override the subgraph URL at runtime on a per-request basis, you can use [request customizations](/router/customizations/overview/#request-path) in the `SubgraphService` layer. + + + +You can enhance your graph's security with GraphOS Router by maintaining a persisted query list (PQL), an operation safelist made by your first-party apps. As opposed to automatic persisted queries (APQ) where operations are automatically cached, operations must be preregistered to the PQL. Once configured, the router checks incoming requests against the PQL. + +Learn more in [Safelisting with persisted queries](/router/configuration/persisted-queries). + +--- + + + +You can customize the router's behavior with [plugins](/router/customizations/overview). Each plugin can have its own section in the configuration file with arbitrary values: + +```yaml {4,8} title="example-plugin-router.yaml" +plugins: + example.plugin: + var1: "hello" + var2: 1 +``` + +Learn more in [Native Plugins for router](/graphos/routing/customization/native-plugins). + +--- + + + +Learn more in [Entity Caching](/graphos/routing/performance/caching/entity). + +--- + + + +Learn more in [File Uploads](/graphos/routing/operations/file-upload). + +--- + + + +Learn more in [Progressive Override](/graphos/schema-design/federated-schemas/reference/directives#progressive-override). + +--- + + + +Learn more in [Rhai customization for router](/graphos/routing/customization/rhai). + +--- + + + +[Apollo Sandbox](/graphos/explorer/sandbox) is a GraphQL development environment. It runs a graph via introspection queries on the router's supergrpah schema, and it provides an IDE for making queries to the graph. + +Running Sandbox in router requires configuring `sandbox.enabled`, `supergraph.instrospection`, and `homepage.enabled`: + +```yaml title="router.yaml" +sandbox: + enabled: true + +# Sandbox uses introspection to obtain your router's schema. +supergraph: + introspection: true + +# Sandbox requires the default landing page to be disabled. +homepage: + enabled: false +``` + + + +**Do not enable Sandbox in production.** Sandbox requires enabling introspection, which is strongly discouraged in production environments. + + + +Learn more in [Apollo Sandbox](/graphos/platform/sandbox). + +--- + + + +Learn more in [Subscriptions](/graphos/routing/operations/subscriptions). + +--- + + + +#### Supergraph listen address + +As the gateway and single endpoint to your supergraph, an Apollo Router has a socket address and port that it listens for client requests. This listen address is configurable in YAML as `supergraph.listen`. + +By default, the router starts an HTTP server that listens on `127.0.0.1:4000`. You can specify a different address by setting `supergraph.listen` for IPv4, IPv6, or Unix sockets. + +##### IPv4 + +```yaml title="router.yaml" +supergraph: + # The socket address and port to listen on (default: 127.0.0.1:400) + listen: 127.0.0.1:4000 +``` + +##### IPv6 + +```yaml title="router.yaml" +supergraph: + # The socket address and port to listen on. (default: [::1]:4000) + # Note that this must be quoted to avoid interpretation as an array in YAML. + listen: "[::1]:4000" +``` + +##### Unix socket + +```yaml title="router_unix.yaml" +supergraph: + # Absolute path to a Unix socket + listen: /tmp/router.sock +``` + + + +Listening on a Unix socket is not supported on Windows. + + + +#### Supergraph endpoint path + +The path of the HTTP endpoint of the supergraph that the router runs is configured by `supergraph.path`. + +By default, the router starts an HTTP server that exposes a `POST`/`GET` endpoint at path `/`. + +```yaml title="router.yaml" +supergraph: + # The path for GraphQL execution + # (Defaults to /) + path: /graphql +``` + +The path must start with `/`. + +A path can contain parameters and wildcards: + +- `/{parameter}` matches a single segment. For example: + + - `/abc/{my_param}/def` matches `/abc/1/def` and `/abc/whatever/def`, but it doesn't match `/abc/1/2/def` or `/abc/def` + +- `/{*parameter}` matches all segments in the rest of a path. For example: + - `/abc/{*wildcard}` matches `/abc/1/def` and `/abc/w/h/a/t/e/v/e/r`, but it doesn't match `/abc/` or `/not_abc_at_all` + + + +- Both parameters and wildcards require a name, even though you can’t use those names anywhere. + +- The router doesn't support wildcards in the _middle_ of a path (e.g., `/{*wild}/graphql`). Instead, use a path parameter (e.g., `/{parameter}/graphql`). + + + +#### Introspection + +In GraphQL, introspection queries are used during development to learn about a GraphQL API's schema. The router can resolve introspection queries, based on the configuration of `supergraph.introspection`. + +By default, the router doesn't resolve introspection queries. + +To enable introspection queries during development, set the `supergraph.introspection` flag: + +```yaml title="router.yaml" +# Do not enable introspection in production! +supergraph: + introspection: true +``` + +##### Introspection recursion limit + +The [schema-introspection schema](https://spec.graphql.org/draft/#sec-Schema-Introspection.Schema-Introspection-Schema) is recursive: a client can query the fields of the types of some other fields, and so on arbitrarily deep. This can produce responses that grow much faster than the size of the request. + +To prevent this, the router is configured by default to not execute introspection queries that nest list fields that are too deep, instead returning an error. The criteria matches `MaxIntrospectionDepthRule` in graphql-js, and it may change in future versions. + +In case the router rejects legitimate queries, you can disable the limit by setting the `limits.introspection_max_depth` flag: + +```yaml title="router.yaml" +# Do not enable introspection in production! +supergraph: + introspection: true +limits: + introspection_max_depth: false +``` + +#### Early cancel + +Up until [Apollo Router Core v1.43.1](https://github.com/apollographql/router/releases/tag/v1.43.1), when the client closed the connection without waiting for the response, the entire request was cancelled and did not go through the entire pipeline. Since this causes issues with request monitoring, the router introduced a new behavior in 1.43.1. Now, the entire pipeline is executed if the request is detected as cancelled, but subgraph requests are not actually done. The response will be reported with the `499` status code, but not actually sent to the client. + +To go back to the previous behavior of immediately cancelling the request, the following configuration can be used for `supergraph.early_cancel`: + +```yaml +supergraph: + early_cancel: true +``` + +Additionally, since v1.43.1, the router can show a log when it detects that the client canceled the request. This log can be activated with: + +```yaml title="router.yaml" +supergraph: + experimental_log_on_broken_pipe: true +``` + +#### Connection shutdown timeout + +When the Router schema or configuration updates all connections must be closed for resources to be freed. +To ensure that long-lived connections do not hang on to resources, a maximum graceful shutdown timeout can be configured with `supergraph.connection_shutdown_timeout`: + +```yaml title="router.yaml" +supergraph: + connection_shutdown_timeout: 60s +``` + +The default value is 60 seconds. + +Note that if `early_cancel` is `false` (default), then requests in progress will still hold onto pipeline resources. +In that case, traffic shaping request timeouts should be used to prevent long-running requests: + +```yaml title="router.yaml" +traffic_shaping: + router: + timeout: 60s +``` + +#### Automatic fragment generation + +By default, the router compresses subgraph requests by generating fragment definitions based on the shape of the subgraph operation. In many cases this significantly reduces the size of the query sent to subgraphs. + +You can explicitly opt-out of this behavior by specifying `supergraph.generate_query_fragments`: + +```yaml +supergraph: + generate_query_fragments: false +``` + +--- + + + + + +#### Enhanced operation signature normalization + + + + + +The router supports enhanced operation signature normalization in the following versions: + +- [General availability](/resources/product-launch-stages/#general-availability) in v1.54.0 and later +- [Experimental](/resources/product-launch-stages/#experimental-features) in v1.49.0 to v1.53.0 + + + +Apollo's legacy operation signature algorithm removes information about certain fields, such as input objects and aliases. +This removal means some operations may have the same normalized signature though they are distinct operations. + +Enhanced normalization incorporates [input types](#input-types) and [aliases](#aliases) in signature generation. +It also includes other improvements that make it more likely that two operations that only vary slightly have the same signature. + +Configure enhanced operation signature normalization in `router.yaml` with the `telemetry.apollo.signature_normalization_algorithm` option: + +```yaml title="router.yaml" +telemetry: + apollo: + signature_normalization_algorithm: enhanced # Default is legacy +``` + +Once you enable this configuration, operations with enhanced signatures might appear with different operation IDs than they did previously in GraphOS Studio. + +##### Input types + +Enhanced signatures include input object type shapes, while still redacting any actual values. +Legacy signatures [replace input object type with `{}`](/graphos/metrics/operation-signatures/#1-transform-in-line-argument-values). + +Given the following example operation: + +```graphql showLineNumbers=false +query InlineInputTypeQuery { + inputTypeQuery( + input: { + inputString: "foo" + inputInt: 42 + inputBoolean: null + nestedType: { someFloat: 4.2 } + enumInput: SOME_VALUE_1 + nestedTypeList: [{ someFloat: 4.2, someNullableFloat: null }] + listInput: [1, 2, 3] + } + ) { + enumResponse + } +} +``` + +The legacy normalization algorithm generates the following signature: + +```graphql showLineNumbers=false +query InlineInputTypeQuery { + inputTypeQuery(input: {}) { + enumResponse + } +} +``` + +The enhanced normalization algorithm generates the following signature: + +```graphql {3-11} showLineNumbers=false +query InlineInputTypeQuery { + inputTypeQuery( + input: { + inputString: "" + inputInt: 0 + inputBoolean: null + nestedType: { someFloat: 0 } + enumInput: SOME_VALUE_1 + nestedTypeList: [{ someFloat: 0, someNullableFloat: null }] + listInput: [] + } + ) { + enumResponse + } +} +``` + +##### Aliases + +Enhanced signatures include any field aliases used in an operation. +Legacy signatures [remove aliases completely](/graphos/metrics/operation-signatures/#field-aliases), meaning the signature may be invalid if the same field was used with multiple aliases. + +Given the following example operation: + +```graphql showLineNumbers=false +query AliasedQuery { + noInputQuery { + interfaceAlias1: interfaceResponse { + sharedField + } + interfaceAlias2: interfaceResponse { + ... on InterfaceImplementation1 { + implementation1Field + } + ... on InterfaceImplementation2 { + implementation2Field + } + } + inputFieldAlias1: objectTypeWithInputField(boolInput: true) { + stringField + } + inputFieldAlias2: objectTypeWithInputField(boolInput: false) { + intField + } + } +} +``` + +The legacy normalization algorithm generates the following signature: + +```graphql showLineNumbers=false +query AliasedQuery { + noInputQuery { + interfaceResponse { + sharedField + } + interfaceResponse { + ... on InterfaceImplementation1 { + implementation1Field + } + ... on InterfaceImplementation2 { + implementation2Field + } + } + objectTypeWithInputField(boolInput: true) { + stringField + } + objectTypeWithInputField(boolInput: false) { + intField + } + } +} +``` + +The enhanced normalization algorithm generates the following signature: + +```graphql showLineNumbers=false +query AliasedQuery { + noInputQuery { + interfaceAlias1: interfaceResponse { + sharedField + } + interfaceAlias2: interfaceResponse { + ... on InterfaceImplementation1 { + implementation1Field + } + ... on InterfaceImplementation2 { + implementation2Field + } + } + inputFieldAlias1: objectTypeWithInputField(boolInput: true) { + stringField + } + inputFieldAlias2: objectTypeWithInputField(boolInput: false) { + intField + } + } +} +``` + + + +#### Extended reference reporting + + + + + +The router supports extended reference reporting in the following versions: + +- [General availability](/resources/product-launch-stages/#general-availability) in v1.54.0 and later +- [Experimental](/resources/product-launch-stages/#experimental-features) in v1.50.0 to v1.53.0 + + + + + +You can configure the router to report enum and input object references for enhanced insights and operation checks. +Apollo's legacy reference reporting doesn't include data about enum values and input object fields, meaning you can't view enum and input object field usage in GraphOS Studio. +Legacy reporting can also cause [inaccurate operation checks](#enhanced-operation-checks). + +Configure extended reference reporting in `router.yaml` with the `telemetry.apollo.metrics_reference_mode` option like so: + +```yaml title="router.yaml" +telemetry: + apollo: + metrics_reference_mode: extended # Default is legacy +``` + + + +#### Extended error reporting + + + + + + + +The router supports extended error reporting in the following versions: + +- [Preview](/resources/product-launch-stages/#preview) in v2.1.2 and later +- [Experimental](/resources/product-launch-stages/#experimental-features) in v2.0.0 + + + +You can configure the router to report extended error information for improved diagnostics. +Apollo's legacy error reporting doesn't include the service or error code, meaning you can't easily attribute errors to their root cause in GraphOS Studio. + +Configure extended reference reporting in `router.yaml` with the `telemetry.apollo.errors.preview_extended_error_metrics` option like so: + +```yaml title="router.yaml" +telemetry: + apollo: + errors: + preview_extended_error_metrics: enabled # Default is disabled +``` + +[Learn more.](/graphos/routing/graphos-reporting#errors) + +##### Configuration effect timing + +Once you configure extended reference reporting, you can view enum value and input field usage alongside object [field usage in GraphOS Studio](/graphos/metrics/field-usage) for all subsequent operations. + +Configuring extended reference reporting automatically turns on [enhanced operation checks](#enhanced-operation-checks), though you won't see an immediate change in your operations check behavior. + +This delay is because operation checks rely on historical operation data. +To ensure sufficient data to distinguish between genuinely unused values and those simply not reported in legacy data, enhanced checks require some operations with extended reference reporting turned on. + +##### Enhanced operation checks + +Thanks to extended reference reporting, operation checks can more accurately flag issues for changes to enum values and input object fields. See the comparison table below for differences between standard operation checks based on legacy reference reporting and enhanced checks based on extended reference reporting. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Standard Check Behavior
+ (Legacy reference reporting) +
+ Enhanced Check Behavior
+ (Extended reference reporting) +
+ +###### Enum value removal + + Removing any enum values is considered a breaking change if any operations use the enum.Removing enum values is only a breaking change if historical operations use the specific enum value(s) that were removed.
+ +###### Default argument changes for input object fields + + + Changing or removing a default argument is generally considered a breaking change, but changing or removing default values for input object fields isn't. + + Changing or removing default values for input object fields is considered a breaking change. + +You can [configure checks to ignore default values changes](/graphos/platform/schema-management/checks#ignored-conditions-settings). + +
+ +###### Nullable input object field removal + + Removing a nullable input object field is always considered a breaking change.Removing a nullable input object field is only considered a breaking change if the nullable field is present in historical operations. If the nullable field is always omitted in historical operations, its removal isn't considered a breaking change.
+ +###### Changing nullable input object fields to non-nullable + + Changing a nullable input object field to non-nullable is considered a breaking change.Changing a nullable input object field to non-nullable is only considered a breaking change if the field had a null value in historical operations. If the field was always a non-null value in historical operations, changing it to non-nullable isn't considered a breaking change.
+ + + +You won't see an immediate change in checks behavior when you first turn on extended reference reporting. +[Learn more.](#configuration-effect-timing) + + + +--- + + + +Learn more in [TLS for the router](/graphos/routing/security/tls). + +--- + + + +Learn more in [Traffic Shaping](/graphos/routing/performance/traffic-shaping). + +--- + +## YAML configuration utilities + +### Variable expansion + +You can reference variables directly in your YAML config file. This is useful for referencing secrets without including them in the file. + +Currently, the router supports expansion of environment variables and file paths. Corresponding variables are prefixed with `env.` and `file.`, respectively. + +The router uses Unix-style expansion. Here are some examples: + +- `${env.ENV_VAR_NAME}` expands to the value of environment variable `ENV_VAR_NAME`. +- `${env.ENV_VAR_NAME:-some_default}` expands to the value of environment variable `ENV_VAR_NAME`, or falls back to the value `some_default` if the environment variable is not defined. +- `${file.a.txt}` expands to the contents of the file `a.txt`. +- `${file.a.txt:-some_default}` expands to the contents of the file `a.txt`, or falls back to the value `some_default` if the file does not exist. + +Variable expansions are valid only for YAML _values_, not keys. + + +### Reusing configurations with YAML aliases + +You can reuse parts of your configuration file in multiple places using standard YAML aliasing syntax: + +```yaml title="router.yaml" +headers: + subgraphs: + products: + request: + - insert: &insert_custom_header + name: "custom-header" + value: "something" + reviews: + request: + - insert: *insert_custom_header +``` + +Here, the `name` and `value` entries under `&insert_custom_header` are reused under `*insert_custom_header`. + +## Related topics + +- [Checklist for configuring the router for production](/technotes/TN0008-production-readiness-checklist/#apollo-router) \ No newline at end of file diff --git a/docs/source/routing/customization/coprocessor.mdx b/docs/source/routing/customization/coprocessor.mdx index e860f7753e..b9f8f5ede4 100644 --- a/docs/source/routing/customization/coprocessor.mdx +++ b/docs/source/routing/customization/coprocessor.mdx @@ -141,7 +141,7 @@ By default, the context is not sent to the coprocessor (`context: false`). You can send _all_ context keys to your coprocessor using `context: all`. You can also specify exactly which context keys you wish to send to a coprocessor by listing them under the `selective` key. This will reduce the size of the request/response and may improve performance. -If you're upgrading from router 1.x, the [context key names changed](/docs/graphos/routing/upgrade/from-router-v1#renamed-context-keys) in router v2.0. You can specify `context: deprecated` to send all context with the old names, compatible with v1.x. Context keys are translated to their v1.x names before being sent to the coprocessor, and translated back to the v2.x names after being received from the coprocessor. +If you're upgrading from router 1.x, the [context key names changed](/graphos/routing/upgrade/from-router-v1#renamed-context-keys) in router v2.0. You can specify `context: deprecated` to send all context with the old names, compatible with v1.x. Context keys are translated to their v1.x names before being sent to the coprocessor, and translated back to the v2.x names after being received from the coprocessor. diff --git a/docs/source/routing/customization/coprocessor/index.mdx b/docs/source/routing/customization/coprocessor/index.mdx new file mode 100644 index 0000000000..72907186b7 --- /dev/null +++ b/docs/source/routing/customization/coprocessor/index.mdx @@ -0,0 +1,472 @@ +--- +title: External Coprocessing +subtitle: Customize your router's behavior in any language +description: Customize the Apollo GraphOS Router with external coprocessing. Write standalone code in any language, hook into request lifecycle, and modify request/response details. +--- + +import CoprocTypicalConfig from "../../../../shared/coproc-typical-config.mdx"; + + + +With **external coprocessing**, you can hook into the GraphOS Router's request-handling lifecycle by writing standalone code in any language and framework. This code (i.e., your **coprocessor**) can run anywhere on your network that's accessible to the router over HTTP. + +You can configure your router to "call out" to your coprocessor at different **stages** throughout the request-handling lifecycle, enabling you to perform custom logic based on a client request's headers, query string, and other details. This logic can access disk and perform network requests, all while safely isolated from the critical router process. + +When your coprocessor responds to these requests, its response body can modify [various details](#responding-to-coprocessor-requests) of the client's request or response. You can even [terminate a client request](#terminating-a-client-request). + +**Recommended locations for hosting your coprocessor include:** + +- On the same host as your router (minimal request latency) +- In the same Pod as your router, as a "sidecar" container (minimal request latency) +- In the same availability zone as your router (low request latency with increased deployment isolation) + +## How it works + +Whenever your router receives a client request, at various **stages** in the [request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle) it can send HTTP POST requests to your coprocessor: + +```mermaid +flowchart TB; + client(Client); + coprocessing(Coprocessor); + subgraph " " + routerService("RouterService"); + supergraphService("SupergraphService"); + executionService("ExecutionService"); + subgraphService[["SubgraphService(s)"]]; + end; + subgraphs[[Subgraphs]]; + client --"1. Sends request"--> routerService; + routerService <-."2. Can send request
details to coprocessor
and receive modifications".-> coprocessing; + routerService --"3"--> supergraphService; + supergraphService <-."4. Can send request
details to coprocessor
and receive modifications".-> coprocessing; + supergraphService --"5"--> executionService; + executionService <-."6. Can send request
details to coprocessor
and receive modifications".-> coprocessing; + executionService --"7"--> subgraphService; + subgraphService <-."8. Can send request
details to coprocessor
and receive modifications".-> coprocessing; + subgraphService -- "9"--> subgraphs; + + class client,subgraphs,coprocessing secondary; +``` + +This diagram shows request execution proceeding "down" from a client, through the router, to individual subgraphs. Execution then proceeds back "up" to the client in the reverse order. + +As shown in the diagram above, the `RouterService`, `SupergraphService`, `ExecutionService`, and `SubgraphService` steps of the [request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle) can send these POST requests (also called **coprocessor requests**). + +Each supported service can send its coprocessor requests at two different **stages**: + +- As execution proceeds "down" from the client to individual subgraphs + - Here, the coprocessor can inspect and modify details of requests before GraphQL operations are processed. + - The coprocessor can also instruct the router to [_terminate_ a client request](#terminating-a-client-request) immediately. +- As execution proceeds back "up" from subgraphs to the client + - Here, the coprocessor can inspect and modify details of the router's response to the client. + +At _every_ stage, the router waits for your coprocessor's response before it continues processing the corresponding request. Because of this, you should maximize responsiveness by configuring _only_ whichever coprocessor requests your customization requires. + +### Multiple requests with `SubgraphService` + +If your coprocessor hooks into your router's `SubgraphService`, the router sends a separate coprocessor request _for each subgraph request in its query plan._ In other words, if your router needs to query three separate subgraphs to fully resolve a client operation, it sends three separate coprocessor requests. Each coprocessor request includes the [name](#servicename) and [URL](#uri) of the subgraph being queried. + +## Setup + +First, make sure your router is [connected to a GraphOS Enterprise organization](/router/enterprise-features/#enabling-enterprise-features). + +You configure external coprocessing in your router's [YAML config file](/router/configuration/overview/#yaml-config-file), under the `coprocessor` key. + +### Typical configuration + +This example configuration sends commonly used request and response details to your coprocessor (see the comments below for explanations of each field): + + + +### Minimal configuration + +You can confirm that your router can reach your coprocessor by setting this minimal configuration before expanding it as needed: + +```yaml title="router.yaml" +coprocessor: + url: http://127.0.0.1:8081 # Replace with the URL of your coprocessor's HTTP endpoint. + router: + request: + headers: false +``` + +In this case, the `RouterService` only sends a coprocessor request whenever it receives a client request. The coprocessor request body includes _no_ data related to the client request (only "control" data, which is [covered below](#coprocessor-request-format)). + +### Conditions + +You can define [conditions](/router/configuration/telemetry/instrumentation/conditions) for a stage of the request lifecycle that you want to run the coprocessor. You can set coprocessor conditions with [selectors](/router/configuration/telemetry/instrumentation/selectors) based on headers or context entries. + + + +The `Execution` stage doesn't support coprocessor conditions. + + + +Example configurations: + +- Run during the `SupergraphResponse` stage only for the first event of a supergraph response. Useful for handling only the first subscription event when a subscription is opened: + +```yaml title="router.yaml" +coprocessor: + url: http://127.0.0.1:3000 + supergraph: + response: + condition: + eq: + - true + - is_primary_response: true # Will be true only for the first event received on a supergraph response (like classical queries and mutations for example) + body: true + headers: true +``` + +- Run during the `Request` stage only if the request contains a request header: + +```yaml title="router.yaml" +coprocessor: + url: http://127.0.0.1:3000 + router: + request: + condition: + eq: + - request_header: should-execute-copro # Header name + - "enabled" # Header value + body: true + headers: true +``` + +### Context configuration + +The router request context is used to share data across stages of the request pipeline. The coprocessor can also use this context. +By default, the context is not sent to the coprocessor (`context: false`). +You can send _all_ context keys to your coprocessor using `context: all`. +You can also specify exactly which context keys you wish to send to a coprocessor by listing them under the `selective` key. This will reduce the size of the request/response and may improve performance. + +If you're upgrading from router 1.x, the [context key names changed](/docs/graphos/routing/upgrade/from-router-v1#renamed-context-keys) in router v2.0. You can specify `context: deprecated` to send all context with the old names, compatible with v1.x. Context keys are translated to their v1.x names before being sent to the coprocessor, and translated back to the v2.x names after being received from the coprocessor. + + + +`context: true` from router 1.x is still supported by the configuration, and is an alias for `context: deprecated`. +We strongly recommend using `context: deprecated` or `context: all` instead. + + + +Example: + +```yaml title="router.yaml" +coprocessor: + url: http://127.0.0.1:3000 # mandatory URL which is the address of the coprocessor + router: + request: + context: false # Do not send any context entries + supergraph: + request: + headers: true + context: # It will only send these 2 context keys to your coprocessor + selective: + - apollo::supergraph::operation_name + - apollo::demand_control::actual_cost + body: true + response: + headers: true + context: all # It will send all context keys with new names (2.x version) + body: true + subgraph: + all: + request: + context: deprecated # It will send all the context keys with deprecated names (1.x version) +``` + + + +If you use the `selective` configuration, you must use the new context key names from v2.x. It does not support the `deprecated` keys from v1.x. So for example, if you try to specify `operation_name` instead of `apollo::supergraph::operation_name`, it won't map to the new context key. + + + +### Client configuration + + + +For example, to enable h2c (http2 cleartext) communication with a coprocessor you can use this configuration: + +```yaml title="router.yaml" +coprocessor: + url: http://127.0.0.1:8081 + # Using an HTTP (not HTTPS) URL and experimental_http2: http2only results in connections that use h2c + client: + experimental_http2: http2only +``` + +## Coprocessor request format + +The router communicates with your coprocessor via HTTP POST requests (called **coprocessor requests**). The body of each coprocessor request is a JSON object with properties that describe either the current client request or the current router response. + + + +**Body properties vary by the router's current execution stage.** [See example request bodies for each stage.](#example-requests-by-stage) + + + +Properties of the JSON body are divided into two high-level categories: + +- "Control" properties + - These provide information about the context of the specific router request or response. They provide a mechanism to influence the router's execution flow. + - The router always includes these properties in coprocessor requests. +- Data properties + - These provide information about the substance of a request or response, such as the GraphQL query string and any HTTP headers. Aside from `sdl`, your coprocessor can modify all of these properties. + - You [configure which of these fields](#setup) the router includes in its coprocessor requests. By default, the router includes _none_ of them. + +To learn more about coprocessor requests, go to: +- [Reference of request properties](/graphos/routing/customization/coprocessor/reference#properties) +- [Example requests by stage](/graphos/routing/customization/coprocessor/reference#example-requests-by-stage) + +## Responding to coprocessor requests + +The router expects your coprocessor to respond with a `200` status code and a JSON body that matches the structure of the [request body](#example-requests-by-stage). + +In the response body, your coprocessor can return _modified values_ for certain properties. By doing so, you can modify the remainder of the router's execution for the client request. + +The router supports modifying the following properties from your coprocessor: + +- [`control`](#control) + - Modify this property to immediately [terminate a client request](#terminating-a-client-request). +- [`body`](#body) +- [`headers`](#headers) +- [`context`](#context) + + + +**Do not** modify other [control properties](#property-reference). Doing so can cause the client request to fail. + + + +If you omit a property from your response body entirely, the router uses its existing value for that property. + +### Terminating a client request + +Every coprocessor request body includes a `control` property with the string value `continue`. If your coprocessor's response body _also_ sets `control` to `continue`, the router continues processing the client request as usual. + +Alternatively, your coprocessor's response body can set `control` to an _object_ with a `break` property, like so: + +```json +{ + "control": { "break": 401 }, //highlight-line + "body": { + "errors": [ + { + "message": "Not authenticated.", + "extensions": { + "code": "ERR_UNAUTHENTICATED" + } + } + ] + } +} +``` + +If the router receives an object with this format for `control`, it immediately terminates the request-handling lifecycle for the client request. It sends an HTTP response to the client with the following details: + +- The HTTP status code is set to the value of the `break` property (`401` in the example above). +- The response body is the coprocessor's returned value for `body`. + - The value of `body` should adhere to the standard GraphQL JSON response format (see the example above). + - Alternatively, you can specify a string value for `body`. If you do, the router returns an error response with that string as the error's `message`. + +The example response above sets the HTTP status code to `400`, which indicates a failed request. + +You can _also_ use this mechanism to immediately return a _successful_ response: + +```json +{ + "control": { "break": 200 }, + "body": { + "data": { + "currentUser": { + "name": "Ada Lovelace" + } + } + } +} +``` + + + +If you return a successful response, make sure the structure of the `data` property matches the structure expected by the client query. + + + + + +The `body` in the `RouterRequest` and `RouterResponse` stages is always a string, but you can still `break` with a GraphQL response if it's encoded as JSON. + + + + + +```json +{ + "control": { "break": 500 }, + "body": "{ \"errors\": [ { \"message\": \"Something went wrong\", \"extensions\": { \"code\": \"INTERNAL_SERVER_ERRROR\" } } ] }" +} +``` + +```json +{ + "control": { "break": 200 }, + "body": "{ \"data\": { \"currentUser\": { \"name\": \"Ada Lovelace\" } }" +} +``` + + + + + +If you return a successful response, make sure the structure of the `data` property matches the structure expected by the client query. + + + +### Failed responses + +If a request to a coprocessor results in a **failed response**, which is seperate from a **control break**, the router will return an error to the client making the supergraph request. The router considers all of the following scenarios to be a **failed response** from your coprocessor: + +- Your coprocessor doesn't respond within the amount of time specified by the `timeout` key in your [configuration](#typical-configuration) (default one second). +- Your coprocessor responds with a non-`2xx` HTTP code. +- Your coprocessor's response body doesn't match the JSON structure of the corresponding [request body](#example-requests-by-stage). +- Your coprocessor's response body sets different values for [control properties](#property-reference) that must not change, such as `stage` and `version`. + +## Handling deferred query responses + +GraphOS Router and Apollo Router Core support the incremental delivery of query response data via [the `@defer` directive](/router/executing-operations/defer-support/): + +```mermaid +sequenceDiagram + Client->>Router: Sends a query that
defers some fields + Note over Router: Resolves non-deferred
fields + Router->>Client: Returns data for
non-deferred fields + Note over Router: Resolves deferred
fields + Router->>Client: Returns data for
deferred fields +``` + +For a single query with deferred fields, your router sends multiple "chunks" of response data to the client. If you enable coprocessor requests for the `RouterResponse` stage, your router sends a separate coprocessor request for _each chunk_ it returns as part of a deferred query. + +**Note the following about handling deferred response chunks:** + +- The [`status_code`](#status_code) and [`headers`](#headers) fields are included only in the coprocessor request for any response's _first_ chunk. These values can't change after the first chunk is returned to the client, so they're subsequently omitted. + +- If your coprocessor modifes the response [`body`](#body) for a response chunk, it must provide the new value as a _string_, _not_ as an object. This is because response chunk bodies include multipart boundary information in addition to the actual serialized JSON response data. [See examples.](#examples-of-deferred-response-chunks) + + - Many responses will not contain deferred streams and for these the body string can usually be fairly reliably transformed into a JSON object for easy manipulation within the coprocessor. Coprocessors should be carefully coded to allow for the presence of a body that is not a valid JSON object. + +- Because the data is a JSON string at both `RouterRequest` and `RouterResponse`, it's entirely possible for a coprocessor to rewrite the body from invalid JSON content into valid JSON content. This is one of the primary use cases for `RouterRequest` body processing. + +### Examples of deferred response chunks + +The examples below illustrate the differences between the _first_ chunk of a deferred response and all subsequent chunks: + +#### First response chunk + +The first response chunk includes `headers` and `statusCode` fields: + +```json +{ + "version": 1, + "stage": "RouterResponse", + "id": "8dee7fe947273640a5c2c7e1da90208c", + "sdl": "...", // String omitted due to length + // highlight-start + "headers": { + "content-type": ["multipart/mixed;boundary=\"graphql\";deferSpec=20220824"], + "vary": ["origin"] + }, + // highlight-end + "body": "\r\n--graphql\r\ncontent-type: application/json\r\n\r\n{\"data\":{\"me\":{\"id\":\"1\"}},\"hasNext\":true}\r\n--graphql\r\n", + "context": { + "entries": { + "apollo::supergraph::operation_kind": "query", + "apollo::telemetry::client_version": "", + "apollo::telemetry::client_name": "manual" + } + }, + "statusCode": 200 //highlight-line +} +``` + +#### Subsequent response chunk + +Subsequent response chunks omit the `headers` and `statusCode` fields: + +```json +{ + "version": 1, + "stage": "RouterResponse", + "id": "8dee7fe947273640a5c2c7e1da90208c", + "sdl": "...", // String omitted due to length + "body": "content-type: application/json\r\n\r\n{\"hasNext\":false,\"incremental\":[{\"data\":{\"name\":\"Ada Lovelace\"},\"path\":[\"me\"]}]}\r\n--graphql--\r\n", + "context": { + "entries": { + "apollo::supergraph::operation_kind": "query", + "apollo::telemetry::client_version": "", + "apollo::telemetry::client_name": "manual" + } + } +} +``` + +## Adding authorization claims via coprocessor + +To use the [authorization directives](/router/configuration/authorization#authorization-directives), a request needs to include **claims**—the details of its authentication and scope. The most straightforward way to add claims is with [JWT authentication](/router/configuration/./authn-jwt). You can also add claims with a [`RouterService` or `SupergraphService` coprocessor](#how-it-works) since they hook into the request lifecycle before the router applies authorization logic. + +An example configuration of the router calling a coprocessor for authorization claims: + +```yaml title="router.yaml" +coprocessor: + url: http://127.0.0.1:8081 # Required. Replace with the URL of your coprocessor's HTTP endpoint. + router: # By including this key, a coprocessor can hook into the `RouterService`. You can also use `SupergraphService` for authorization. + request: # By including this key, the `RouterService` sends a coprocessor request whenever it first receives a client request. + headers: false # These boolean properties indicate which request data to include in the coprocessor request. All are optional and false by default. + context: all # The authorization directives works with claims stored in the request's context +``` + +This configuration prompts the router to send an HTTP POST request to your coprocessor whenever it receives a client request. For example, your coprocessor may receive a request with this format: + +```json +{ + "version": 1, + "stage": "RouterRequest", + "control": "continue", + "id": "d0a8245df0efe8aa38a80dba1147fb2e", + "context": { + "entries": { + "accepts-json": true + } + } +} +``` + +When your coprocessor receives this request from the router, it should add claims to the request's [`context`](#context) and return them in the response to the router. Specifically, the coprocessor should add an entry with a claims object. The key must be `apollo::authentication::jwt_claims`, and the value should be the claims required by the authorization directives you intend to use. For example, if you want to use [`@requireScopes`](/router/configuration/authorization#requiresscopes), the response may look something like this: + +```json +{ + "version": 1, + "stage": "RouterRequest", + "control": "continue", + "id": "d0a8245df0efe8aa38a80dba1147fb2e", + "context": { + "entries": { + "accepts-json": true, + "apollo::authentication::jwt_claims": { + "scope": "profile:read profile:write" + } + } + } +} +``` + +## Additional resources + +- See the Apollo Solutions ["Hello World" coprocessor](https://github.com/apollosolutions/example-coprocessor-helloworld) for an example of a coprocessor that simply logs the router's payload. +- See the following Apollo Solutions authorization and authentication examples: + - [External authentication coprocessor example](https://github.com/apollosolutions/example-coprocessor-external-auth) + - [Custom auth coprocessor example](https://github.com/apollosolutions/example-coprocessor-custom-auth-directive) + - [`@policy` coprocessor example](https://github.com/apollosolutions/example-coprocessor-auth-policy) +- Use the Apollo Solutions [router extensibility load testing repository](https://github.com/apollosolutions/router-extensibility-load-testing) to load test coprocessors. + + diff --git a/docs/source/routing/customization/coprocessor/reference.mdx b/docs/source/routing/customization/coprocessor/reference.mdx new file mode 100644 index 0000000000..d5cda41277 --- /dev/null +++ b/docs/source/routing/customization/coprocessor/reference.mdx @@ -0,0 +1,844 @@ +--- +title: Coprocessor Reference +--- + +## Property reference + +Table of coprocessor request properties. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Property / TypeDescription
+ +**Control properties** + +
+ +##### `control` + +`string | object` + + + +Indicates whether the router should continue processing the current client request. In coprocessor request bodies from the router, this value is always the string value `continue`. + +In your coprocessor's response, you can instead return an _object_ with the following format: + +```json +{ "break": 400 } +``` + +If you do this, the router terminates the request-handling lifecycle and immediately responds to the client with the provided HTTP code and response [`body`](#body) you specify. + +For details, see [Terminating a client request](#terminating-a-client-request). + +
+ +##### `id` + +`string` + + + +A unique ID corresponding to the client request associated with this coprocessor request. + +**Do not return a _different_ value for this property.** If you do, the router treats the coprocessor request as if it failed. + +
+ +##### `subgraphRequestId` + +`string` + + + +A unique ID corresponding to the subgraph request associated with this coprocessor request (only available at the `SubgraphRequest` and `SubgraphResponse` stages). + +**Do not return a _different_ value for this property.** If you do, the router treats the coprocessor request as if it failed. + +
+ +##### `stage` + +`string` + + + +Indicates which stage of the router's [request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle) this coprocessor request corresponds to. + +This value is one of the following: + +- `RouterRequest`: The `RouterService` has just received a client request. +- `RouterResponse`: The `RouterService` is about to send response data to a client. +- `SupergraphRequest`: The `SupergraphService` is about to send a GraphQL request. +- `SupergraphResponse`: The `SupergraphService` has just received a GraphQL response. +- `SubgraphRequest`: The `SubgraphService` is about to send a request to a subgraph. +- `SubgraphResponse`: The `SubgraphService` has just received a subgraph response. + +**Do not return a _different_ value for this property.** If you do, the router treats the coprocessor request as if it failed. + +
+ +##### `version` + +`number` + + + +Indicates which version of the coprocessor request protocol the router is using. + +Currently, this value is always `1`. + +**Do not return a _different_ value for this property.** If you do, the router treats the coprocessor request as if it failed. + +
+ +**Data properties** + +
+ +##### `body` + +`string | object` + + + +The body of the corresponding request or response. + +This field is populated when the underlying HTTP method is `POST`. If you are looking for operation data on `GET` requests, that info will be populated in the `path` parameter per the [GraphQL over HTTP spec](https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#get). + +If your coprocessor [returns a _different_ value](#responding-to-coprocessor-requests) for `body`, the router replaces the existing body with that value. This is common when [terminating a client request](#terminating-a-client-request). + +This field's type depends on the coprocessor request's [`stage`](#stage): + +- For `SubgraphService` stages, `body` is a JSON _object_. +- For `SupergraphService` stages, `body` is a JSON _object_. +- For `RouterService` stages, `body` is a JSON _string_. + - This is necessary to support handling [deferred queries](#handling-deferred-query-responses). + - If you modify `body` during the `RouterRequest` stage, the new value must be a valid string serialization of a JSON object. If it isn't, the router detects that the body is malformed and returns an error to the client. + +This field's structure depends on whether the coprocessor request corresponds to a request, a standard response, or a response "chunk" for a deferred query: + +- **If a request,** `body` usually contains a `query` property containing the GraphQL query string. +- **If a standard response,** `body` usually contains `data` and/or `errors` properties for the GraphQL operation result. +- **If a response "chunk",** `body` contains `data` for _some_ of the operation fields. + +By default, the `RouterResponse` stage returns _redacted_ errors within the `errors` field. To process subgraph errors manually in your coprocessor, enable [subgraph error inclusion](/router/configuration/subgraph-error-inclusion). + +
+ +##### `context` + +`object` + + + +An object representing the router's shared context for the corresponding client request. + +If your coprocessor [returns a _different_ value](#responding-to-coprocessor-requests) for `context`, the router replaces the existing context with that value. + +
+ +##### `hasNext` + +`bool` + + + +When `stage` is `SupergraphResponse`, if present and `true` then there will be subsequent `SupergraphResponse` calls to the co-processor for each multi-part (`@defer`/subscriptions) response. + +
+ +##### `headers` + +`object` + + + +An object mapping of all HTTP header names and values for the corresponding request or response. + +Ensure headers are handled like HTTP headers in general. For example, normalize header case before your coprocessor operates on them. + +If your coprocessor [returns a _different_ value](#responding-to-coprocessor-requests) for `headers`, the router replaces the existing headers with that value. + +> The router discards any `content-length` headers sent by coprocessors because incorrect `content-length` values can lead to HTTP request failures. + +
+ +##### `method` + +`string` + + + +The HTTP method that is used by the request. + +
+ +##### `path` + +`string` + + + +The `RouterService` or `SupergraphService` path that this coprocessor request pertains to. + +
+ +##### `sdl` + +`string` + + + +A string representation of the router's current supergraph schema. + +This value can be very large, so you should avoid including it in coprocessor requests if possible. + +The router ignores modifications to this value. + +
+ +##### `serviceName` + +`string` + + + +The name of the subgraph that this coprocessor request pertains to. + +This value is present only for coprocessor requests from the router's `SubgraphService`. + +**Do not return a _different_ value for this property.** If you do, the router treats the coprocessor request as if it failed. + +
+ +##### `statusCode` + +`number` + + + +The HTTP status code returned with a response. + +
+ +##### `uri` + +`string` + + + +When `stage` is `SubgraphRequest`, this is the full URI of the subgraph the router will query. + +
+ +##### `query_plan` + +`string` + + + +When `stage` is `ExecutionRequest`, this contains the query plan for the client query. It cannot be modified by the coprocessor. + +
+ +## Example requests by stage + +### `RouterRequest` + + + +```json title="Example coprocessor request body" +{ + // Control properties + "version": 1, + "stage": "RouterRequest", + "control": "continue", + "id": "1b19c05fdafc521016df33148ad63c1b", + + // Data properties + "headers": { + "cookie": [ + "tasty_cookie=strawberry" + ], + "content-type": [ + "application/json" + ], + "host": [ + "127.0.0.1:4000" + ], + "apollo-federation-include-trace": [ + "ftv1" + ], + "apollographql-client-name": [ + "manual" + ], + "accept": [ + "*/*" + ], + "user-agent": [ + "curl/7.79.1" + ], + "content-length": [ + "46" + ] + }, + "body": "{ + \"query\": \"query GetActiveUser {\n me {\n name\n}\n}\" + }", + "context": { + "entries": { + "accepts-json": false, + "accepts-wildcard": true, + "accepts-multipart": false + } + }, + "sdl": "...", // String omitted due to length + "path": "/", + "method": "POST" +} +``` + + + +### `RouterResponse` + + + +```json +{ + // Control properties + "version": 1, + "stage": "RouterResponse", + "control": "continue", + "id": "1b19c05fdafc521016df33148ad63c1b", + + // Data properties + "headers": { + "vary": [ + "origin" + ], + "content-type": [ + "application/json" + ] + }, + "body": "{ + \"data\": { + \"me\": { + \"name\": \"Ada Lovelace\" + } + } + }", + "context": { + "entries": { + "apollo_telemetry::subgraph_metrics_attributes": {}, + "accepts-json": false, + "accepts-multipart": false, + "apollo::telemetry::client_name": "manual", + "apollo_telemetry::usage_reporting": { + "statsReportKey": "# Long\nquery Long{me{name}}", + "referencedFieldsByType": { + "User": { + "fieldNames": [ + "name" + ], + "isInterface": false + }, + "Query": { + "fieldNames": [ + "me" + ], + "isInterface": false + } + } + }, + "apollo::telemetry::client_version": "", + "accepts-wildcard": true + } + }, + "statusCode": 200, + "sdl": "..." // Omitted due to length +} +``` + + + +### `SupergraphRequest` + + + +```json +{ + // Control properties + "version": 1, + "stage": "SupergraphRequest", + "control": "continue", + + // Data properties + "headers": { + "cookie": ["tasty_cookie=strawberry"], + "content-type": ["application/json"], + "host": ["127.0.0.1:4000"], + "apollo-federation-include-trace": ["ftv1"], + "apollographql-client-name": ["manual"], + "accept": ["*/*"], + "user-agent": ["curl/7.79.1"], + "content-length": ["46"] + }, + "body": { + "query": "query Long {\n me {\n name\n}\n}", + "operationName": "MyQuery", + "variables": {} + }, + "context": { + "entries": { + "accepts-json": false, + "accepts-wildcard": true, + "accepts-multipart": false, + "this-is-a-test-context": 42 + } + }, + "serviceName": "service name shouldn't change", + "uri": "http://thisurihaschanged" +} +``` + + + +### `SupergraphResponse` + + + +```json +{ + // Control properties + "version": 1, + "stage": "SupergraphResponse", + "control": { + "break": 200 + }, + + // Data properties + "body": { + "errors": [{ "message": "my error message" }] + }, + "context": { + "entries": { + "testKey": true + } + }, + "headers": { + "aheader": ["a value"] + } +} +``` + + + +#### `ExecutionRequest` + + + +```json +{ + // Control properties + "version": 1, + "stage": "ExecutionRequest", + "control": "continue", + + // Data properties + "headers": { + "cookie": ["tasty_cookie=strawberry"], + "content-type": ["application/json"], + "host": ["127.0.0.1:4000"], + "apollo-federation-include-trace": ["ftv1"], + "apollographql-client-name": ["manual"], + "accept": ["*/*"], + "user-agent": ["curl/7.79.1"], + "content-length": ["46"] + }, + "body": { + "query": "query Long {\n me {\n name\n}\n}", + "operationName": "MyQuery" + }, + "context": { + "entries": { + "accepts-json": false, + "accepts-wildcard": true, + "accepts-multipart": false, + "this-is-a-test-context": 42 + } + }, + "serviceName": "service name shouldn't change", + "uri": "http://thisurihaschanged", + "queryPlan": { + "usage_reporting": { + "statsReportKey": "# Me\nquery Me{me{name username}}", + "referencedFieldsByType": { + "User": { "fieldNames": ["name", "username"], "isInterface": false }, + "Query": { "fieldNames": ["me"], "isInterface": false } + } + }, + "root": { + "kind": "Fetch", + "serviceName": "accounts", + "variableUsages": [], + "operation": "query Me__accounts__0{me{name username}}", + "operationName": "Me__accounts__0", + "operationKind": "query", + "id": null, + "inputRewrites": null, + "outputRewrites": null, + "authorization": { + "is_authenticated": false, + "scopes": [], + "policies": [] + } + }, + "formatted_query_plan": "QueryPlan {\n Fetch(service: \"accounts\") {\n {\n me {\n name\n username\n }\n }\n },\n}", + "query": { + "string": "query Me {\n me {\n name\n username\n }\n}\n", + "fragments": { "map": {} }, + "operations": [ + { + "name": "Me", + "kind": "query", + "type_name": "Query", + "selection_set": [ + { + "Field": { + "name": "me", + "alias": null, + "selection_set": [ + { + "Field": { + "name": "name", + "alias": null, + "selection_set": null, + "field_type": { "Named": "String" }, + "include_skip": { "include": "Yes", "skip": "No" } + } + }, + { + "Field": { + "name": "username", + "alias": null, + "selection_set": null, + "field_type": { "Named": "String" }, + "include_skip": { "include": "Yes", "skip": "No" } + } + } + ], + "field_type": { "Named": "User" }, + "include_skip": { "include": "Yes", "skip": "No" } + } + } + ], + "variables": {} + } + ], + "subselections": {}, + "unauthorized": { + "paths": [], + "errors": { "log": true, "response": "errors" } + }, + "filtered_query": null, + "defer_stats": { + "has_defer": false, + "has_unconditional_defer": false, + "conditional_defer_variable_names": [] + }, + "is_original": true + } + } +} +``` + + + +### `ExecutionResponse` + + + +```json +{ + // Control properties + "version": 1, + "stage": "ExecutionResponse", + "control": { + "break": 200 + }, + + // Data properties + "body": { + "errors": [{ "message": "my error message" }] + }, + "context": { + "entries": { + "testKey": true + } + }, + "headers": { + "aheader": ["a value"] + } +} +``` + + + +#### `SubgraphRequest` + + + +```json +{ + // Control properties + "version": 1, + "stage": "SubgraphRequest", + "control": "continue", + "id": "666d677225c1bc6d7c54a52b409dbd4e", + "subgraphRequestId": "b5964998b2394b64a864ef802fb5a4b3", + + // Data properties + "headers": {}, + "body": { + "query": "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{body id}}}}", + "operationName": "TopProducts__reviews__1", + "variables": { + "representations": [ + { + "__typename": "Product", + "upc": "1" + }, + { + "__typename": "Product", + "upc": "2" + }, + { + "__typename": "Product", + "upc": "3" + } + ] + } + }, + "context": { + "entries": { + "apollo_telemetry::usage_reporting": { + "statsReportKey": "# TopProducts\nquery TopProducts{topProducts{name price reviews{body id}}}", + "referencedFieldsByType": { + "Query": { + "fieldNames": ["topProducts"], + "isInterface": false + }, + "Review": { + "fieldNames": ["body", "id"], + "isInterface": false + }, + "Product": { + "fieldNames": ["price", "name", "reviews"], + "isInterface": false + } + } + }, + "apollo::telemetry::client_version": "", + "apollo_telemetry::subgraph_metrics_attributes": {}, + "apollo::telemetry::client_name": "" + } + }, + "uri": "https://reviews.demo.starstuff.dev/", + "method": "POST", + "serviceName": "reviews" +} +``` + + + +### `SubgraphResponse` + + + +```json +{ + // Control properties + "version": 1, + "stage": "SubgraphResponse", + "id": "b7810c6f7f95640fd6c6c8781e3953c0", + "subgraphRequestId": "b5964998b2394b64a864ef802fb5a4b3", + "control": "continue", + + // Data properties + "headers": { + "etag": ["W/\"d3-7aayASjs0+e2c/TpiAYgEu/yyo0\""], + "via": ["2 fly.io"], + "server": ["Fly/90d459b3 (2023-03-07)"], + "date": ["Thu, 09 Mar 2023 14:28:46 GMT"], + "x-powered-by": ["Express"], + "x-ratelimit-limit": ["10000000"], + "access-control-allow-origin": ["*"], + "x-ratelimit-remaining": ["9999478"], + "content-type": ["application/json; charset=utf-8"], + "fly-request-id": ["01GV3CCG5EM3ZNVZD2GH0B00E2-lhr"], + "x-ratelimit-reset": ["1678374007"] + }, + "body": { + "data": { + "_entities": [ + { + "reviews": [ + { + "body": "Love it!", + "id": "1" + }, + { + "body": "Prefer something else.", + "id": "4" + } + ] + }, + { + "reviews": [ + { + "body": "Too expensive.", + "id": "2" + } + ] + }, + { + "reviews": [ + { + "body": "Could be better.", + "id": "3" + } + ] + } + ] + } + }, + "context": { + "entries": { + "apollo_telemetry::usage_reporting": { + "statsReportKey": "# TopProducts\nquery TopProducts{topProducts{name price reviews{body id}}}", + "referencedFieldsByType": { + "Product": { + "fieldNames": ["price", "name", "reviews"], + "isInterface": false + }, + "Query": { + "fieldNames": ["topProducts"], + "isInterface": false + }, + "Review": { + "fieldNames": ["body", "id"], + "isInterface": false + } + } + }, + "apollo::telemetry::client_version": "", + "apollo_telemetry::subgraph_metrics_attributes": {}, + "apollo::telemetry::client_name": "" + } + }, + "serviceName": "reviews", + "statusCode": 200 +} +``` + + diff --git a/docs/source/routing/customization/rhai.mdx b/docs/source/routing/customization/rhai/index.mdx similarity index 100% rename from docs/source/routing/customization/rhai.mdx rename to docs/source/routing/customization/rhai/index.mdx diff --git a/docs/source/routing/customization/rhai-reference.mdx b/docs/source/routing/customization/rhai/reference.mdx similarity index 99% rename from docs/source/routing/customization/rhai-reference.mdx rename to docs/source/routing/customization/rhai/reference.mdx index 028551c14f..7fda1085f1 100644 --- a/docs/source/routing/customization/rhai-reference.mdx +++ b/docs/source/routing/customization/rhai/reference.mdx @@ -2,6 +2,9 @@ title: Rhai Script API Reference subtitle: APIs for router customizations description: This reference documents the symbols and behaviors that are specific to Rhai customizations for the Apollo GraphOS Router and Apollo Router Core. Includes entry point hooks, logging, and more. +redirectFrom: + - /graphos/routing/customization/rhai-reference + --- This reference documents the symbols and behaviors that are specific to [Rhai customizations](/graphos/routing/customization/rhai/) for the GraphOS Router and Apollo Router Core. diff --git a/docs/source/routing/federation-version-support.mdx b/docs/source/routing/federation-version-support.mdx index 6c4bc9d9df..a9960e5bc1 100644 --- a/docs/source/routing/federation-version-support.mdx +++ b/docs/source/routing/federation-version-support.mdx @@ -428,4 +428,4 @@ Only Apollo Router Core and GraphOS Router v1.59 and earlier support Federation - Router v1.60 and later - Router v2.0 and later -[Learn how to upgrade from Federation version 1 to 2.](/graphos/reference/migration/to-federation-version-2) +[Learn how to upgrade from Federation version 1 to 2.](/graphos/schema-design/federated-schemas/reference/moving-to-federation-2) diff --git a/docs/source/routing/get-started.mdx b/docs/source/routing/get-started.mdx new file mode 100644 index 0000000000..db08692800 --- /dev/null +++ b/docs/source/routing/get-started.mdx @@ -0,0 +1,317 @@ +--- +title: Apollo Router Quickstart +subtitle: Run the router locally +description: This quickstart tutorial walks you through installing an Apollo Router binary, running it with an example supergraph schema and a YAML configuration file, and making test queries with Apollo Sandbox. +redirectFrom: + - /graphos/routing/self-hosted/install +--- + +import ElasticNotice from "../../shared/elastic-notice.mdx"; + +Hello! Let's run Apollo Router for the first time, using the simple scenario of developing locally. + +In this guide, you will: + +- Download and run the router as a binary. +- Create a supergraph schema. +- Create a router YAML configuration file. +- Run the router in development mode. +- Make a query to the running router. + +## 1. Download the router + +Let's start by downloading and running the router locally. + +1. Download the latest version of the router binary with a single command line: + + ```bash showLineNumbers=false + curl -sSL https://router.apollo.dev/download/nix/latest | sh + ``` + + + + To download and install a specific version of router, set the version in the download URL path. + + For example, to download router v2.0.0: + + ```bash showLineNumbers=false + curl -sSL https://router.apollo.dev/download/nix/v2.0.0 | sh + ``` + + + + Optionally, go to [router releases](https://github.com/apollographql/router/releases) in GitHub to download and extract a bundle. + +1. Check that your router downloaded successfully by running the `router` binary from your project's root directory: + + ```bash showLineNumbers=false + ./router --version + ``` + + +## 2. Create a supergraph schema + +A router needs a schema for the federated graph, or _supergraph_, that it's orchestrating. This guide uses an example supergraph schema, which you download and provide to the router. + +The example supergraph schema is composed of four subgraphs: `accounts`, `inventory`, `products`, and `reviews`. It outlines the types (`Query`, `Mutation`, `Product`, `Review`, `User`) and their fields, and it specifies which subgraph is responsible for resolving each piece of data using Apollo Federation directives (`@join__*`, `@link`). + +1. From your project's root directory, run the following to download and save an example supergraph schema: + + ```bash showLineNumbers=false + curl -sSL https://supergraph.demo.starstuff.dev/ > supergraph.graphql + ``` + + + +```graphql title="supergraph.graphql" +schema + @link(url: "https://specs.apollo.dev/link/v1.0") + @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) { + query: Query + mutation: Mutation +} + +directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE + +directive @join__field( + graph: join__Graph + requires: join__FieldSet + provides: join__FieldSet + type: String + external: Boolean + override: String + usedOverridden: Boolean +) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION + +directive @join__graph(name: String!, url: String!) on ENUM_VALUE + +directive @join__implements( + graph: join__Graph! + interface: String! +) repeatable on OBJECT | INTERFACE + +directive @join__type( + graph: join__Graph! + key: join__FieldSet + extension: Boolean! = false + resolvable: Boolean! = true + isInterfaceObject: Boolean! = false +) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR + +directive @join__unionMember( + graph: join__Graph! + member: String! +) repeatable on UNION + +directive @link( + url: String + as: String + for: link__Purpose + import: [link__Import] +) repeatable on SCHEMA + +scalar join__FieldSet + +enum join__Graph { + ACCOUNTS + @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev/") + INVENTORY + @join__graph( + name: "inventory" + url: "https://inventory.demo.starstuff.dev/" + ) + PRODUCTS + @join__graph(name: "products", url: "https://products.demo.starstuff.dev/") + REVIEWS + @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev/") +} + +scalar link__Import + +enum link__Purpose { + """ + `SECURITY` features provide metadata necessary to securely resolve fields. + """ + SECURITY + + """ + `EXECUTION` features provide metadata necessary for operation execution. + """ + EXECUTION +} + +type Mutation @join__type(graph: PRODUCTS) @join__type(graph: REVIEWS) { + createProduct(upc: ID!, name: String): Product @join__field(graph: PRODUCTS) + createReview(upc: ID!, id: ID!, body: String): Review + @join__field(graph: REVIEWS) +} + +type Product + @join__type(graph: ACCOUNTS, key: "upc", extension: true) + @join__type(graph: INVENTORY, key: "upc") + @join__type(graph: PRODUCTS, key: "upc") + @join__type(graph: REVIEWS, key: "upc") { + upc: String! + weight: Int + @join__field(graph: INVENTORY, external: true) + @join__field(graph: PRODUCTS) + price: Int + @join__field(graph: INVENTORY, external: true) + @join__field(graph: PRODUCTS) + inStock: Boolean @join__field(graph: INVENTORY) + shippingEstimate: Int @join__field(graph: INVENTORY, requires: "price weight") + name: String @join__field(graph: PRODUCTS) + reviews: [Review] @join__field(graph: REVIEWS) + reviewsForAuthor(authorID: ID!): [Review] @join__field(graph: REVIEWS) +} + +type Query + @join__type(graph: ACCOUNTS) + @join__type(graph: INVENTORY) + @join__type(graph: PRODUCTS) + @join__type(graph: REVIEWS) { + me: User @join__field(graph: ACCOUNTS) + recommendedProducts: [Product] @join__field(graph: ACCOUNTS) + topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCTS) +} + +type Review @join__type(graph: REVIEWS, key: "id") { + id: ID! + body: String + author: User @join__field(graph: REVIEWS, provides: "username") + product: Product +} + +type User + @join__type(graph: ACCOUNTS, key: "id") + @join__type(graph: REVIEWS, key: "id") { + id: ID! + name: String @join__field(graph: ACCOUNTS) + username: String + @join__field(graph: ACCOUNTS) + @join__field(graph: REVIEWS, external: true) + reviews: [Review] @join__field(graph: REVIEWS) +} +``` + + + +## 3. Create a router config + +The router's many features are configurable via a YAML configuration file. You set your options declaratively in YAML, then point your router to it at startup. + +Let's customize a common setting: the router's _supergraph listen address_. It's the network address and port on which the router receives client requests. By default the address is `127.0.0.1:4000`. As an exercise, let's change the port to `5555`. + +1. In your same working directory, create a file named `router.yaml`. Open it for editing. +1. Add the following configuration that sets `supergraph.listen` to `127.0.0.1:5555`: + + ```yaml title="router.yaml" + supergraph: + listen: 127.0.0.1:5555 + ``` + +## 4. Run the router + + +Let's run the router in dev mode, using both the supergraph schema and YAML configuration files you created: + +1. Run the router with these command-line options: + - `--dev` enables dev mode + - `--config` provides the path to your YAML configuration file + - `--supergraph` provides the path to your supergraph schema + + ```sh showLineNumbers=false + ./router --dev --config router.yaml --supergraph supergraph.graphql + ``` + + + + Running router with `--dev` is the same as using the following configuration: + + ```yaml title="Same configuration as --dev" + sandbox: + enabled: true + homepage: + enabled: false + supergraph: + introspection: true + include_subgraph_errors: + all: true + plugins: + # Enable with the header, Apollo-Expose-Query-Plan: true + experimental.expose_query_plan: true + ``` + + [Learn more](/graphos/routing/configuration/cli#development-mode) about router dev mode. + + + +1. Check that your router is running, with output similar to the example: + + + + ```sh showLineNumbers=false disableCopy=true + 2025-04-25T21:54:05.910202Z INFO Running with *development* mode settings which facilitate development experience (e.g., introspection enabled) + 2025-04-25T21:54:05.981114Z INFO Apollo Router v2.1.3 // (c) Apollo Graph, Inc. // Licensed as ELv2 (https://go.apollo.dev/elv2) + 2025-04-25T21:54:05.981141Z INFO Anonymous usage data is gathered to inform Apollo product development. See https://go.apollo.dev/o/privacy for details. + 2025-04-25T21:54:05.985764Z INFO state machine transitioned event="UpdateLicense(Unlicensed)" state=Startup previous_state="Startup" + 2025-04-25T21:54:05.987948Z INFO state machine transitioned event="UpdateConfiguration()" state=Startup previous_state="Startup" + 2025-04-25T21:54:05.988144Z INFO state machine transitioned event="NoMoreLicense" state=Startup previous_state="Startup" + 2025-04-25T21:54:06.010232Z INFO Health check exposed at http://127.0.0.1:8088/health + 2025-04-25T21:54:06.010717Z WARN Connector debugging is enabled, this may expose sensitive information. + 2025-04-25T21:54:06.405064Z INFO GraphQL endpoint exposed at http://127.0.0.1:5555/ 🚀 + 2025-04-25T21:54:06.405628Z INFO You're using some "experimental" features of the Apollo Router (those which have their configuration prefixed by "experimental_"). + We may make breaking changes in future releases. To help us design the stable version we need your feedback. + Here is a list of links where you can give your opinion: + + - experimental_response_trace_id: https://github.com/apollographql/router/discussions/2147 + + For more information about launch stages, please see the documentation here: https://www.apollographql.com/docs/resources/product-launch-stages/ + 2025-04-25T21:54:06.406568Z INFO state machine transitioned event="UpdateSchema()" state=Running previous_state="Startup" + 2025-04-25T21:54:06.406591Z INFO state machine transitioned event="NoMoreConfiguration" state=Running previous_state="Running" + ``` + + + +## 5. Make a query + +When the router runs in dev mode, it hosts an [Apollo Sandbox](/graphos/explorer/sandbox/) automatically. Sandbox has a browser-based IDE, Explorer, that you can use to write and send real GraphQL queries to your graph. + + +1. Go to the URL your router is running at, [`http://127.0.0.1:5555`](http://127.0.0.1:5555). Sandbox should be running there. + +1. Copy and paste the example query into the **Operation** pane of Explorer: + + ```graphql + query Query { + recommendedProducts { + inStock + name + price + reviews { + author { + name + } + } + } + } + ``` + +1. Click **Query** to run the query, then check for its response in the **Response** pane. + + Apollo Sandbox IDE showing successful query and response at the end of the router quickstart + +That's it! You've successfully sent a query to a router running a development graph and received a response. + + +## Next steps + +Now that you've run the router locally, explore more about deployment and configuration: + +- Deploy the router [in your own infrastructure](/graphos/routing/self-hosted) with containers and/or Helm. +- [Configure runtime features](/router/configuration/overview) of the router. diff --git a/docs/source/routing/graphos-features.mdx b/docs/source/routing/graphos-features.mdx index 7162508059..0a54ac5bf0 100644 --- a/docs/source/routing/graphos-features.mdx +++ b/docs/source/routing/graphos-features.mdx @@ -1,16 +1,16 @@ --- -title: GraphOS Router Features -subtitle: Use router features enabled by GraphOS plans +title: Licensed GraphOS Router Features +subtitle: Features that requiring a licensed GraphOS plan description: Unlock Enterprise features for the GraphOS Router by connecting it to Apollo GraphOS. redirectFrom: - /router/enterprise-features --- -A router connected to GraphOS, whether cloud-hosted or self-hosted, is called a **GraphOS Router**. It has access to specific GraphOS features depending on the connected GraphOS organization's plan. Refer to the [pricing page](https://www.apollographql.com/pricing#graphos-router) to compare GraphOS Router features across plan types. +This page lists the additional features of GraphOS Router that are enabled via integration with a licensed GraphOS plan. -## GraphOS Router features +> Refer to the [pricing page](https://www.apollographql.com/pricing) to compare GraphOS Router features across plan types. -The GraphOS Router supports a collection of premium features specific to GraphOS. These features include: +## GraphOS Router licensed features - Real-time updates via [GraphQL subscriptions](/graphos/routing/operations/subscriptions) - Improved performance with [query batching](/graphos/routing/performance/query-batching) @@ -25,163 +25,13 @@ The GraphOS Router supports a collection of premium features specific to GraphOS - An [offline license](/graphos/reference/router/graphos-features#the-enterprise-license) that enables running the router with GraphOS features when disconnected from the internet. - [Using contexts to share data](/graphos/schema-design/federated-schemas/entities/use-contexts) with the `@context` and `@fromContext` directives -For details on these features, see [this blog post](https://blog.apollographql.com/apollo-router-v1-12-improved-router-security-performance-and-extensibility) in addition to the documentation links above. +## Enabling licensed plan features -### Enabling plan-specific features - -To enable support for plan-specific features in GraphOS Router: +To enable licensed plan features in a router: - You must run GraphOS Router v1.12 or later. [Download the latest version.](/graphos/reference/router/self-hosted-install#1-download-and-extract-the-router-binary) - Certain features might require a later router version. See a particular feature's documentation for details. - Your router instances must connect to GraphOS with a **graph API key** and **graph ref** associated with your organization. - You connect your router to GraphOS by setting [these environment variables](/graphos/reference/router/configuration#environment-variables) when starting the router. - - If your router _already_ connects to your GraphOS organization, no further action is required. - -### The GraphOS license - -Whenever your router instance starts up and connects to GraphOS, it fetches a **license**, which is the credential that authorizes its use of GraphOS features: - -```mermaid -flowchart LR; - subgraph "Your Infrastructure"; - router(["GraphOS Router"]); - end; - subgraph "GraphOS"; - uplink(Apollo Uplink) - end; - router--"Fetches supergraph schema
and license"-->uplink; -``` - -A router instance retains its license for the duration of its execution. If you stop a router instance and then later start a new instance on the same machine, it must fetch a new license. - -Licenses are served via [Apollo Uplink](/graphos/routing/uplink), the same multi-cloud endpoint that your router uses to fetch its supergraph schema from GraphOS. Because of this, licenses introduce no additional network dependencies, meaning your router's uptime remains unaffected. To learn more about multi-cloud Uplink, read the [Apollo blog post](https://www.apollographql.com/blog/announcement/backend/introducing-multi-cloud-support-for-apollo-uplink). - -A router instance's license is valid for the duration of your organization's current subscription billing period (plus a [grace period](#grace-period-for-expired-plans)), even if the router temporarily becomes disconnected from GraphOS. - - - -### Offline license - - - - - -Offline license support is available on an as-needed basis to Enterprise organizations. Send a request to your Apollo contact to enable it for your GraphOS Studio organization. - - - -Running your GraphOS Router fleet while fully connected to GraphOS is the best choice for most Apollo users. However, some scenarios can prevent your routers from connecting to GraphOS for an extended period, ranging from disasters that break connectivity to isolated sites operating with air-gapped networks. If you need to restart or rapidly scale your entire router fleet, but you're unable to communicate with Apollo Uplink, new router instances won't be able to serve traffic. - -To support long-term disconnection scenarios, GraphOS supports **offline licenses** for the GraphOS Router. An offline license enables routers to start and serve traffic without a persistent connection to GraphOS. Instead of fetching its supergraph schema from Apollo Uplink, an offline router gets its supergraph schema from a local supergraph schema file. - - - -You can use the GraphOS [schema delivery pipeline](/graphos/platform/schema-management#schema-delivery) for supergraph CI (schema checks, linting, contracts, etc.) in an online environment to manage the local supergraph schema file provided to your offline router. - - - -An offline license can be retrieved from GraphOS with the [`rover license fetch`](/rover/commands/license) command. - -With an offline license, a router can either be fully disconnected from GraphOS or configured to connect to GraphOS on a best-effort basis so that it can send graph usage metrics. Apollo recommends configuring your router to report graph usage metrics to GraphOS whenever possible. Since your router sends metrics in a best-effort fashion, it incurs no performance or uptime penalties while enabling several powerful GraphOS features, such as operation checks, field insights, operation traces, and contracts. - - - -A router using an offline license requires [the use of local manifests](/graphos/routing/security/persisted-queries#local_manifests) when using [safelisting with persisted queries](/graphos/routing/security/persisted-queries), otherwise it will not work as designed when the router is disconnected from Uplink. - - - -An offline license is valid for the lesser of the duration of your contract with Apollo, or one year, with an added grace period of 28 days. You are responsible for keeping your offline license files up to date within your infrastructure by rerunning `rover license fetch` to fetch updated license files. - -#### Set up offline license for the GraphOS Router - -Follow these steps to configure an GraphOS Router to use an offline license: - -1. Fetch an offline license by running [`rover license fetch`](/rover/commands/license/#license-fetch) with the ID of the graph from which you want to fetch a license: - - ```bash - rover license fetch --graph-id - ``` - -1. Provide the offline license to your router on startup. The router accepts an offline license in a few ways: - - 1. [`--license `](/graphos/reference/router/configuration#--license) CLI option, with an argument containing an absolute or relative path to an offline license file - 1. [`APOLLO_ROUTER_LICENSE_PATH`](/graphos/reference/router/configuration#--license) environment variable, containing an absolute or relative path to an offline license file - 1. [`APOLLO_ROUTER_LICENSE`](/graphos/reference/router/configuration#--license) environment variable, containing the stringified contents of an offline license file - - - - - The router checks the CLI option and environment variables in the listed order, then it uses the value of the first option or variable that is set. - - The `--license ` option is only available when running the router binary. When running a router with `rover dev`, you must use environment variables to provide your offline license. - - - -1. Configure the router to use a local supergraph schema by setting one of the following: - - * [`--s/-supergraph`](/graphos/reference/router/configuration#-s----supergraph) CLI option, with an argument containing an absolute or relative path to supergraph schema file - * [`APOLLO_SUPERGRAPH_PATH`](/graphos/reference/router/configuration#-s----supergraph) environment variable, containing an absolute or relative path to supergraph schema file - * [`APOLLO_SUPERGRAPH_URLS`](/graphos/reference/router/configuration#-s----supergraph) environment variable, containing URLs to supergraph schemas - -1. (**Recommended**) Configure the router to report usage metrics to GraphOS in a best-effort basis by setting both the [`APOLLO_KEY`](/graphos/reference/router/configuration#apollo_key) and [`APOLLO_GRAPH_REF`](/graphos/reference/router/configuration#apollo_graph_ref) environment variables. - - These metrics are necessary for several important GraphOS features (operations checks, field insights, operation traces, contracts). Sending them best-effort incurs no performance or uptime penalties. - -### Licenses with local development - -You might also need to run an GraphOS Router instance on your local machine, such as with the [`rover dev`](/graphos/graphs/local-development) command. It's likely that your local router instance doesn't connect to GraphOS to get its supergraph schema from Uplink. For example, you can run `rover dev` to perform composition locally. - -**You _can_ use GraphOS Router features with a locally composed supergraph schema!** To do so, your router must still connect to GraphOS to obtain its [license](#the-graphos-license). - -#### Set up local development - -These steps work both for running the router executable directly (`./router`) and for running it via `rover dev`: - -1. [Create a new variant](/graphos/graphs/federated-graphs/#adding-a-variant-via-the-rover-cli) for your supergraph that you'll use _only_ to fetch GraphOS licenses. - - Give the variant a name that clearly distinguishes it from variants that track schemas and metrics. - - Every team member that runs a router locally can use this same variant. - - When you create this variant, publish a dummy subgraph schema like the following (your router won't use it): - - ```graphql - type Query { - hello: String - } - ``` - -2. Create a [graph API key](/graphos/platform/access-management/api-keys#graph-api-keys) for your supergraph and assign it the **Contributor** role. - - We recommend creating a separate graph API key for _each team member_ that will run the router locally. - -3. When you start up your local router with your usual command, set the `APOLLO_GRAPH_REF` and `APOLLO_KEY` environment variables for that command: - - ```bash - APOLLO_GRAPH_REF="..." APOLLO_KEY="..." ./router --supergraph schema.graphql - ``` - - - The value of `APOLLO_GRAPH_REF` is the graph ref for the new, license-specific variant you created (for example, `docs-example-graph@local-licenses`). - - The value of `APOLLO_KEY` is the graph API key you created. - -4. Your router will fetch an GraphOS license while using its locally composed supergraph schema. - -### Common errors - -**If your router doesn't successfully connect to GraphOS,** it logs an error that begins with one of the following strings if any GraphOS features are enabled: - -| Error Message | Description | -|-----------------------------|-------------| -| `Not connected to GraphOS.` | At least one of the `APOLLO_KEY` and `APOLLO_GRAPH_REF` environment variables wasn't set on router startup. | -| `License not found.` | The router connected to GraphOS with credentials that are not associated with a GraphOS plan. | -| `License has expired.` | Your organization's GraphOS subscription has ended. **Your router will stop processing incoming requests at the end of the standard [grace period](#grace-period-for-expired-plans).** | - -## Turning off GraphOS features - -To turn off an GraphOS feature, remove all of its associated configuration keys from your router's [YAML config file](/graphos/reference/router/configuration#yaml-config-file). - -## Grace period for expired plans - -If your organization terminates its GraphOS subscription, your router's license is considered expired at the end of your final paid subscription period. GraphOS provides a grace period for expired licenses so that you can turn off GraphOS features before they produce breaking errors in your router. - -If your router has an expired GraphOS license, its behavior degrades according to the following schedule, _if_ any GraphOS features are still enabled: - -- **For the first 14 days after your license expires,** your router continues to behave as though it has a valid license. -- **After 14 days,** your router begins a **soft outage**: it continues processing client requests, but it emits logs and metrics that indicate it's experiencing an outage. -- **After 28 days,** your router begins a **hard outage**. It no longer processes incoming client requests and continues emitting logs and metrics from the soft outage. -Your router resumes normal functioning whenever you renew your GraphOS subscription or turn off all [GraphOS features](#list-of-features). +> Learn more about the [GraphOS plan license](/graphos/routing/license). diff --git a/docs/source/routing/license.mdx b/docs/source/routing/license.mdx new file mode 100644 index 0000000000..4126cb82ce --- /dev/null +++ b/docs/source/routing/license.mdx @@ -0,0 +1,154 @@ +--- +title: GraphOS Router License +description: Learn how to manage the license for an Apollo GraphOS Router, including offline license configuration. +--- + +## The GraphOS license + +Whenever your instance of GraphOS Router starts up and connects to GraphOS, it fetches a __license__, which is the credential that authorizes its use of GraphOS features: + +A router instance retains its license for the duration of its execution. If you stop a router instance and then later start a new instance on the same machine, it must fetch a new license. + +Licenses are served via [Apollo Uplink](/graphos/routing/uplink), the same multi-cloud endpoint that your router uses to fetch its supergraph schema from GraphOS. Because of this, licenses introduce no additional network dependencies, meaning your router's uptime remains unaffected. To learn more about multi-cloud Uplink, read the [Apollo blog post](https://www.apollographql.com/blog/announcement/backend/introducing-multi-cloud-support-for-apollo-uplink). + + +```mermaid +flowchart LR; + subgraph "Your Infrastructure"; + router(["GraphOS Router"]); + end; + subgraph "GraphOS"; + uplink(Apollo Uplink) + end; + router--"Fetches supergraph schema
and license"-->uplink; +``` + +A router instance's license is valid for the duration of your organization's current subscription billing period (plus a [grace period](#grace-period-for-expired-plans)), even if the router temporarily becomes disconnected from GraphOS. + +## Licenses with local development + +You might also need to run an GraphOS Router instance on your local machine, such as with the [`rover dev`](/graphos/graphs/local-development) command. It's likely that your local router instance doesn't connect to GraphOS to get its supergraph schema from Uplink. For example, you can run `rover dev` to perform composition locally. + +**You _can_ use GraphOS Router features with a locally composed supergraph schema!** To do so, your router must still connect to GraphOS to obtain its [license](#the-graphos-license). + +### Set up local development + +These steps work both for running the router executable directly (`./router`) and for running it via `rover dev`: + +1. [Create a new variant](/graphos/graphs/federated-graphs/#adding-a-variant-via-the-rover-cli) for your supergraph that you'll use _only_ to fetch GraphOS licenses. + - Give the variant a name that clearly distinguishes it from variants that track schemas and metrics. + - Every team member that runs a router locally can use this same variant. + - When you create this variant, publish a dummy subgraph schema like the following (your router won't use it): + + ```graphql + type Query { + hello: String + } + ``` + +2. Create a [graph API key](/graphos/platform/access-management/api-keys#graph-api-keys) for your supergraph and assign it the __Contributor__ role. + - We recommend creating a separate graph API key for _each team member_ that will run the router locally. + +3. When you start up your local router with your usual command, set the `APOLLO_GRAPH_REF` and `APOLLO_KEY` environment variables for that command: + + ```bash + APOLLO_GRAPH_REF="..." APOLLO_KEY="..." ./router --supergraph schema.graphql + ``` + + - The value of `APOLLO_GRAPH_REF` is the graph ref for the new, license-specific variant you created (for example, `docs-example-graph@local-licenses`). + - The value of `APOLLO_KEY` is the graph API key you created. + +4. Your router will fetch an GraphOS license while using its locally composed supergraph schema. + + + +## Offline license + + + + + +Offline license support is available on an as-needed basis to Enterprise organizations. Send a request to your Apollo contact to enable it for your GraphOS Studio organization. + + + +Running your GraphOS Router fleet while fully connected to GraphOS is the best choice for most Apollo users. However, some scenarios can prevent your routers from connecting to GraphOS for an extended period, ranging from disasters that break connectivity to isolated sites operating with air-gapped networks. If you need to restart or rapidly scale your entire router fleet, but you're unable to communicate with Apollo Uplink, new router instances won't be able to serve traffic. + +To support long-term disconnection scenarios, GraphOS supports __offline licenses__ for the GraphOS Router. An offline license enables routers to start and serve traffic without a persistent connection to GraphOS. Instead of fetching its supergraph schema from Apollo Uplink, an offline router gets its supergraph schema from a local supergraph schema file. + + + +You can use the GraphOS [schema delivery pipeline](/graphos/platform/schema-management#schema-delivery) for supergraph CI (schema checks, linting, contracts, etc.) in an online environment to manage the local supergraph schema file provided to your offline router. + + + +An offline license can be retrieved from GraphOS with the [`rover license fetch`](/rover/commands/license) command. + +With an offline license, a router can either be fully disconnected from GraphOS or configured to connect to GraphOS on a best-effort basis so that it can send graph usage metrics. Apollo recommends configuring your router to report graph usage metrics to GraphOS whenever possible. Since your router sends metrics in a best-effort fashion, it incurs no performance or uptime penalties while enabling several powerful GraphOS features, such as operation checks, field insights, operation traces, and contracts. + + + +A router using an offline license requires [the use of local manifests](/graphos/routing/security/persisted-queries#local_manifests) when using [safelisting with persisted queries](/graphos/routing/security/persisted-queries), otherwise it will not work as designed when the router is disconnected from Uplink. + + + +An offline license is valid for the lesser of the duration of your contract with Apollo, or one year, with an added grace period of 28 days. You are responsible for keeping your offline license files up to date within your infrastructure by rerunning `rover license fetch` to fetch updated license files. + +### Set up offline license for the GraphOS Router + +Follow these steps to configure an GraphOS Router to use an offline license: + +1. Fetch an offline license by running [`rover license fetch`](/rover/commands/license/#license-fetch) with the ID of the graph from which you want to fetch a license: + + ```bash + rover license fetch --graph-id + ``` + +1. Provide the offline license to your router on startup. The router accepts an offline license in a few ways: + + 1. [`--license `](/graphos/reference/router/configuration#--license) CLI option, with an argument containing an absolute or relative path to an offline license file + 1. [`APOLLO_ROUTER_LICENSE_PATH`](/graphos/reference/router/configuration#--license) environment variable, containing an absolute or relative path to an offline license file + 1. [`APOLLO_ROUTER_LICENSE`](/graphos/reference/router/configuration#--license) environment variable, containing the stringified contents of an offline license file + + + + - The router checks the CLI option and environment variables in the listed order, then it uses the value of the first option or variable that is set. + - The `--license ` option is only available when running the router binary. When running a router with `rover dev`, you must use environment variables to provide your offline license. + + + +1. Configure the router to use a local supergraph schema by setting one of the following: + + * [`--s/-supergraph`](/graphos/reference/router/configuration#-s----supergraph) CLI option, with an argument containing an absolute or relative path to supergraph schema file + * [`APOLLO_SUPERGRAPH_PATH`](/graphos/reference/router/configuration#-s----supergraph) environment variable, containing an absolute or relative path to supergraph schema file + * [`APOLLO_SUPERGRAPH_URLS`](/graphos/reference/router/configuration#-s----supergraph) environment variable, containing URLs to supergraph schemas + +1. (**Recommended**) Configure the router to report usage metrics to GraphOS in a best-effort basis by setting both the [`APOLLO_KEY`](/graphos/reference/router/configuration#apollo_key) and [`APOLLO_GRAPH_REF`](/graphos/reference/router/configuration#apollo_graph_ref) environment variables. + + These metrics are necessary for several important GraphOS features (operations checks, field insights, operation traces, contracts). Sending them best-effort incurs no performance or uptime penalties. + +## Troubleshooting + +**If your router doesn't successfully connect to GraphOS,** it logs an error that begins with one of the following strings if any GraphOS features are enabled: + +| Error Message | Description | +|-----------------------------|-------------| +| `Not connected to GraphOS.` | At least one of the `APOLLO_KEY` and `APOLLO_GRAPH_REF` environment variables wasn't set on router startup. | +| `License not found.` | The router connected to GraphOS with credentials that are not associated with a GraphOS plan. | +| `License has expired.` | Your organization's GraphOS subscription has ended. **Your router will stop processing incoming requests at the end of the standard [grace period](#grace-period-for-expired-plans).** | + +## Turning off GraphOS features + +To turn off an GraphOS feature, remove all of its associated configuration keys from your router's [YAML config file](/graphos/reference/router/configuration#yaml-config-file). + +## Grace period for expired plans + +If your organization terminates its GraphOS subscription, your router's license is considered expired at the end of your final paid subscription period. GraphOS provides a grace period for expired licenses so that you can turn off GraphOS features before they produce breaking errors in your router. + +If your router has an expired GraphOS license, its behavior degrades according to the following schedule, _if_ any GraphOS features are still enabled: + +- **For the first 14 days after your license expires,** your router continues to behave as though it has a valid license. +- **After 14 days,** your router begins a **soft outage**: it continues processing client requests, but it emits logs and metrics that indicate it's experiencing an outage. +- **After 28 days,** your router begins a **hard outage**. It no longer processes incoming client requests and continues emitting logs and metrics from the soft outage. + +Your router resumes normal functioning whenever you renew your GraphOS subscription or turn off all [GraphOS features](#list-of-features). diff --git a/docs/source/routing/observability/telemetry/trace-exporters/datadog.mdx b/docs/source/routing/observability/telemetry/trace-exporters/datadog.mdx index ac235e190f..032a1e5ff1 100644 --- a/docs/source/routing/observability/telemetry/trace-exporters/datadog.mdx +++ b/docs/source/routing/observability/telemetry/trace-exporters/datadog.mdx @@ -9,7 +9,7 @@ context: import BatchProcessorPreamble from '../../../../../shared/batch-processor-preamble.mdx'; import BatchProcessorRef from '../../../../../shared/batch-processor-ref.mdx'; -This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/trace-exporters/otlp) to use with [Datadog](https://www.datadoghq.com/). +This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/telemetry/trace-exporters/otlp) to use with [Datadog](https://www.datadoghq.com/). For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). diff --git a/docs/source/routing/observability/telemetry/trace-exporters/dynatrace.mdx b/docs/source/routing/observability/telemetry/trace-exporters/dynatrace.mdx index 9c0fbf98e1..0cc9cedfea 100644 --- a/docs/source/routing/observability/telemetry/trace-exporters/dynatrace.mdx +++ b/docs/source/routing/observability/telemetry/trace-exporters/dynatrace.mdx @@ -6,7 +6,7 @@ context: - telemetry --- -This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/trace-exporters/otlp) to use with [Dynatrace](https://dynatrace.com/). +This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/telemetry/trace-exporters/otlp) to use with [Dynatrace](https://dynatrace.com/). For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). diff --git a/docs/source/routing/observability/telemetry/trace-exporters/jaeger.mdx b/docs/source/routing/observability/telemetry/trace-exporters/jaeger.mdx index 9d1be7bd04..014b2a8f62 100644 --- a/docs/source/routing/observability/telemetry/trace-exporters/jaeger.mdx +++ b/docs/source/routing/observability/telemetry/trace-exporters/jaeger.mdx @@ -6,7 +6,7 @@ context: - telemetry --- -This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/trace-exporters/otlp) to use with [Jaeger](https://www.jaegertracing.io/). +This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/telemetry/trace-exporters/otlp) to use with [Jaeger](https://www.jaegertracing.io/). For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). diff --git a/docs/source/routing/observability/telemetry/trace-exporters/new-relic.mdx b/docs/source/routing/observability/telemetry/trace-exporters/new-relic.mdx index 5297edacf2..346e363ab1 100644 --- a/docs/source/routing/observability/telemetry/trace-exporters/new-relic.mdx +++ b/docs/source/routing/observability/telemetry/trace-exporters/new-relic.mdx @@ -6,7 +6,7 @@ context: - telemetry --- -This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/trace-exporters/otlp) to use with [New Relic](https://newrelic.com/). +This tracing exporter is a configuration of the [OTLP exporter](/graphos/routing/observability/telemetry/trace-exporters/otlp) to use with [New Relic](https://newrelic.com/). For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). diff --git a/docs/source/routing/operations/defer.mdx b/docs/source/routing/operations/defer.mdx index 7a21d412bb..405de6c7a5 100644 --- a/docs/source/routing/operations/defer.mdx +++ b/docs/source/routing/operations/defer.mdx @@ -1,19 +1,17 @@ --- -title: Router Support for @defer +title: "@defer Directive Support" subtitle: Improve performance by delivering fields incrementally description: Improve your GraphQL query performance with GraphOS Router and Apollo Router Core's support for the @defer directive. Incrementally deliver response data by deferring certain fields. minVersion: 1.8.0 --- -Queries sent to GraphOS Router or Apollo Router Core can use the `@defer` directive to enable the incremental delivery of response data. By deferring data for some fields, the router can resolve and return data for the query's _other_ fields more quickly, improving responsiveness. +Apollo Router's support of the `@defer` directive helps client developers tackle the common challenge of how to create a responsive user experience when certain fields of a query take longer to resolve than others. `@defer` improves application performance by delivering response data incrementally. This is important for real-time applications like dashboards or reports. By deferring data for some fields, the router can resolve and return data for the query's other fields more quickly, improving responsiveness. -The router's `@defer` support is compatible with all [federation-compatible subgraph libraries](/federation/building-supergraphs/supported-subgraphs/). That's because the router takes advantage of your supergraph's existing [entities](/federation/entities/) to fetch any deferred field data via followup queries to your subgraphs. - -## What is `@defer`? +## What is the `@defer` directive? The `@defer` directive enables a client query to specify sets of fields that it doesn't need to receive data for _immediately_. This is helpful whenever some fields in a query take much longer to resolve than others. -Deferred fields are always contained within a GraphQL fragment, and the `@defer` directive is applied to that fragment (_not_ to the individual fields). +The `@defer` directive is applied to a GraphQL query. Specifically, deferred fields are always contained within a GraphQL fragment, and the `@defer` directive is applied to that fragment. Here's an example query that uses `@defer`: @@ -33,7 +31,8 @@ query GetTopProducts { To respond incrementally, the router uses a multipart-encoded HTTP response. To use `@defer` successfully with the router, a client's GraphQL library must _also_ support the directive by handling multipart HTTP responses correctly. -The router's `@defer` support is compatible with all [federation-compatible subgraph libraries](/federation/building-supergraphs/supported-subgraphs/), because the deferring logic exists entirely within the router itself. +The router's `@defer` support is compatible with all [federation-compatible subgraph libraries](/federation/building-supergraphs/supported-subgraphs/). That's because the router takes advantage of your supergraph's existing [entities](/federation/entities/) to fetch any deferred field data via followup queries to your subgraphs. + ## Which fields can my router defer? @@ -143,7 +142,7 @@ To use `@defer` successfully, your supergraph and its clients must meet the requ - This functionality is currently supported in Apollo Client for [Web](/react/data/defer) and [Kotlin (experimental)](/kotlin/fetching/defer). - Your supergraph must be one of: - A [cloud supergraph](/graphos/routing/cloud#cloud-supergraphs) - - A [self-hosted supergraph](/graphos/routing/self-hosted#self-hosted-supergraphs) running the [GraphOS Router](/graphos/routing/about-router) + - A [self-hosted supergraph](/graphos/routing/self-hosted#self-hosted-supergraphs) running the GraphOS Router ### Entity-specific requirements diff --git a/docs/source/routing/operations/file-upload.mdx b/docs/source/routing/operations/file-upload.mdx index 9170a22a1e..bb45f8ee8e 100644 --- a/docs/source/routing/operations/file-upload.mdx +++ b/docs/source/routing/operations/file-upload.mdx @@ -277,7 +277,7 @@ Each part of the request payload is separated by a boundary string (`gc0p4Jq0M2Y Refer to the docs for your client library for further instructions. - [Apollo Client (web)](/react/data/file-uploads/) -- [Apollo iOS](/ios/file-uploads/) +- [Apollo iOS](/ios/advanced/file-uploads/) - [Apollo Kotlin](/kotlin/advanced/upload/) Custom clients can be implemented following the [spec documentation](https://github.com/jaydenseric/graphql-multipart-request-spec). diff --git a/docs/source/routing/operations/index.mdx b/docs/source/routing/operations/index.mdx deleted file mode 100644 index 96f2310f06..0000000000 --- a/docs/source/routing/operations/index.mdx +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Real-Time Operations -subtitle: Configure the router for real-time operations -description: Configure the Apollo GraphOS Router to support real-time operations, including subscriptions, defer directive, and file uploads. ---- - -Responsive applications rely on the router to handle operations in real time. You can configure to support various real-time operations: - -- [**Subscriptions**](/graphos/routing/operations/subscriptions) - support GraphQL subscription operations -- [**Defer**](/graphos/routing/operations/defer) - use the `@defer` directive to enable incremental delivery of response data -- [**File Uploads**](/graphos/routing/operations/file-upload) - upload files to the router using multipart HTTP requests diff --git a/docs/source/routing/operations/subscriptions/index.mdx b/docs/source/routing/operations/subscriptions/configuration.mdx similarity index 95% rename from docs/source/routing/operations/subscriptions/index.mdx rename to docs/source/routing/operations/subscriptions/configuration.mdx index 00aaa6002e..3462fe0cb1 100644 --- a/docs/source/routing/operations/subscriptions/index.mdx +++ b/docs/source/routing/operations/subscriptions/configuration.mdx @@ -7,48 +7,13 @@ minVersion: 1.22.0 -GraphOS routers provides support for GraphQL subscription operations: - -```graphql -subscription OnStockPricesChanged { - stockPricesChanged { - symbol - price - } -} -``` - -With subscription support enabled, you can add `Subscription` fields to the schema of any subgraph that supports common WebSocket protocols for subscription communication: - -```graphql title="stocks.graphql" -type Subscription { - stockPricesChanged: [Stock!]! -} -``` - -## What are subscriptions for? - - - -## How subscriptions work - - - - - -[Walk through an example.](#example-execution) - - - -### Special considerations - -Whenever your router updates its supergraph schema at runtime, it terminates all active subscriptions. Clients can detect this special-case termination via an error code and execute a new subscription. See [Termination on schema update](#termination-on-schema-update). +Learn how to configure the router to enable GraphQL subscriptions. ## Prerequisites Before you add `Subscription` fields to your subgraphs, do all of the following in the order shown to prevent schema composition errors: -1. Update your router instances to version `1.22.0` or later. [Download the latest version.](/router/quickstart/) +1. Update your router instances to version `1.22.0` or later. [Download the latest version.](/graphos/routing/get-started) - Previous versions of the router don't support subscription operations. 1. Make sure your router is [connected to a GraphOS Enterprise organization](/router/enterprise-features/#enabling-enterprise-features). - Subscription support is an Enterprise feature of self-hosted routers. @@ -387,7 +352,7 @@ Disabling deduplication is useful if you need to create a separate connection to ### Termination on schema update -Whenever your router's supergraph schema is updated, **the router terminates all active subscriptions.** +Whenever your router's supergraph schema is updated, **the router terminates all active subscriptions.** Clients can detect this special-case termination via an error code and execute a new subscription. Your router's supergraph schema is updated in the following cases: diff --git a/docs/source/routing/operations/subscriptions/overview.mdx b/docs/source/routing/operations/subscriptions/overview.mdx new file mode 100644 index 0000000000..b0de64b6a3 --- /dev/null +++ b/docs/source/routing/operations/subscriptions/overview.mdx @@ -0,0 +1,41 @@ +--- +title: Overview of GraphQL Subscription Support +subtitle: Enable clients to receive real-time updates +description: Configure your router to support GraphQL subscriptions, enabling clients to receive real-time updates via WebSocket or HTTP callbacks. +minVersion: 1.22.0 +--- + + + +GraphQL subscriptions enable clients to manage real-time data updates effectively, without the need for constant polling. This is particularly crucial in applications that need live updates, such as notifications, stock tickers, or chat applications. Using subscriptions improves performance and user experience by ensuring that clients receive the latest information as soon as changes occur on the backend. + +```graphql title="Example GraphQL subscription" showLineNumbers=false +subscription OnStockPricesChanged { + stockPricesChanged { + symbol + price + } +} +``` + +The router supports both the callback and multipart protocols for handling subscriptions. With subscription support enabled, you can add `Subscription` fields to the schema of any subgraph that supports common WebSocket protocols for subscription communication: + +```graphql title="stocks.graphql" showLineNumbers=false +type Subscription { + stockPricesChanged: [Stock!]! +} +``` + +## What are subscriptions for? + + + +## How subscriptions work + + + +## Next steps + +- [Configure](/graphos/routing/operations/subscriptions/configuration) the router and update your subgraph schemas to enable and handle subscriptions. + +- Learn about the [callback](/graphos/routing/operations/subscriptions/callback-protocol) and [multipart](/graphos/routing/operations/subscriptions/multipart-protocol) protocols. diff --git a/docs/source/routing/performance/caching/index.mdx b/docs/source/routing/performance/caching/index.mdx index 8a004e82cf..db875be1da 100644 --- a/docs/source/routing/performance/caching/index.mdx +++ b/docs/source/routing/performance/caching/index.mdx @@ -1,16 +1,37 @@ --- -title: Caching -subtitle: Accelerate query retrieval with GraphOS caching. +title: Caching in Apollo Router +subtitle: Accelerate query retrieval with in-memory and distributed caching +description: Accelerate query retrieval for your federated graph with in-memory and distributed caching in Apollo Router. --- -By default, GraphOS Router stores the following data in its in-memory cache to improve performance: +Apollo Router supports multiple caching strategies, including in-memory caching, distributed caching with Redis, and entity caching, that allow you to reduce redundant subgraph requests and improve query latency. + +## In-memory caching + +By default, the router stores in its in-memory cache to improve performance: - Generated query plans - Automatic persisted queries (APQ) - Introspection responses -You can configure certain caching behaviors for generated query plans and APQ (but not introspection responses). For details, see In-memory caching in the Apollo Router. +You can configure certain caching behaviors for generated query plans and APQ (but not introspection responses). For details, see in-memory caching in the Apollo Router. + +Learn more about [in-memory caching](/graphos/routing/performance/caching/in-memory). + +## Distributed caching + + + +You can configure a Redis-backed distributed cache that enables multiple router instances to share cached values. Those instances can share a Redis-backed cache for their query plans and automatic persisted queries (APQ). If any of your router instances caches a particular value, all of your instances can look up that value to significantly improve responsiveness. + +Learn more about [distributed caching](/graphos/routing/performance/caching/distributed). + +## Entity-based caching + + + +Entity caching speeds up graph data retrieval by storing only the necessary data for entities, rather than entire client responses. It's helpful in scenarios where the same data is requested frequently, such as product information systems and user profile services. -If you have a GraphOS Enterprise plan, you can configure a Redis-backed distributed cache that enables multiple router instances to share cached values. For details, see Distributed caching in GraphOS Router. +Using Redis, the router stores subgraph responses and ensures that requests for the same entity from different clients are served from the cache, rather than fetching the data repeatedly from subgraphs. It can cache data at a fine-grained level and provides separate configurations for caching duration (TTL) and other caching behaviors per subgraph. -You can configure a Redis-backed entity cache that enables a client query to retrieve cached entity data split between subgraph responses. For details, see subgraph entity caching in GraphOS Router. +[Learn more about entity-based caching](/graphos/routing/performance/caching/entity). diff --git a/docs/source/routing/query-planning/native-query-planner.mdx b/docs/source/routing/query-planning/native-query-planner.mdx index fb74e744d5..2756b0ca01 100644 --- a/docs/source/routing/query-planning/native-query-planner.mdx +++ b/docs/source/routing/query-planning/native-query-planner.mdx @@ -11,7 +11,7 @@ Learn about the Rust-native query planner in GraphOS Router v2.x ## Background about query planner implementations -In v1.49.0, the router introduced a [query planner](/graphos/routing/about-router#query-planning) implemented natively in Rust. This native query planner improves the overall performance and resource utilization of query planning. It existed alongside the legacy JavaScript implementation that uses the V8 JavaScript engine. +In v1.49.0, the router introduced a query planner implemented natively in Rust. This native query planner improves the overall performance and resource utilization of query planning. It existed alongside the legacy JavaScript implementation that uses the V8 JavaScript engine. As of v1.59.0, the native query planner is the default planner in the router. As a result, the legacy query planner, which was built using Deno and relied on the v8 engine, has been deprecated. diff --git a/docs/source/routing/request-lifecycle.mdx b/docs/source/routing/request-lifecycle.mdx index 867e610233..ba03f7bc71 100644 --- a/docs/source/routing/request-lifecycle.mdx +++ b/docs/source/routing/request-lifecycle.mdx @@ -1,22 +1,21 @@ --- title: Router Request Lifecycle -subtitle: Understand how the router processes client requests -description: Understand how GraphQL client requests get processed by the request lifecycle pipeline of Apollo GraphOS Router. +subtitle: Learn how the router processes client requests +description: Understand how GraphQL client requests get processed through the request lifecycle pipeline of an Apollo Router. --- import RequestLifecycleOverviewDiagram from '../../shared/diagrams/router-request-lifecycle-overview.mdx'; -Every client request made to a GraphOS Router goes through the **router request lifecycle**: a multi-stage pipeline of services that processes requests and returns responses. +Every client request made to an Apollo Router goes through the **router request lifecycle**: a multi-stage pipeline of services that processes requests and returns responses. - +The router processes a client request by first passing it between services along the lifecycle's **request path**. In the request path, it needs to figure out how to use your subgraphs to fetch or update the fields of the request. To do this, the router generates a _query plan_: -Understanding the router request lifecycle makes it easier for you to write router customization plugins or configure router telemetry. +Diagram of a query plan + - - -The router processes a client request by first passing it between services along the lifecycle's **request path**. The request path breaks up a request and sends constituent sub-requests to subgraphs. Then along the lifecycle's **response path**, the router gathers all the responses from the subgraph requests into a client response. +A query plan is a blueprint for dividing a single incoming operation into one or more operations that are each resolvable by a single subgraph. Some of these operations depend on the results of other operations, so the query plan also defines any required ordering for their execution. The router's _query planner_ determines the optimal set of subgraph queries for each client operation, then merges the subgraph responses into a single response for the client. ## Request path diff --git a/docs/source/routing/security/authorization-overview.mdx b/docs/source/routing/security/authorization-overview.mdx new file mode 100644 index 0000000000..a92efb72e4 --- /dev/null +++ b/docs/source/routing/security/authorization-overview.mdx @@ -0,0 +1,108 @@ +--- +title: Overview of Authorization in the GraphOS Router +subtitle: Strengthen subgraph security with a centralized governance layer +description: Enforce authorization in the GraphOS Router with the @requireScopes, @authenticated, and @policy directives. +--- + + + +APIs provide access to business-critical data. Unrestricted access can result in data breaches, monetary losses, or potential denial of service. Even for internal services, checks can be essential to limit data to authorized parties. + +Services may have their own access controls, but enforcing authorization _in the Apollo Router_ is valuable for a few reasons: + +- **Optimal query execution**: Validating authorization _before_ processing requests enables the early termination of unauthorized requests. Stopping unauthorized requests at the edge of your graph reduces the load on your services and enhances performance. + + ```mermaid + flowchart LR; + clients(Client); + subgraph Router[" "] + router(["GraphOS Router"]); + serviceB[Users
API]; + serviceC[Posts
API]; + end + router -.->|"❌ Subquery"| serviceB & serviceC; + clients -->|"⚠️Unauthorized
request"| router; + ``` + + - If every field in a particular subquery requires authorization, the router's [query planner](/router/customizations/overview#request-path) can _eliminate entire subgraph requests_ for unauthorized requests. For example, a request may have permission to view a particular user's posts on a social media platform but not have permission to view any of that user's personally identifiable information (PII). Check out [How it works](/graphos/routing/security/authorization#how-it-works) to learn more. + + ```mermaid + flowchart LR; + clients(Client); + subgraph Router[" "] + router(["GraphOS Router"]); + serviceB[Users
API]; + serviceC[Posts
API]; + end + router -->|"✅ Authorized
subquery"| serviceC; + router -.->|"❌ Unauthorized
subquery"| serviceB; + clients -->|"⚠️ Partially authorized
request"| router; + ``` + + - Also, [query deduplication](/router/configuration/traffic-shaping/#query-deduplication) groups requested fields based on their required authorization. Entire groups can be eliminated from the query plan if they don't have the correct authorization. + +- **Declarative access rules**: You define access controls at the field level, and GraphOS [composes](/graphos/routing/security/authorization#composition-and-federation) them across your services. These rules create graph-native governance without the need for an extra orchestration layer. + +- **Principled architecture**: Through composition, the router centralizes authorization logic while allowing for auditing at the service level. This centralized authorization is an initial checkpoint that other service layers can reinforce. + + ```mermaid + flowchart LR; + clients(Client); + Level2:::padding + subgraph Level1["
🔐 Router layer                                                   "] + router(["GraphOS Router"]); + subgraph Level2["🔐 Service layer"] + serviceB[Users
API]; + serviceC[Posts
API]; + end + end + + router -->|"Subquery"| serviceB & serviceC; + clients -->|"Request"| router; + + classDef padding padding-left:1em, padding-right:1em + ``` + + + +To learn more about why authorization is ideal at the router layer, watch Andrew Carlson's talk at Austin API Summit 2024: [Centralize Data Access Control with GraphQL](https://www.youtube.com/watch?v=ETyAPY4bsYY). + + + + + + + + + +## How access control works + +The GraphOS Router provides access controls via **authorization directives** that define access to specific fields and types across your supergraph: + +- The [`@requiresScopes`](/graphos/routing/security/authorization#requiresscopes) directive allows granular access control through the scopes you define. +- The [`@authenticated`](/graphos/routing/security/authorization#authenticated) directive allows access to the annotated field or type for _authenticated requests only_. +- The [`@policy`](/graphos/routing/security/authorization#policy) directive offloads authorization validation to a [Rhai script](/graphos/routing/customization/rhai/) or a [coprocessor](/router/customizations/coprocessor) and integrates the result in the router. It's useful when your authorization policies go beyond simple authentication and scopes. + +For example, imagine you're building a social media platform that includes a `Users` subgraph. You can use the [`@requiresScopes`](/graphos/routing/security/authorization#requiresscopes) directive to declare that viewing other users' information requires the `read:user` scope: + +```graphql +type Query { + users: [User!]! @requiresScopes(scopes: [["read:users"]]) +} +``` + +You can use the [`@authenticated`](/graphos/routing/security/authorization#authenticated) directive to declare that users must be logged in to update their own information: + +```graphql +type Mutation { + updateUser(input: UpdateUserInput!): User! @authenticated +} +``` + +You can define both directives—together or separately—at the field level to fine-tune your access controls. When directives are declared both on a field and the field's type, they will all be tried, and the field will be removed if any of them does not authorize it. +GraphOS [composes](/graphos/routing/security/authorization#composition-and-federation) restrictions into the supergraph schema so that each subgraph's restrictions are respected. +The router then enforces these directives on all incoming requests. + +## Next steps + +- Learn how to use [authorization directives](/graphos/routing/security/authorization) in your GraphQL schemas to secure access to your graphs. diff --git a/docs/source/routing/security/authorization.mdx b/docs/source/routing/security/authorization.mdx index 055c3fe53e..397df2bb08 100644 --- a/docs/source/routing/security/authorization.mdx +++ b/docs/source/routing/security/authorization.mdx @@ -1,107 +1,12 @@ --- title: Authorization in the GraphOS Router -subtitle: Strengthen subgraph security with a centralized governance layer +subtitle: Enforce authorization with schema directives description: Enforce authorization in the GraphOS Router with the @requireScopes, @authenticated, and @policy directives. --- -APIs provide access to business-critical data. Unrestricted access can result in data breaches, monetary losses, or potential denial of service. Even for internal services, checks can be essential to limit data to authorized parties. - -Services may have their own access controls, but enforcing authorization _in the Apollo Router_ is valuable for a few reasons: - -- **Optimal query execution**: Validating authorization _before_ processing requests enables the early termination of unauthorized requests. Stopping unauthorized requests at the edge of your graph reduces the load on your services and enhances performance. - - ```mermaid - flowchart LR; - clients(Client); - subgraph Router[" "] - router(["GraphOS Router"]); - serviceB[Users
API]; - serviceC[Posts
API]; - end - router -.->|"❌ Subquery"| serviceB & serviceC; - clients -->|"⚠️Unauthorized
request"| router; - ``` - - - If every field in a particular subquery requires authorization, the router's [query planner](/router/customizations/overview#request-path) can _eliminate entire subgraph requests_ for unauthorized requests. For example, a request may have permission to view a particular user's posts on a social media platform but not have permission to view any of that user's personally identifiable information (PII). Check out [How it works](#how-it-works) to learn more. - - ```mermaid - flowchart LR; - clients(Client); - subgraph Router[" "] - router(["GraphOS Router"]); - serviceB[Users
API]; - serviceC[Posts
API]; - end - router -->|"✅ Authorized
subquery"| serviceC; - router -.->|"❌ Unauthorized
subquery"| serviceB; - clients -->|"⚠️ Partially authorized
request"| router; - ``` - - - Also, [query deduplication](/router/configuration/traffic-shaping/#query-deduplication) groups requested fields based on their required authorization. Entire groups can be eliminated from the query plan if they don't have the correct authorization. - -- **Declarative access rules**: You define access controls at the field level, and GraphOS [composes](#composition-and-federation) them across your services. These rules create graph-native governance without the need for an extra orchestration layer. - -- **Principled architecture**: Through composition, the router centralizes authorization logic while allowing for auditing at the service level. This centralized authorization is an initial checkpoint that other service layers can reinforce. - - ```mermaid - flowchart LR; - clients(Client); - Level2:::padding - subgraph Level1["
🔐 Router layer                                                   "] - router(["GraphOS Router"]); - subgraph Level2["🔐 Service layer"] - serviceB[Users
API]; - serviceC[Posts
API]; - end - end - - router -->|"Subquery"| serviceB & serviceC; - clients -->|"Request"| router; - - classDef padding padding-left:1em, padding-right:1em - ``` - - - -To learn more about why authorization is ideal at the router layer, watch Andrew Carlson's talk at Austin API Summit 2024: [Centralize Data Access Control with GraphQL](https://www.youtube.com/watch?v=ETyAPY4bsYY). - - - - - - - - - -## How access control works - -The GraphOS Router provides access controls via **authorization directives** that define access to specific fields and types across your supergraph: - -- The [`@requiresScopes`](#requiresscopes) directive allows granular access control through the scopes you define. -- The [`@authenticated`](#authenticated) directive allows access to the annotated field or type for _authenticated requests only_. -- The [`@policy`](#policy) directive offloads authorization validation to a [Rhai script](/graphos/routing/customization/rhai/) or a [coprocessor](/router/customizations/coprocessor) and integrates the result in the router. It's useful when your authorization policies go beyond simple authentication and scopes. - -For example, imagine you're building a social media platform that includes a `Users` subgraph. You can use the [`@requiresScopes`](#requiresscopes) directive to declare that viewing other users' information requires the `read:user` scope: - -```graphql -type Query { - users: [User!]! @requiresScopes(scopes: [["read:users"]]) -} -``` - -You can use the [`@authenticated`](#authenticated) directive to declare that users must be logged in to update their own information: - -```graphql -type Mutation { - updateUser(input: UpdateUserInput!): User! @authenticated -} -``` - -You can define both directives—together or separately—at the field level to fine-tune your access controls. When directives are declared both on a field and the field's type, they will all be tried, and the field will be removed if any of them does not authorize it. -GraphOS [composes](#composition-and-federation) restrictions into the supergraph schema so that each subgraph's restrictions are respected. -The router then enforces these directives on all incoming requests. +Learn how to secure access to your graph via the router by using authorization directives in your GraphQL schemas. ## Prerequisites diff --git a/docs/source/routing/security/tls.mdx b/docs/source/routing/security/tls.mdx index 97d1af2187..7f21e938a3 100644 --- a/docs/source/routing/security/tls.mdx +++ b/docs/source/routing/security/tls.mdx @@ -7,17 +7,27 @@ redirectFrom: The GraphOS Router supports TLS to authenticate and encrypt communications, both on the client side and the subgraph side. It works automatically on the subgraph side if the subgraph URL starts with `https://`. +```yaml title="Example TLS configuration" +tls: + supergraph: + certificate: ${file./path/to/certificate.pem} + certificate_chain: ${file./path/to/certificate_chain.pem} + key: ${file./path/to/key.pem} +``` + ## Configuring TLS TLS support is configured in the `tls` section, under the `supergraph` key for the client side, and the `subgraph` key for the subgraph side, with configuration possible for all subgraphs and overriding per subgraph. -The list of supported TLS versions and algorithms is static, it cannot be configured. +The list of supported TLS versions and algorithms is static. + +### Supported TLS versions -Supported TLS versions: * TLS 1.2 * TLS 1.3 -Supported cipher suites: +### Supported TLS cipher suites + * TLS13_AES_256_GCM_SHA384 * TLS13_AES_128_GCM_SHA256 * TLS13_CHACHA20_POLY1305_SHA256 @@ -28,14 +38,15 @@ Supported cipher suites: * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -Supported key exchange groups: +### Supported key exchange groups + * X25519 * SECP256R1 * SECP384R1 ## TLS termination -Clients can connect to the router directly over HTTPS, without terminating TLS in an intermediary. You can configure this in the `tls` configuration section: +Clients can connect to the router directly over HTTPS, without terminating TLS in an intermediary. You can configure this in the `tls` configuration section: ```yaml tls: diff --git a/docs/source/routing/self-hosted/containerization/aws.mdx b/docs/source/routing/self-hosted/containerization/aws.mdx new file mode 100644 index 0000000000..9eaad0a49a --- /dev/null +++ b/docs/source/routing/self-hosted/containerization/aws.mdx @@ -0,0 +1,156 @@ +--- +title: Deploying GraphOS Router on AWS +subtitle: Deploy router with Amazon Elastic Container Service (ECS) +description: Build and deploy Apollo Router on Amazon Web Services (AWS) with Amazon Elastic Container Service (ECS) +--- + +Learn how to deploy the router for development on AWS with Elastic Container Service (ECS). + +You will: +- Build a router image with a Dockerfile. +- Set up an Elastic Cloud Registry and push your router image to it. +- Create an ECS task definition for your router and deploy it. + +## Prerequisites + +Before you start: + +1. [Set up a GraphQL API in GraphOS](/graphos/get-started/guides/graphql#step-1-set-up-your-graphql-api). + - Save your `APOLLO_KEY` and `APOLLO_GRAPH_REF`. You'll need them when deploying the router. +1. Install [Docker](https://www.docker.com/get-started/) locally. +1. Set up you [AWS environment](https://aws.amazon.com/getting-started/guides/setup-environment/) + - Install the AWS CLI. + - Use an existing Create an Amazon +1. Choose a version of the router to deploy (for example, `v1.61.0`). You'll need it when specifying the router image to deploy. + +## Build router image + +To deploy your own router, start by customizing and building a router image, using a Dockerfile and a router configuration file: + +1. In a local directory, create a `router.yaml` file and copy-paste the following configuration into the file: + + ```yaml title="router.yaml" + supergraph: + listen: 0.0.0.0:4000 + health_check: + listen: 0.0.0.0:8088 + ``` + + The router's default HTTP and health check endpoint addresses are localhost, so they wouldn't be reachable when deployed. This configuration enables the router to listen to all addresses. + +1. Create a `Dockerfile` file and copy-paste the following into the file: + + ```text showLineNumbers=false + # Use the official Apollo Router Core image as the base. + # Set the image tag to the desired router version (e.g. v1.61.0) + FROM ghcr.io/apollographql/router:v1.61.0 + + # Replace the default router config with the local, customized router.yaml + COPY router.yaml /dist/config/router.yaml + ``` + + The Dockerfile sources the base router image from the GitHub container registry, using the version of router you specify. It then copies your customized `router.yaml` configuration file to overwrite the default router configuration file. + +1. From the same local directory, run the following `docker` CLI command to build a new router image. Choose a name and tag for the image, for example `router-aws:v1.61.0`. + + ```bash showLineNumbers=false + docker buildx build --platform linux/amd64 -t router-aws:v1.61.0 --load . + ``` + + - Because Cloud Run only supports AMD64-based images, the `docker buildx build --platform linux/amd64` command ensures the image is built for AMD64 and is compatible. + - The `--load` option loads the built image to `docker images`. + +1. Run `docker images` and validate that your router image is in the returned list of images. + +## Push router image to registry + +Now that you have a built router image, create a repository in Elastic Cloud Registry (ECR) and push your image to it: + +1. In a local terminal, run the AWS CLI command to create a new ECR repository: + - For `--repository-name`, set a name for your repository (for example, `router-repo`) + - For `--region`, set your AWS region (for example, `us-west-1`) + + ```bash showLineNumbers=false + aws ecr create-repository \ + --repository-name router-repo \ + --region us-west-1 + ``` + +1. In AWS CLI, authenticate your Docker CLI to ECR. + - For `--region`, use your AWS regions (for example, `us-west-1`) + - Use your ECR repository URI, which you can copy from your ECR Repositories Console (for example, `0123456789000.dkr.ecr.us-west-1.amazonaws.com`) + + ```bash showLineNumbers=false + aws ecr get-login-password --region us-west-1 | docker login --username AWS --password-stdin 0123456789000.dkr.ecr.us-west-1.amazonaws.com + ``` + + > To troubleshoot ECR authentication, go to [AWS documentation](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-authenticate-registry). + +1. Run `docker tag` to tag the image before pushing it to ECR. + + ```bash showLineNumbers=false + docker tag router-aws:v1.61.0 0123456789000.dkr.ecr.us-west-1.amazonaws.com/router-repo:v1.61.0 + ``` + +1. Run `docker push` to push the router image to your ECR repository URI, using a tag (e.g., `:v1.61.0`): + + ```bash showLineNumbers=false + docker push 0123456789000.dkr.ecr.us-west-1.amazonaws.com/router-repo:v1.61.0 + ``` + +1. Run `aws ecr list-images` and validate that your image is in the list of images in your ECR repository: + + ```bash showLineNumbers=false + aws ecr list-images --repository-name router-repo + ``` + +## Create and deploy ECS task + +With your image pushed to your ECR repository, in ECS you can define a task for the router and deploy it as a service. + +### Create cluster + +You need an ECS cluster to deploy the router. + +If you don't have a cluster, you can create one with default settings: + +1. In the AWS Console, go to the Amazon ECS Console, then click **Create cluster**. +1. Enter a name for your cluster. +1. Click **Create**. + +### Create task definition + +Create an ECS task definition for your router: + +1. In the AWS ECS Console, go to **Task definitions** from the left navigation panel, then click **Create new task definition** and select **Create new task definition**. +1. Fill in the details for **Container - 1**: + - **Name**: Enter a container name + - **Image URI**: Select the URI of your router image + - **Port mappings**: + - **Container port**: Enter `4000` (must match ) and + - **Port name**: Enter a port name + - **Environment variables**: Enter the environment variables `APOLLO_KEY` and `APOLLO_GRAPH_REF` and set them to your graph API key and graph ref, respectively +1. In `Docker configuration - optional`, enter the command options to configure the router and run it in development mode: + + ```text showLineNumbers=false + --dev, --config, /dist/config/router.yaml + ``` +1. Click **Create**. + +### Deploy router + +Deploy the router in your ECS cluster: + +1. In AWS ECS Console under **Task definitions**, select your defined task, then click **Deploy** and select **Create service**. +1. Fill in the fields for the service: + - **Existing cluster**: Select your cluster + - **Service name**: Enter a name for your service +1. Click **Create** to create the service. ECS will start deploying the service for the router. +1. After AWS finishes deploying, click on the service to go to its page in Console. Check the service logs for messages from the running router. For example: + + ```text title="Example router log message" + {"timestamp":"2025-04-04T17:32:14.928608731Z","level":"INFO","message":"Apollo Router v1.61.0 // (c) Apollo Graph, Inc. // Licensed as ELv2 (https://go.apollo.dev/elv2)","target":"apollo_router::executable","resource":{}} + ``` +1. Go to the service URL and validate the the router's development Sandbox is running successfully. + +Congrats, you've successfully deployed the router! diff --git a/docs/source/routing/self-hosted/containerization/azure.mdx b/docs/source/routing/self-hosted/containerization/azure.mdx new file mode 100644 index 0000000000..97aba854c2 --- /dev/null +++ b/docs/source/routing/self-hosted/containerization/azure.mdx @@ -0,0 +1,157 @@ +--- +title: Deploying GraphOS Router on Azure +subtitle: Deploy router with Azure Container App +description: Build and deploy Apollo GraphOS Router as an Azure Container App +--- + +Learn how to deploy the router for development on Azure as a Container App. + +You will: +- Build a router image with a Dockerfile. +- Set up an Azure Container Registry and push your router image to it. +- Create and deploy an Azure Container App for your router. + +## Prerequisites + +Before you start: + +1. [Set up a GraphQL API in GraphOS](/graphos/get-started/guides/graphql#step-1-set-up-your-graphql-api). + - Save your `APOLLO_KEY` and `APOLLO_GRAPH_REF`. You'll need them when deploying the router. +1. Install [Docker](https://www.docker.com/get-started/) locally. +1. Login to or create an [Azure account](https://azure.microsoft.com/en-us/pricing/purchase-options/azure-account). +1. Install [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). +1. Choose a version of the router to deploy (for example, `v1.61.0`). You'll need it when specifying the router image to deploy. + +## Build router image + +To deploy your own router, start by customizing and building a router image, using a Dockerfile and a router configuration file: + +1. In a local directory, create a `router.yaml` file and copy-paste the following configuration into the file: + + ```yaml title="router.yaml" + supergraph: + listen: 0.0.0.0:4000 + health_check: + listen: 0.0.0.0:8088 + ``` + + The router's default HTTP and health check endpoint addresses are localhost, so they wouldn't be reachable when deployed. This configuration enables the router to listen to all addresses. + +1. Create a `Dockerfile` file and copy-paste the following into the file: + + ```text showLineNumbers=false + # Use the official Apollo Router Core image as the base. + # Set the image tag to the desired router version (e.g. v1.61.0) + FROM ghcr.io/apollographql/router:v1.61.0 + + # Replace the default router config with the local, customized router.yaml + COPY router.yaml /dist/config/router.yaml + ``` + + The Dockerfile sources the base router image from the GitHub container registry, using the version of router you specify. It then copies your customized `router.yaml` configuration file to overwrite the default router configuration file. + +1. From the same local directory, use `docker buildx build` to build a new router image for a specific platform. Choose a name and tag for the image, for example `router:v1.61.0`. + + ```bash showLineNumbers=false + docker buildx build --platform linux/amd64 -t router:v1.61.0 --load . + ``` + + - The `--load` option loads the built image to `docker images`. + +1. Run `docker images` and validate that your router image is in the returned list of images. + +## Push router image to container registry + +Create an Azure Container Registry as needed, then push your router image to it. + +### Create new container registry + +If you don't have an existing container registry, create a new one: + +1. Log in to the Azure Portal and go to [Container registries](https://portal.azure.com/?quickstart=true#browse/Microsoft.ContainerRegistry%2Fregistries). +1. Click **Create container registry**. +1. Fill in the details: + - **Subscription**: Select your subscription + - **Resource group**: Select existing group or create new + - **Registry name**: Enter a unique name for your registry (for example, `myapolloregistry`) + - **Location**: Select an appropriate region + - **Pricing plan**: Select an appropriate plan + +1. Click **Review + create**, then click **Create**. +1. Your registry should now be created. Click on your registry to go to its portal page. + +### Log in to container registry + +1. In a terminal, sign in to Azure CLI: + + ```bash showLineNumbers=false + az login + ``` + +1. Log in and authenticate to your registry (for example, `myapolloregistry`): + + ```bash showLineNumbers=false + az acr login --name myapolloregistry + ``` + +### Tag and push image to registry + +1. Use `docker tag` to create an alias of the image with the fully qualified path to your registry (for example, `myapolloregistry.azurecr.io`): + + ```bash showLineNumbers=false + docker tag router:v1.61.0 myapolloregistry.azurecr.io/router:v1.61.0 + ``` +1. Push the image to the registry: + + ```bash showLineNumbers=false + docker push myapolloregistry.azurecr.io/router:v1.61.0 + ``` + +1. Use `az acr repository list` to verify your image is now in the registry: + + ```bash showLineNumbers=false + az acr repository list --name myapolloregistry + ``` + + + +```bash showLineNumbers=false +[ + "myapolloregistry" +] +``` + + +### Deploy the router + +Create and deploy a container app to run the router in Azure: + +1. Log in to the Azure Portal, then go to [Create Container App](https://portal.azure.com/#create/Microsoft.ContainerApp) +1. Fill in the details for the **Basics** tab: + - Subscription: Select your subscription + - Resource Group: Select existing group or create new + - Name: Enter a unique name for your web app. + - Publish: Choose **Container** + - Operating System: Choose **Linux** + - Region: Select an appropriate region + - App Service Plan: Select existing plan or create new + +1. Fill in the details for the **Container** tab: + - **Subscription**: Select your subscription + - **Registry**: Select your registry + - **Image**: Select your router image + - **Image tag**: Select your router image's tag + - **Arguments override**: Enter `--dev, --config, /dist/config/router.yaml` + - **Environment variables**: Enter `APOLLO_GRAPH_REF` and `APOLLO_KEY` with your graph ref and API key, respectively + +1. Fill in the details for the **Ingress** tab: + - **Ingress**: Check **Enabled** + - **Ingress traffic**: Select **Accepting traffic from anywhere** + - **Ingress type**: Select **HTTP** + - **Target port**: Enter `4000` (must match your router's `supergraph.listen` port) + +1. Click **Review + create**. +1. Click **Create**, then wait for your deployment to complete. +1. Click **Go to resource** to open the portal page for your deployed container, then click on the **Application Url** to verify that your router's Sandbox is running successfully. + +Congrats, you've successfully deployed the router! diff --git a/docs/source/routing/self-hosted/containerization/docker.mdx b/docs/source/routing/self-hosted/containerization/docker.mdx index 28a69e5b3b..ac4bfc3063 100644 --- a/docs/source/routing/self-hosted/containerization/docker.mdx +++ b/docs/source/routing/self-hosted/containerization/docker.mdx @@ -1,12 +1,12 @@ --- -title: Run in Docker -subtitle: Run the router container image in Docker -description: Run the Apollo Router Core container image in Docker with examples covering basic setup, configuration overrides, debugging, and building custom Docker images. +title: Deploying GraphOS Router in Docker +subtitle: Deploy router container image +description: Run an Apollo Router container image in Docker with examples covering basic setup, configuration overrides, debugging, and building custom Docker images. --- import ElasticNotice from '../../../../shared/elastic-notice.mdx'; -This guide provides the following examples of running an Apollo Router Core container image in Docker: +This guide provides the following examples of running an Apollo Router container image in Docker: * Running a basic example with default configuration. * Customizing your configuration to override the default configuration. @@ -49,7 +49,7 @@ services: APOLLO_KEY: "" ``` -Whether you use `docker run` or `docker compose`, make sure to replace `` with whichever version you want to use, such as `v1.58.0`, and `` and `` with your graph reference and API key, respectively. +Whether you use `docker run` or `docker compose`, make sure to replace `` with whichever version you want to use, and `` and `` with your graph reference and API key, respectively. For more complex configurations, such as overriding subgraph URLs or propagating headers, see [Router Configuration](/router/configuration/overview/). diff --git a/docs/source/routing/self-hosted/containerization/gcp.mdx b/docs/source/routing/self-hosted/containerization/gcp.mdx new file mode 100644 index 0000000000..6236080198 --- /dev/null +++ b/docs/source/routing/self-hosted/containerization/gcp.mdx @@ -0,0 +1,155 @@ +--- +title: Deploying GraphOS Router on GCP +subtitle: Deploy router with Google Cloud Run +description: Build and deploy Apollo GraphOS Router or Apollo Router Core to Google Cloud Platform (GCP) with Google Cloud Run. +--- + +Learn how to deploy the router for development on Google Cloud Platform (GCP) with Google Cloud Run. + +You will: +- Build a router image using a Dockerfile and a router configuration file. +- Set up a container registry and push your router image to it. +- Create a Cloud Run service and configure it to deploy your router. + +## Prerequisites + +Before you start: + +1. [Set up a GraphQL API in GraphOS](/graphos/get-started/guides/graphql#step-1-set-up-your-graphql-api). + - Save your `APOLLO_KEY` and `APOLLO_GRAPH_REF` in your GCP Secret Manager. You'll need them when deploying the router. +1. Install [Docker](https://www.docker.com/get-started/) locally. +1. Create a [GCP account](https://cloud.google.com/) or use an existing account. +1. Create a [GCP project](https://console.cloud.google.com/projectcreate). Choose a project name (for example, `my-project`) and save it to use later when deploying the router. +1. Install the [gcloud CLI](https://cloud.google.com/sdk/docs/install) and log in to your GCP account. +1. Choose a version of the router to deploy (for example, `v1.61.0`). You'll need it when specifying the router image to deploy. + +## Build router image + +To deploy your own router, start by customizing and building a router image, using a Dockerfile and a router configuration file: + +1. In a local directory, create a `router.yaml` file and copy-paste the following configuration into the file: + + ```yaml title="router.yaml" + supergraph: + listen: 0.0.0.0:4000 + health_check: + listen: 0.0.0.0:8088 + ``` + + The router's default HTTP and health check endpoint addresses are localhost, so they wouldn't be reachable when deployed. This configuration enables the router to listen to all addresses. + +1. Create a `Dockerfile` file and copy-paste the following into the file: + + ```text showLineNumbers=false + # Use the official Apollo Router Core image as the base. + # Set the image tag to the desired router version (e.g. v1.61.0) + FROM ghcr.io/apollographql/router:v1.61.0 + + # Replace the default router config with the local, customized router.yaml + COPY router.yaml /dist/config/router.yaml + ``` + + The Dockerfile sources the base router image from the GitHub container registry, using the version of router you specify. It then copies your customized `router.yaml` configuration file to overwrite the default router configuration file. + +1. From the same local directory, use `docker buildx` CLI command to build a new router image. Choose a name and tag for the image, for example `router-gcp:v1.61.0`. + + ```bash showLineNumbers=false + docker buildx build --platform linux/amd64 -t router-gcp:v1.61.0 --load . + ``` + + - Because Cloud Run only supports AMD64-based images, the `docker buildx build --platform linux/amd64` command ensures the image is built for AMD64 and is compatible. + - The `--load` option loads the built image to `docker images`. + +1. Use `docker images` to validate that your router image is successfully built and loaded. + +## Push router image to container registry + +With a router image built, set up GCP Artifact Registry, then tag and push your image to it. + +### Set up container registry + +1. In GCP, enable [Artifact Registry](https://cloud.google.com/artifact-registry/docs/enable-service) in your project. + - Create a repository and choose a repository name (for example, `my-repo`). Keep this name handy, as you'll need it later to build and deploy a router image. + +### Tag and push router image + +1. Use `docker tag` to tag the image before pushing it to Artifact Registry. Make sure your tag conforms with Artifact Registry's [naming convention](https://cloud.google.com/artifact-registry/docs/docker/names) (for example, `us-west2-docker.pkg.dev/my-project/my-repo/router-gcp:v1.61.0`). + + ```bash showLineNumbers=false + docker tag router-gcp:v1.61.0 \ + us-west2-docker.pkg.dev/my-project/my-repo/router-gcp:v1.61.0 + ``` + +1. Use `docker push` to push the router image to Artifact Registry. + + ```bash showLineNumbers=false + docker push us-west2-docker.pkg.dev/my-project/my-repo/router-gcp:v1.61.0 + ``` + +1. Validate the router image has been successfully pushed to Artifact Registry. You can use Google Cloud Console and navigate to your repository in Artifact Registry. You can also use the gcloud CLI and run `gcloud artifacts docker images`. For example: + + ```bash showLineNumbers=false + gcloud artifacts docker images list us-west2-docker.pkg.dev/my-project/my-repo + ``` + +## Create and deploy Cloud Run service + +With the router image pushed to GCP, you can now configure and deploy it as a Cloud Run service. + +You can use either Google Cloud console or gcloud CLI. In either case, you need to gather the following information: + +* Name for your deployed router service (for example, `my-router`) +* GCP project name (for example, `my-project`) +* Artifact Registry repo name (for example, `my-repo`) +* GCP region (for example, `us-west2`) +* Full image path (for example, `us-west2-docker.pkg.dev/my-project/my-repo/router-gcp:v1.61.0`) +* `APOLLO_KEY` and `APOLLO_GRAPH_REF` secrets + +### Deploy with Google Cloud console + +1. In GCP console for your project, go to Cloud Run and select **Deploy container** > **Service**. +1. On the **Create Service** page, fill in the details: + - **Container image URL**: Select your router image + - **Service name**: Enter a name for your deployed router (for example, `my-router`) + - **Region**: Select your GCP region + - **Authentication**: Select **Allow unauthenticated invocations**. +1. On the **Container(s)** > **Edit Container** tab, go to the **Settings** tab and fill in the details: + - **Container port**: Enter `4000` (must match the `supergraph.listen` port of your router configuration) + - **Container command**: Enter `/dist/router` + - **Container arguments**: Enter `--dev` (runs the router in development mode) +1. Also on the **Container(s)** > **Edit Container** tab, go to the **Variables & Secrets** and fill in the details: + * Add `APOLLO_KEY` and set it to your graph API key + * Add `APOLLO_GRAPH_REF` and set it to your graph ref +1. Click **Deploy**. +1. Once deployed, select the service from the [Cloud Run console](https://console.cloud.google.com/run), then click on its **URL** (for example, `https://my-router-123456789012.us-west1.run.app/`) and validate that router's development Sandbox is running successfully. + +### Deploy with gcloud CLI + +1. To deploy the router with the gcloud CLI, use `gcloud run deploy` with your configuration info in place of the example info: + + ```bash showLineNumbers=false + gcloud run deploy my-router \ + --image=us-west2-docker.pkg.dev/my-project/my-repo/router-gcp:v1.61.0 \ + --command=/dist/router \ + --args=--dev \ + --set-secrets=APOLLO_KEY=APOLLO_KEY:latest,APOLLO_GRAPH_REF=APOLLO_GRAPH_REF:latest \ + --region=us-west2 \ + --project=router-container-gcp + ``` + +1. Update traffic to your deployed router by running `gcloud run services update-traffic`: + + ```bash + gcloud run services update-traffic my-router --to-latest + ``` + +1. Use `gcloud run services` to get the service URL. For example, for a service named `my-router`: + + ```bash + gcloud run services describe my-router --format 'value(status.url)' + ``` + +1. In a browser, go to the service URL and validate the the router's development Sandbox is running successfully. + +Congrats, you've successfully deployed the router! + diff --git a/docs/source/routing/self-hosted/containerization/index.mdx b/docs/source/routing/self-hosted/containerization/index.mdx index e1199c9527..d14b59a332 100644 --- a/docs/source/routing/self-hosted/containerization/index.mdx +++ b/docs/source/routing/self-hosted/containerization/index.mdx @@ -1,5 +1,5 @@ --- -title: Containerizing the GraphOS Router +title: Containerizing an Apollo Router subtitle: Run router images in containers description: Containerize the Apollo GraphOS Router for portability and scalability. Choose from default or debug images. Deploy in Kubernetes or run in Docker. --- @@ -24,11 +24,15 @@ A router image has the following layout: ## Next steps -The default behavior of a router image is suitable for a basic deployment or development scenario. +While the default behavior of a router image is largely suitable for a basic deployment or development scenario, running a containerized router usually requires configuring the router's HTTP endpoint (and optional health check endpoint) to listen on a non-localhost address. -For examples of customizing and deploying router images in specific environments, see the guides for: -* [Deploying in Kubernetes](/router/containerization/kubernetes/). -* [Running in Docker](/router/containerization/docker/) +To learn from examples of customizing and deploying router images in specific environments, see the deployment guides for: + +* [Docker](/router/containerization/docker/) +* [AWS](/graphos/routing/self-hosted/containerization/aws) +* [Azure](/graphos/routing/self-hosted/containerization/azure) +* [GCP](/graphos/routing/self-hosted/containerization/gcp) +* [Kubernetes](/router/containerization/kubernetes/) See the Apollo Solutions [example Cloud Foundry deployment](https://github.com/apollosolutions/example-pcf-deployment) for a minimal router configuration and Cloud Foundry manifest file. diff --git a/docs/source/routing/self-hosted/index.mdx b/docs/source/routing/self-hosted/index.mdx index 545944468c..3cdf684cf2 100644 --- a/docs/source/routing/self-hosted/index.mdx +++ b/docs/source/routing/self-hosted/index.mdx @@ -1,10 +1,9 @@ --- -title: Self-Hosted Router -subtitle: Host and deploy routers in your own infrastructure -description: Distribute operations efficiently across microservices in your federated GraphQL API with the Apollo GraphOS Router or Apollo Router Core. Configure caching, security features, and more. +title: Deploying Self-Hosted Apollo Router +subtitle: How to deploy router for your own infrastructure --- -A self-hosted GraphOS Router or Apollo Router Core enables you to fully manage the runtime infrastructure and deployments of your supergraph. +Apollo Router is a graph runtime that you can deploy in your own infrastructure. ```mermaid flowchart LR; @@ -19,31 +18,31 @@ flowchart LR; class clients secondary; ``` - +Each release of Apollo Router includes: -Self-hosting the GraphOS Router requires a current GraphOS [Enterprise or Free plan](https://www.apollographql.com/pricing). +- A binary +- A container image +- A Helm chart - +## Local binary -## Downloading and installing a self-hosted router +Running Apollo Router directly from its binary speeds up local development, and it enables embedded use cases where containers are unavailable. -Apollo provides the router as both a binary and as images to run in your containerized deployments. +Follow the [quickstart](/graphos/routing/get-started) to run a router binary. -### Router binary +## Kubernetes via Helm -Apollo provides a binary of the router for multiple platforms. You can download the router bundle, extract the router binary, and run it. +Helm is a package manager for Kubernetes. Apollo provides an application Helm chart with each release of Apollo Router in GitHub Container Registry. Since router v0.14.0, Apollo has released each router Helm chart as an Open Container Initiative (OCI) image in `oci://ghcr.io/apollographql/helm-charts/router`. -To learn more, follow the steps in the [self-hosted router installation](/graphos/reference/router/self-hosted-install) reference to run a router binary with a sample supergraph schema. +Follow the [Kubernetes deployment guide](/graphos/routing/self-hosted/containerization/kubernetes) to deploy the router with a Helm chart. -### Router container image +## Container -Apollo provides container images of the router to deploy in self-hosted environments. The router images are hosted on GitHub in its container repository. Each router release includes both production and debug images. +For containerization without k8s or Helm, Apollo provides container images with each release of Apollo Router. The images are available in GitHub, downloadable from `ghcr.io/apollographql/router` and the [router repo](https://github.com/apollographql/router/pkgs/container/router). Both debug and production images are provided. -To learn more, go to the [containerization overview](/graphos/routing/self-hosted/containerization). +Follow the router deployment guide for your container environment: -- If running with Docker, go to the [Docker](/graphos/routing/self-hosted/containerization/docker) docs to learn how to run router images. -- If running with Kubernetes, go to the [Kubernetes](/graphos/routing/self-hosted/containerization/kubernetes) docs to learn to deploy with router Helm charts. - -## Next steps - -- To prepare your routers for production deployment, follow the guides in [Production Readiness](/graphos/platform/production-readiness/checklist) docs. +- [AWS](/graphos/routing/self-hosted/containerization/aws) +- [Azure](/graphos/routing/self-hosted/containerization/azure) +- [GCP](/graphos/routing/self-hosted/containerization/gcp) +- [Docker](/graphos/routing/self-hosted/containerization/docker) diff --git a/docs/source/routing/self-hosted/install.mdx b/docs/source/routing/self-hosted/install.mdx deleted file mode 100644 index b5ade4692c..0000000000 --- a/docs/source/routing/self-hosted/install.mdx +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: Router Quickstart -subtitle: Run the router with GraphOS and Apollo-hosted subgraphs -description: This quickstart tutorial walks you through installing the Apollo GraphOS Router or Apollo Router Core and running it with GraphOS and some example Apollo-hosted subgraphs. ---- - -import ElasticNotice from "../../../shared/elastic-notice.mdx"; - -Hello! This tutorial walks you through installing the router (GraphOS Router or Apollo Router Core) and running it in with GraphOS and some example Apollo-hosted subgraphs. - -> **This quickstart helps you run a _self-hosted_ instance of the router.** If you [create a cloud supergraph](/graphos/quickstart/cloud/) with Apollo GraphOS, Apollo provisions and hosts your supergraph's GraphOS -> Router for you. -> -> Cloud supergraphs are recommended for organizations that don't need to host their router in their own infrastructure. - -## 1. Download and extract the router binary - - - -### Download options - -You can either automatically download the router binary directly to your current directory, or manually download the router bundle for your platform. - -#### Automatic download (Linux, OSX, WSL) - -If you have a bash-compatible terminal, you can download the latest version of the Apollo Router Core directly to your current directory with the following command: - -```bash -curl -sSL https://router.apollo.dev/download/nix/latest | sh -``` - -With the router binary now in your current directory, go to the step [Running the binary](#running-the-binary). - -#### Manual download - -Go to the Apollo Router Core's [GitHub Releases page](https://github.com/apollographql/router/releases) and download the latest `.tar.gz` file that matches your system. Currently, tarballs are available for the following: - -- Linux (x86_64) -- Linux (aarch64) -- macOS (Apple Silicon) -- Windows (x86_64) - -If a tarball for your system or architecture isn't available, you can [build and run the router from source](https://github.com/apollographql/router/blob/HEAD/DEVELOPMENT.md#development-1). You can also [open an issue on GitHub](https://github.com/apollographql/router/issues/new/choose) to request the addition of new architectures. - -After downloading, extract the file by running the following from a new project directory, substituting the path to the tarball: - -```bash -tar -xf path/to/file.tar.gz --strip-components=1 -``` - -If you omit the `--strip-components=1` option, the `router` executable is installed in a `dist` subdirectory. - -### Running the binary - -You can now run the router from your project's root directory with the following command: - -```bash -./router -``` - -If you do, you'll get output similar to the following: - -``` -Apollo Router // (c) Apollo Graph, Inc. // Licensed as ELv2 (https://go.apollo.dev/elv2) - -⚠️ The Apollo Router requires a composed supergraph schema at startup. ⚠️ - -👉 DO ONE: - - * Pass a local schema file with the '--supergraph' option: - - $ ./router --supergraph - - * Fetch a registered schema from GraphOS by setting - these environment variables: - - $ APOLLO_KEY="..." APOLLO_GRAPH_REF="..." ./router - - For details, see the Apollo docs: - https://www.apollographql.com/docs/federation/managed-federation/setup - -🔬 TESTING THINGS OUT? - - 1. Download an example supergraph schema with Apollo-hosted subgraphs: - - $ curl -L https://supergraph.demo.starstuff.dev/ > starstuff.graphql - - 2. Run the router in development mode with the supergraph schema: - - $ ./router --dev --supergraph starstuff.graphql -``` - -This is because router requires a supergraph schema and we aren't providing it one! Let's fix that. - -## 2. Download the example supergraph schema - -For this quickstart, we're using example Apollo-hosted subgraphs, along with an example supergraph schema that's composed from those subgraph schemas. - -From your project's root directory, run the following: - -```bash -curl -sSL https://supergraph.demo.starstuff.dev/ > supergraph-schema.graphql -``` - -This saves a `supergraph-schema.graphql` file with the following contents: - - - -```graphql title="supergraph-schema.graphql" -schema - @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) { - query: Query - mutation: Mutation -} - -directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE - -directive @join__field( - graph: join__Graph - requires: join__FieldSet - provides: join__FieldSet - type: String - external: Boolean - override: String - usedOverridden: Boolean -) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION - -directive @join__graph(name: String!, url: String!) on ENUM_VALUE - -directive @join__implements( - graph: join__Graph! - interface: String! -) repeatable on OBJECT | INTERFACE - -directive @join__type( - graph: join__Graph! - key: join__FieldSet - extension: Boolean! = false - resolvable: Boolean! = true - isInterfaceObject: Boolean! = false -) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR - -directive @join__unionMember( - graph: join__Graph! - member: String! -) repeatable on UNION - -directive @link( - url: String - as: String - for: link__Purpose - import: [link__Import] -) repeatable on SCHEMA - -scalar join__FieldSet - -enum join__Graph { - ACCOUNTS - @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev/") - INVENTORY - @join__graph( - name: "inventory" - url: "https://inventory.demo.starstuff.dev/" - ) - PRODUCTS - @join__graph(name: "products", url: "https://products.demo.starstuff.dev/") - REVIEWS - @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev/") -} - -scalar link__Import - -enum link__Purpose { - """ - `SECURITY` features provide metadata necessary to securely resolve fields. - """ - SECURITY - - """ - `EXECUTION` features provide metadata necessary for operation execution. - """ - EXECUTION -} - -type Mutation @join__type(graph: PRODUCTS) @join__type(graph: REVIEWS) { - createProduct(upc: ID!, name: String): Product @join__field(graph: PRODUCTS) - createReview(upc: ID!, id: ID!, body: String): Review - @join__field(graph: REVIEWS) -} - -type Product - @join__type(graph: ACCOUNTS, key: "upc", extension: true) - @join__type(graph: INVENTORY, key: "upc") - @join__type(graph: PRODUCTS, key: "upc") - @join__type(graph: REVIEWS, key: "upc") { - upc: String! - weight: Int - @join__field(graph: INVENTORY, external: true) - @join__field(graph: PRODUCTS) - price: Int - @join__field(graph: INVENTORY, external: true) - @join__field(graph: PRODUCTS) - inStock: Boolean @join__field(graph: INVENTORY) - shippingEstimate: Int @join__field(graph: INVENTORY, requires: "price weight") - name: String @join__field(graph: PRODUCTS) - reviews: [Review] @join__field(graph: REVIEWS) - reviewsForAuthor(authorID: ID!): [Review] @join__field(graph: REVIEWS) -} - -type Query - @join__type(graph: ACCOUNTS) - @join__type(graph: INVENTORY) - @join__type(graph: PRODUCTS) - @join__type(graph: REVIEWS) { - me: User @join__field(graph: ACCOUNTS) - recommendedProducts: [Product] @join__field(graph: ACCOUNTS) - topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCTS) -} - -type Review @join__type(graph: REVIEWS, key: "id") { - id: ID! - body: String - author: User @join__field(graph: REVIEWS, provides: "username") - product: Product -} - -type User - @join__type(graph: ACCOUNTS, key: "id") - @join__type(graph: REVIEWS, key: "id") { - id: ID! - name: String @join__field(graph: ACCOUNTS) - username: String - @join__field(graph: ACCOUNTS) - @join__field(graph: REVIEWS, external: true) - reviews: [Review] @join__field(graph: REVIEWS) -} -``` - - - -This file is all that the router needs to communicate with our subgraphs! - -## 3. Run the router in development mode with the default configuration - -Now from your project root, run the following: - -```sh -./router --dev --supergraph supergraph-schema.graphql -``` - -The console output should look like the following: - -```sh -2022-06-29T22:23:24.266542Z INFO apollo_router::executable: Apollo Router v0.9.5 // (c) Apollo Graph, Inc. // Licensed as ELv2 (https://go.apollo.dev/elv2) -2022-06-29T22:23:24.488286Z INFO apollo_router::router: starting Apollo Router -2022-06-29T22:23:25.774334Z INFO apollo_router::axum_http_server_factory: GraphQL endpoint exposed at http://127.0.0.1:4000/ 🚀 -``` - -That's it! Running the router with the `--dev` flag enables a development mode that exposes [Apollo Sandbox](/graphos/explorer/sandbox/) so you can run queries against the router. - - - -**Do not use the `--dev` flag in a non-development environment.** It relaxes certain default configuration options to provide an improved local development experience (e.g., it exposes subgraph error messages to clients). - -[Learn more about dev mode defaults.](/router/configuration/overview#dev-mode-defaults) - - - -Visit `http://127.0.0.1:4000` to open Apollo Sandbox, inspect your entire supergraph, and run your first queries! - -## Next steps - -Now that you know how to run the router with a supergraph schema, you can: - -- Set up [managed federation](/federation/managed-federation/overview) -- Learn about [additional configuration options](/router/configuration/overview) -- [Estimate the system resources needed to deploy the router](/technotes/TN0045-router_resource_estimator/). diff --git a/docs/source/routing/upgrade/from-router-v1.mdx b/docs/source/routing/upgrade/from-router-v1.mdx index b5c8f4b47d..fd12bc513e 100644 --- a/docs/source/routing/upgrade/from-router-v1.mdx +++ b/docs/source/routing/upgrade/from-router-v1.mdx @@ -39,7 +39,7 @@ The following headings describe features that have been removed or deprecated in Multiple metrics have been removed in router v2.x as part of evolving towards OpenTelemetry metrics and conventions. Each of the removed metrics listed below has a replacement metric or a method for deriving its value: -- Removed `apollo_router_http_request_retry_total`. This is replaced by `http.client.request.duration` metric's `http.request.resend_count` attribute. Set [`default_requirement_level`](/docs/graphos/reference/router/telemetry/instrumentation/instruments#default_requirement_level) +- Removed `apollo_router_http_request_retry_total`. This is replaced by `http.client.request.duration` metric's `http.request.resend_count` attribute. Set [`default_requirement_level`](/graphos/reference/router/telemetry/instrumentation/instruments#default_requirement_level) to `recommended` to make the router emit this attribute. - Removed `apollo_router_timeout`. This metric conflated timed-out requests from client