Skip to content

Commit

Permalink
Split out AS subgraph stuff from library-neutral info (apollographql#…
Browse files Browse the repository at this point in the history
…2172)

* Split out AS subgraph stuff from library-neutral info

* Remove unused and broken import

* Update doc autogeneration scripts for new file paths

* Remove an outdated internal link
  • Loading branch information
Stephen Barlow authored Sep 29, 2022
1 parent 4c0c478 commit 187c6cc
Show file tree
Hide file tree
Showing 26 changed files with 188 additions and 145 deletions.
2 changes: 1 addition & 1 deletion composition-js/src/genHintDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const header = `---
title: Composition hints
---
When you successfully [compose](./federated-types/composition) the schemas provided by your [subgraphs](./subgraphs/) into a supergraph schema, the composition process might output **hints** that provide additional information about the result. Hints are primarily informative and _do not_ necessarily indicate that a problem needs to be fixed.
When you successfully [compose](./federated-types/composition) the schemas provided by your [subgraphs](./building-supergraphs/subgraphs-overview/) into a supergraph schema, the composition process might output **hints** that provide additional information about the result. Hints are primarily informative and _do not_ necessarily indicate that a problem needs to be fixed.
Hints are categorized under the following levels:
Expand Down
7 changes: 5 additions & 2 deletions docs/source/_redirects
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/gateway/ /docs/federation/router/
/other-servers/ /docs/federation/supported-subgraphs/
/subgraphs/ /docs/federation/building-supergraphs/subgraphs-apollo-server/
/gateway/ /docs/federation/building-supergraphs/router/
/router/ /docs/federation/building-supergraphs/router/
/supported-subgraphs/ /docs/federation/building-supergraphs/supported-subgraphs/
/other-servers/ /docs/federation/building-supergraphs/supported-subgraphs/
/federation-spec/ /docs/federation/subgraph-spec/

/v2/* /docs/federation/:splat
Expand Down
4 changes: 2 additions & 2 deletions docs/source/api/apollo-gateway.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This API reference documents the exports from the `@apollo/gateway` package.
## `class ApolloGateway`

The core class of Apollo Server's federated gateway implementation. For an
example of using `ApolloGateway`, see [The gateway](../gateway/).
example of using `ApolloGateway`, see [The graph router](../building-supergraphs/router/).

### Methods

Expand Down Expand Up @@ -585,7 +585,7 @@ The details of the `fetch` response sent by the subgraph.

## `class IntrospectAndCompose`

> ⚠️ **We strongly recommend _against_ using `IntrospectAndCompose` in production.** For details, see [Limitations of `IntrospectAndCompose`](../router#limitations-of-introspectandcompose).
> ⚠️ **We strongly recommend _against_ using `IntrospectAndCompose` in production.** For details, see [Limitations of `IntrospectAndCompose`](../building-supergraphs/router#limitations-of-introspectandcompose).
`IntrospectAndCompose` is a development tool for fetching and composing subgraph SDL into a supergraph for your gateway. Given a list of subgraphs and their URLs, `IntrospectAndCompose` will issue queries for their SDL, compose them into a supergraph, and provide that supergraph to the gateway. It can also be configured to update via polling and perform subgraph health checks to ensure that supergraphs are updated safely. `IntrospectAndCompose` implements the `SupergraphManager` interface and is passed in to `ApolloGateway`'s `supergraphSdl` constructor option.

Expand Down
2 changes: 1 addition & 1 deletion docs/source/api/apollo-subgraph.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const server = new ApolloServer({
});
```

Used when [defining a subgraph](../subgraphs/#defining-a-subgraph) in a federated graph.
Used when [defining a subgraph](../building-supergraphs/subgraphs-apollo-server/#defining-a-subgraph) in a federated graph.

Each schema module is an object with the following format:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: The entry point to your federated supergraph

import FederationArchitecture from '../shared/diagrams/federation-architecture.mdx';

After you set up at least one federation-ready [subgraph](./subgraphs/), you can configure a **graph router** (also known as a gateway) to sit in front of your subgraphs. The router serves as the entry point to your supergraph, and it executes incoming operations across one or more of your subgraphs:
After you set up at least one federation-ready [subgraph](./subgraphs-overview/), you can configure a **graph router** (also known as a gateway) to sit in front of your subgraphs. The router serves as the entry point to your supergraph, and it executes incoming operations across one or more of your subgraphs:

<FederationArchitecture />

Expand All @@ -15,7 +15,7 @@ Apollo actively supports two options for your graph router:

* **The Apollo Router (recommended):** This is a high-performance, precompiled Rust binary.
* [Go to the Apollo Router docs.](/router/quickstart/)
* [See the federation quickstart](./quickstart/setup/) (which uses the Apollo Router).
* [See the federation quickstart](../quickstart/setup/) (which uses the Apollo Router).
* **Apollo Server:** Apollo Server can act as your graph router via the [`@apollo/gateway`](https://www.npmjs.com/package/@apollo/gateway) extension library.

**We recommend starting with the Apollo Router.** It's faster to configure, it's more performant (especially with high request loads), and it rarely requires writing custom code.
Expand All @@ -40,7 +40,7 @@ Create a new Node.js project with `npm init`, then install the necessary package
npm install @apollo/gateway apollo-server graphql
```

The `@apollo/gateway` package includes the [`ApolloGateway` class](./api/apollo-gateway/). To configure Apollo Server to act as a graph router, you pass an instance of `ApolloGateway` to the `ApolloServer` constructor, like so:
The `@apollo/gateway` package includes the [`ApolloGateway` class](../api/apollo-gateway/). To configure Apollo Server to act as a graph router, you pass an instance of `ApolloGateway` to the `ApolloServer` constructor, like so:

```js {7-11,13-16} title="index.js"
const { ApolloServer, gql } = require('apollo-server');
Expand All @@ -67,11 +67,11 @@ server.listen().then(({ url }) => {

### Composing the supergraph schema

In the above example, we provide the `supergraphSdl` option to the `ApolloGateway` constructor. This is the string representation of our [supergraph schema](./federated-types/overview/#supergraph-schema), which is composed from all of our subgraph schemas.
In the above example, we provide the `supergraphSdl` option to the `ApolloGateway` constructor. This is the string representation of our [supergraph schema](../federated-types/overview/#supergraph-schema), which is composed from all of our subgraph schemas.

To learn how to compose your supergraph schema, see [Supported methods](./federated-types/composition/#supported-methods).
To learn how to compose your supergraph schema, see [Supported methods](../federated-types/composition/#supported-methods).

> In production, we strongly recommend running the gateway in a **managed mode** with Apollo Studio, which enables your gateway to update its configuration without a restart. For details, see [Setting up managed federation](https://www.apollographql.com/docs/studio/managed-federation/setup/).
> In production, we strongly recommend running the gateway in a **managed mode** with Apollo Studio, which enables your gateway to update its configuration without a restart. For details, see [Setting up managed federation](/studio/managed-federation/setup/).
On startup, the gateway processes your `supergraphSdl`, which includes routing information for your subgraphs. It then begins accepting incoming requests and creates query plans for them that execute across one or more subgraphs.

Expand Down Expand Up @@ -199,15 +199,15 @@ Each item in the `subgraphs` array is an object that specifies the `name` and `u

On startup, the gateway fetches each subgraph's schema from its `url` and composes those schemas into a supergraph schema. It then begins accepting incoming requests and creates query plans for them that execute across one or more subgraphs.

Additional configuration options can be found in the [`IntrospectAndCompose` API documentation](./api/apollo-gateway#class-introspectandcompose).
Additional configuration options can be found in the [`IntrospectAndCompose` API documentation](../api/apollo-gateway#class-introspectandcompose).

However, `IntrospectAndCompose` has important [limitations](#limitations-of-introspectandcompose).

#### Limitations of `IntrospectAndCompose`

The `IntrospectAndCompose` option can sometimes be helpful for local development, but it's strongly discouraged for any other environment. Here are some reasons why:

* **Composition might fail.** With `IntrospectAndCompose`, your gateway performs composition dynamically on startup, which requires network communication with each subgraph. If composition fails, your gateway [throws errors](./errors/) and experiences unplanned downtime.
* **Composition might fail.** With `IntrospectAndCompose`, your gateway performs composition dynamically on startup, which requires network communication with each subgraph. If composition fails, your gateway [throws errors](../errors/) and experiences unplanned downtime.
* With the static or dynamic `supergraphSdl` configuration, you instead provide a supergraph schema that has _already_ been composed successfully. This prevents composition errors and enables faster startup.
* **Gateway instances might differ.** If you deploy multiple instances of your gateway _while_ deploying updates to your subgraphs, your gateway instances might fetch different schemas from the _same_ subgraph. This can result in sporadic composition failures or inconsistent supergraph schemas between instances.
* When you deploy multiple instances with `supergraphSdl`, you provide the exact same static artifact to each instance, enabling more predictable behavior.
Expand Down Expand Up @@ -387,11 +387,11 @@ server.listen().then(({ url }) => {

> In this example, multiple calls to `didReceiveResponse` are `push`ing a value onto the shared `context.serverIds` array. The order of these calls cannot be guaranteed. If you write logic that modifies the shared `context` object, make sure that modifications are not destructive, and that the order of modifications doesn't matter.
To learn more about `buildService` and `RemoteGraphQLDataSource`, see the [API docs](./api/apollo-gateway/).
To learn more about `buildService` and `RemoteGraphQLDataSource`, see the [API docs](../api/apollo-gateway/).

## Custom directive support

The `@apollo/gateway` library supports the use of custom [directives](https://www.apollographql.com/docs/apollo-server/schema/directives/) in your subgraph schemas. This support differs depending on whether a given directive is a **type system directive** or an **executable directive**.
The `@apollo/gateway` library supports the use of custom [directives](/apollo-server/schema/directives/) in your subgraph schemas. This support differs depending on whether a given directive is a **type system directive** or an **executable directive**.

### Type system directives

Expand All @@ -410,7 +410,7 @@ type ExampleType {
}
```

The gateway strips all definitions _and_ uses of type system directives from your graph's [API schema](./federated-types/overview/#api-schema). This has no effect on your subgraph schemas, which retain this information.
The gateway strips all definitions _and_ uses of type system directives from your graph's [API schema](../federated-types/overview/#api-schema). This has no effect on your subgraph schemas, which retain this information.

Effectively, the gateway supports type system directives by _ignoring_ them, making them the responsibility of the subgraphs that define them.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
title: Implementing a subgraph with Apollo Server
---

import FederationArchitecture from '../shared/diagrams/federation-architecture.mdx';

This article demonstrates how to create a **subgraph** for a federated supergraph using Node.js and Apollo Server.

> To create a subgraph using a different language and/or framework, see the list of [Federation-compatible subgraph implementations](./supported-subgraphs/). Note that not all listed libraries provide full support for Federation features.
> To create a subgraph using a different language and/or framework, see the list of [Federation-compatible subgraph implementations](./supported-subgraphs/). Note that not all listed libraries support _all_ Federation features.
## Defining a subgraph

> To be part of a supergraph, a subgraph must conform to the [Apollo Federation subgraph specification](./subgraph-spec/), which exposes the subgraph's capabilities to your graph router, as well as to tools like Apollo Studio.
> To be part of a supergraph, a subgraph must conform to the [Apollo Federation subgraph specification](../subgraph-spec/), which exposes the subgraph's capabilities to your graph router, as well as to tools like Apollo Studio.
Converting an existing monolithic graph into a single subgraph is a convenient first step in building a federated supergraph. To start, here's a *non-federated* Apollo Server setup:

Expand Down Expand Up @@ -66,7 +64,7 @@ const { buildSubgraphSchema } = require('@apollo/subgraph');

### 2. Opt in to Federation 2

For a subgraph to use [new features in Federation 2](./federation-2/new-in-federation-2/), its schema needs to include the following `extend schema` definition:
For a subgraph to use [new features in Federation 2](../federation-2/new-in-federation-2/), its schema needs to include the following `extend schema` definition:

```js {2-4}
const typeDefs = gql`
Expand All @@ -87,13 +85,13 @@ extend schema

This definition enables the schema to use Federation 2 features. Without it, Federation 2 composition assumes that a subgraph is using Federation 1, which sets certain defaults for backward compatibility.

> As you begin using more [federation-specific directives](./federated-types/federated-directives) beyond `@key` and `@shareable`, you'll need to add those directives to the `import` array shown above.
> As you begin using more [federation-specific directives](../federated-types/federated-directives) beyond `@key` and `@shareable`, you'll need to add those directives to the `import` array shown above.
### 3. Define an entity

> Entities aren't _required_ in a subgraph, but they're a core building block of a federated supergraph, so it's good to get some practice defining them.
As part of our federated architecture, we want _other_ subgraphs to be able to contribute fields to the `User` type. To enable this, we add the `@key` directive to the `User` type's definition to designate it as an [entity](./entities/):
As part of our federated architecture, we want _other_ subgraphs to be able to contribute fields to the `User` type. To enable this, we add the `@key` directive to the `User` type's definition to designate it as an [entity](../entities/):

```js {10} title="index.js"
const typeDefs = gql`
Expand Down Expand Up @@ -133,7 +131,7 @@ const resolvers = {

(This example requires defining the `fetchUserById` function to obtain the appropriate `User` from our backing data store.)

> [Learn more about entities.](./entities/)
> [Learn more about entities.](../entities/)
### 4. Generate the subgraph schema

Expand Down Expand Up @@ -196,96 +194,6 @@ server.listen(4001).then(({ url }) => {
});
```

## Securing your subgraphs

Because of the power and flexibility of the [`Query._entities` and `Query._service` fields](#subgraph-specific-fields), your subgraphs should **not** be directly accessible by clients. Instead, only your graph router should have access to your subgraphs. Clients then communicate with the router:

<FederationArchitecture />

Make sure to implement any necessary firewall rules, access control lists, or other measures to ensure that individual subgraphs can be accessed _only_ via the router.

### Disabling CORS

We recommend that subgraphs do not enable CORS (or at least do not use the wildcard `access-control-allow-origin: *` header). This prevents attackers from exploiting a user's browser to access a subgraph directly.

For Apollo Server subgraphs, you need to disable the default wildcard CORS policy (which is appropriate for many publicly-exposed servers but not for inaccessible servers like subgraphs). For details, see the [Apollo Server CORS documentation](/apollo-server/security/cors/#choosing-cors-options-for-your-project).

## Subgraph-specific fields

When you [generate your subgraph schema](#4-generate-the-subgraph-schema), some federation-specific definitions are automatically added to it. In addition to directive definitions like `@key`, the most useful of these definitions for debugging are two fields of the `Query` type: `_service` and `_entities`:

```graphql
type Query {
# ...your field definitions...

# Added automatically
_service: _Service!
_entities(representations: [_Any!]!): [_Entity]!
}
```

### `Query._service`

This field returns a `_Service` object with one field of its own: `sdl`. You can query it like so:

```graphql
query GetSubgraphSchema {
_service {
sdl
}
}
```

The `sdl` field returns your subgraph's schema as an SDL string. This field has a couple of important differences from a standard [introspection query](https://graphql.org/learn/introspection/) that a tool like Apollo Sandbox uses:

* Unlike introspection, the `sdl` field is _not_ disabled by default in production environments (this is safe if you properly [secure your subgraph](#securing-your-subgraphs)).
* Unlike introspection, the `sdl` field's returned string includes federation-specific directives like `@key`.

### `Query._entities`

> [Learn about entities](./entities/) if you haven't yet.
This field takes a list of **entity representations** and returns a list of corresponding entities.

> Whenever one subgraph references _another_ subgraph's entity, it uses an **entity representation** to do so. An entity representation is an object that includes _only_ the entity's `__typename` and the fields in the entity's `@key`.
```graphql
_entities(representations: [_Any!]!): [_Entity]!
```

* The `_Any` type is a special scalar that enables you to provide entity representations of any valid shape.
* The `_Entity` type is a generated [union type](https://www.apollographql.com/docs/apollo-server/schema/unions-interfaces/#union-type) that includes every entity defined in your subgraph's schema.

You can query this field like so, providing a value for the `$representations` variable as shown:

```graphql title="Query"
query ($representations: [_Any!]!) {
_entities(representations: $representations) {
... on User {
id
username
}
}
}
```

```json title="Variable"
{
"representations": [
{
"__typename": "User",
"id": "5"
}
]
}
```

#### Using in tests and debugging

If you're writing integration tests for your subgraph, you can test the return value of the `_entities` field for various entity representations that your _other_ subgraphs use.

If you're developing your subgraph in your local environment, you can [mock the return value](https://www.apollographql.com/docs/apollo-server/testing/mocking/) of the `_entities` field for your _other_ subgraphs so you don't have to connect those subgraphs to their respective data stores.

## Custom directives in subgraphs

The method for defining custom directives differs slightly for a federated graph, and it also depends on the version of Apollo Server you're using.
Expand Down Expand Up @@ -382,4 +290,4 @@ const server = new ApolloServer({
});
```

Also make sure to read about the [gateway's support for custom directives](./gateway/#custom-directive-support).
Also make sure to read about the [gateway's support for custom directives](./router/#custom-directive-support).
Loading

0 comments on commit 187c6cc

Please sign in to comment.