Releases: apollographql/router
v1.0.0-rc.1
Note
We're almost to 1.0! We've got a couple relatively small breaking changes to the configuration for this release (none to the API) that should be relatively easy to adapt to and a number of bug fixes and usability improvements.
❗ BREAKING ❗
Change headers
propagation configuration (PR #1795)
While it wasn't necessary today, we want to avoid a necessary breaking change in the future by proactively making room for up-and-coming work. We've therefore introduced another level into the headers
configuration with a request
object, to allow for a response
(see Issue #1284) to be an additive feature after 1.0.
A rough look at this should just be a matter of adding in request
and indenting everything that was inside it:
headers:
all:
+ request:
- remove:
named: "test"
The good news is that we'll have response
in the future! For a full set of examples, please see the header propagation documentation.
Bind the Sandbox on the same endpoint as the Supergraph, again (Issue #1785)
We have rolled back an addition that we released in this week's v1.0.0-rc.0
which allowed Sandbox (an HTML page that makes requests to the supergraph
endpoint) to be on a custom socket. In retrospect, we believe it was premature to make this change without considering the broader impact of this change which ultimately touches on CORS and some developer experiences bits. Practically speaking, we may not want to introduce this because it complicates the model in a number of ways.
For the foreseeable future, Sandbox will continue to be on the same listener address as the supergraph
listener.
It's unlikely anyone has really leaned into this much already, but if you've already re-configured sandbox
or homepage
to be on a custom listen
-er and/or path
in 1.0.0-rc.0
, here is a diff of what you should remove:
sandbox:
- listen: 127.0.0.1:4000
- path: /
enabled: false
homepage:
- listen: 127.0.0.1:4000
- path: /
enabled: true
Note this means you can either enable the homepage
, or the sandbox
, but not both.
By @o0Ignition0o in #1796
🚀 Features
Automatically check "Return Query Plans from Router" checkbox in Sandbox (Issue #1803)
When loading Sandbox, we now automatically configure it to toggle the "Request query plans from Router" checkbox to the enabled position which requests query plans from the Apollo Router when executing operations. These query plans are displayed in the Sandbox interface and can be seen by selecting "Query Plan Preview" from the drop-down above the panel on the right side of the interface.
🐛 Fixes
Fix --dev
mode when no configuration file is specified (Issue #1801) (Issue #1802)
We've reconciled an issue where the --dev
mode flag was being ignored when running the router without a configuration file. (While many use cases do require a configuration file, the Router actually doesn't need a confguration in many cases!)
Respect supergraph
's path
for Kubernetes deployment probes (Issue #1787)
If you've configured the supergraph
's path
property using the Helm chart, the liveness
and readiness probes now utilize these correctly. This fixes a bug where they continued to use the default path of /
and resulted in a startup failure.
By @damienpontifex in #1788
Get variable default values from the query for query plan condition nodes (PR #1640)
The query plan condition nodes, generated by the if
argument of the @defer
directive, were
not using the default value of the variable passed in as an argument.
This also fixes default value validations for non-@defer
'd queries.
Correctly hot-reload when changing the supergraph
's listen
socket (Issue #1814)
If you change the supergraph
's listen
socket while in --hot-reload
mode, the Router will now correctly pickup the change and bind to the new socket.
By @o0Ignition0o in #1815
🛠 Maintenance
Improve error message when querying non existent field Issue #1816
When querying a non-existent field you will get a better error message:
{
"errors": [
{
- "message": "invalid type error, expected another type than 'Named type Computer'"
+ "message": "Cannot query field \"xxx\" on type \"Computer\""
}
]
}
Update apollo-router-scaffold
to use the published apollo-router
crate PR #1782
Now that apollo-router
is released on crates.io, we have updated the project scaffold to rely on the published crate instead of Git tags.
By @o0Ignition0o in #1782
Refactor Configuration
validation Issue #1791
Instantiating Configuration
s is now fallible, because it will run consistency checks on top of the already run structure checks.
By @o0Ignition0o in #1794
Refactor response-formatting tests #1798
Rewrite the response-formatting tests to use a builder pattern instead of macros and move the tests to a separate file.
📚 Documentation
Add rustdoc
documentation to various modules (Issue #799)
Adds documentation for:
apollo-router/src/layers/instrument.rs
apollo-router/src/layers/map_first_graphql_response.rs
apollo-router/src/layers/map_future_with_request_data.rs
apollo-router/src/layers/sync_checkpoint.rs
apollo-router/src/plugin/serde.rs
apollo-router/src/tracer.rs
Fixed docs.rs
publishing error from our last release
During our last release we discovered for the first time that our documentation wasn't able to compile on the docs.rs website, leaving our documentation in a failed state.
While we've reconciled that particular problem, we're now being affected by this internal compiler errors (ICE) that is affecting anyone using 1.65.0-nightly
builds circa today. Since docs.rs uses nightly
for all builds, this means it'll be a few more days before we're published there.
With thanks to @SimonSapin in apollographql/federation-rs#185
v1.0.0-rc.0
Note
👋 We're at our release candidate stage but we still have a round of breaking changes and features in this release. Not much more after this! Those using the
apollo-router
as a library should be minimally impacted by Rust API changes in this1.0.0-rc.0
release, however there are notable changes to the configuration file and default values outlined below. We hope you'll appreciate the changes (including the secure defaults, flexibility and introduction of a--dev
mode). Thanks for your continued feedback and cooperation and please try out this release candidate! We will graduate to 1.0 as soon as possible! ✨
❗ BREAKING ❗
Note
We are entering our release candidate ("RC") stage and expect this to be the last of our breaking changes. Overall, most of the breaking changes in this release revolve around three key factors which were motivators for most of the changes:
- Having safe and security defaults which are suitable for production
- Polishing our YAML configuration ergonomics and patterns
- The introduction of a development mode activated with the
--dev
flagSee the full changelog below for details on these (including the "Features" section for the
--dev
changes!)
Adjusted socket ("listener") addresses for more secure default behaviors
- The Router will not listen on "all interfaces" in its default configuration (i.e., by binding to
0.0.0.0
). You may specify a specific socket by specifying theinterface:port
combination. If you desire behavior which binds to all interfaces, your configuration can specify a socket of0.0.0.0:4000
(for port4000
on all interfaces). - By default, Prometheus (if enabled) no longer listens on the same socket as the GraphQL socket. You can change this behavior by binding it to the same socket as your GraphQL socket in your configuration.
- The health check endpoint is no longer available on the same socket as the GraphQL endpoint (In fact, the health check suggestion has changed in ways that are described elsewhere in this release's notes. Please review them separately!)
Safer out-of-the box defaults with sandbox
and introspection
disabled (PR #1748)
To reflect the fact that it is not recomended to have introspection on in production (and since Sandbox uses introspection to power its development features) the sandbox
and introspection
configuration are now disabled unless you are running the Router with --dev
.
If you would like to force them on even when outside of --dev
mode, you can set them to true
explicitly in your YAML configuration:
sandbox:
enabled: true
supergraph:
introspection: true
Landing page ("home page") replaces Sandbox in default "production" mode (PR #1768)
As an extension of Sandbox and Introspection being disabled by default (see above), the Router now displays a simple landing page when running in its default mode. When you run the Apollo Router with the new --dev
flag (see "Features" section below) you will still see the existing "Apollo Studio Sandbox" experience.
We will offer additional options to customize the landing page in the future but for now you can disable the homepage entirely (leaving a very generic page with a GraphQL message) by disabling the homepage entirely in your configuration:
homepage:
enabled: false
By @o0Ignition0o in #1768
Listeners, paths and paths can be configured individually (Issue #1500)
It is now possible to individually configure the following features' socket/listener addresses (i.e., the IP address and port) in addition to the URL path:
- GraphQL execution (default:
http://127.0.0.1:4000/
) - Sandbox (default when using
--dev
:http://127.0.0.1:4000/
) - Prometheus (default when enabled:
http://127.0.0.1:9090/metrics
)
Examples of how to configure these can be seen in the YAML configuration overhaul section of this changelog (just below) as well as in our documentation.
By @o0Ignition0o in #1718
Overhaul/reorganization of YAML configuration (#1500)
To facilitate the changes in the previous bullet-points, we have moved configuration parameters which previously lived in the server
section to new homes in the configuration, including listen
, graphql_path
, landing_page
, and introspection
. Additionally, preview_defer_support
has moved, but is on by default and no longer necessary to be set explicitly unless you wish to disable it.
As another section (below) notes, we have removed the health check and instead recommend users to configure their health checks (in, e.g, Kubernetes, Docker, etc.) to use a simple GraphQL query: /?query={__typename}
. Read more about that in the other section, however this is reflected by its removal in the configuration.
To exemplify the changes, this previous configuration will turn into the configuration that follows it:
Before
server:
listen: 127.0.0.1:4000
graphql_path: /graphql
health_check_path: /health # Health check has been deprecated. See below.
introspection: false
preview_defer_support: true
landing_page: true
telemetry:
metrics:
prometheus:
enabled: true
After
# This section is just for Sandbox configuration
sandbox:
listen: 127.0.0.1:4000
path: /
enabled: false # Disabled by default, but on with `--dev`.
# This section represents general supergraph GraphQL execution
supergraph:
listen: 127.0.0.1:4000
path: /
introspection: false
# Can be removed unless it needs to be set to `false`.
preview_defer_support: true
# The health check has been removed. See the section below in the CHANGELOG
# for more information on how to configure health checks going forward.
# Prometheus scraper endpoint configuration
# The `listen` and `path` are not necessary if `127.0.0.1:9090/metrics` is okay
telemetry:
metrics:
prometheus:
listen: 127.0.0.1:9090
path: /metrics
enabled: true
By @o0Ignition0o in #1718
Environment variable expansion adjustments (#1759)
-
Environment expansions must be prefixed with
env.
. -
File expansions must be prefixed with
file.
. -
The "default" designator token changes from
:
to:-
. For example:${env.USER_NAME:Nandor}
=>${env.USER_NAME:-Nandor}
-
Failed expansions now result in an error
Previously expansions that failed due to missing environment variables were silently skipped. Now they result in a configuration error. Add a default value using the above syntax if optional expansion is needed.
By @BrynCooke in #1763
Dedicated health check endpoint removed with new recommendation to use /query={__typename}
query (Issue #1765)
We have removed the dedicated health check endpoint and now recommend users to configure their health checks (in, e.g, Kubernetes, Docker) to use a simple GraphQL query instead.
Use the following query with a content-type: application/json
header as a health check instead of /.well-known/apollo/server-health
:
/?query={__typename}
The Kubernetes documentation and related Helm charts have been updated to reflect this change.
Using this query has the added benefit of actually testing GraphQL. If this query returns with an HTTP 200 OK, it is just as reliable (and even more meaningful) than the previous /.well-known/apollo/server-health
endpoint. It's important to include the content-type: application/json
header to satisfy the Router's secure requirements that offer CSRF protections.
In the future, we will likely reintroduce a dedicated health check "liveliness" endpoint along with a meaningful "readiness" health check at the same time. In the meantime, the query above is technically more durable than the health check we offered previously.
By @abernix in https://github.com/apollographql/router/pull/TODO
Promote include_subgraph_errors
out of "experimental" status (Issue #1773)
The include_subraph_errors
plugin has been promoted out of "experimental" and will require a small configuration changes. For example:
-plugins:
- experimental.include_subgraph_errors:
- all: true # Propagate errors from all subraphs
- subgraphs:
- products: false # Do not propagate errors from the products subgraph
+include_subgraph_errors:
+ all: true # Propagate errors from all subraphs
+ subgraphs:
+ products: false # Do not propagate errors from the products subgraph
apollo-spaceport
and uplink
are now part of apollo-router
(Issue #491)
Instead of being dependencies, they are now part of the apollo-router
crate. They were not meant to be used independently.
By @SimonSapin in #1751
Remove over-exposed functions from the public API (PR #1746)
The following functions are only required for router implementation, so removing from external API:
subgraph::new_from_response
supergraph::n...
v1.0.0-alpha.3
👋 We're getting closer to our release candidate stages so there are far less breaking changes to the API in these versions, rather changes to configuration. We'll have a bit more in the next releases, but nothing as bad as the bumps from pre-v1.0.0-alpha.x versions. Thanks for your feedback and cooperation! ✨
❗ BREAKING ❗
Unified supergraph and execution response types (PR #1708)
apollo_router::services::supergraph::Response
and apollo_router::services::execution::Response
were two structs with identical fields and almost-identical methods. The main difference was that builders were fallible for the former but not the latter.
They are now the same type (with one location a type
alias of the other), with fallible builders. Callers may need to add either a operator ?
(in plugins) or an .unwrap()
call (in tests).
let response = execution::Response::builder()
.error(error)
.status_code(StatusCode::BAD_REQUEST)
.context(req.context)
- .build();
+ .build()?;
By @SimonSapin in #1708
Rename originating_request
to supergraph_request
on various plugin Request
structures (Issue #1713)
We feel that supergraph_request
makes it more clear that this is the request received from the client.
Prometheus is no longer defaulting to the GraphQL endpoint and listener address (Issue #1645)
The Router's Prometheus interface is now exposed at 127.0.0.1:9090/metrics
, rather than http://0.0.0.0:4000/plugins/apollo.telemetry/prometheus
. This should be both more secure and also more generally compatible with the default settings that Prometheus expects (which also uses port 9090
and just /metrics
as its defaults).
To expose to a non-localhost interface, it is necessary to explicitly opt-into binding to a socket address of 0.0.0.0:9090
(i.e., all interfaces on port 9090) or a specific available interface (e.g., 192.168.4.1
) on the host.
Have a look at the Features section (below) to learn how to customize the listen address and the path.
By @o0Ignition0o in #1654
🚀 Features
New plugin helper: map_first_graphql_response
(Issue #1564)
In supergraph and execution services, the service response contains not just one GraphQL response but a stream of them, in order to support features such as @defer
.
This new method of ServiceExt
and ServiceBuilderExt
in apollo_router::layers
wraps a service and calls a callback
when the first GraphQL response in the stream returned by the inner service becomes available. The callback can then access the HTTP parts (headers, status code, etc) or the first GraphQL response before returning them.
See the doc-comments in apollo-router/src/layers/mod.rs
for more.
By @SimonSapin in #1708
Users can customize the Prometheus listener address and URL path (Issue #1645)
You can now customize the Prometheus listener socket address and URL path in your YAML configuration:
telemetry:
metrics:
prometheus:
listen: 127.0.0.1:9090 # default
path: /metrics # default
enabled: true
By @o0Ignition0o in #1654
Add an apollo_router::graphql::ResponseStream
type alias (PR #1697)
It is equivalent to BoxStream<'static, graphql::Response>
and makes
some type signatures slightly simpler.
By @SimonSapin in #1697
🐛 Fixes
Fix metrics duration for router request (#1705)
With the introduction of BoxStream
for @defer
we introduced a bug when computing HTTP request duration metrics where we failed to wait for the first response in the BoxStream
.
Numerous fixes to preview @defer
query planning (Issue #1698)
Updated to Federation 2.1.2-alpha.0
which brings in a number of fixes for the preview @defer
support. These fixes include:
v1.0.0-alpha.2
👋 We're getting closer to our release candidate stages so there are far less breaking changes to the API in these versions, rather changes to configuration. We'll have a bit more in the next releases, but nothing as bad as the bumps from 0.15.x, through 0.16.0 and on to v1.0.0-alpha.0. Thanks for your feedback and cooperation! ✨
🚀 Features
Add service_name
and service_namespace
in telemetry.metrics.common
(Issue #1490)
Add service_name
and service_namespace
in telemetry.metrics.common
to reflect the same configuration than tracing.
telemetry:
metrics:
common:
# (Optional, default to "apollo-router") Set the service name to easily find metrics related to the apollo-router in your metrics dashboards
service_name: "apollo-router"
# (Optional)
service_namespace: "apollo"
🐛 Fixes
Fix distributed tracing header propagation (#1701)
Span context is now correctly propagated if you're trying to propagate tracing context to the router.
🛠 Maintenance
Replace startup
crate with ctor
crate (#1704)
At startup, the router registers plugins. The crate we used to use (startup
) has been yanked from crates.io and archived on GitHub. We're unsure why the package was yanked, but we've decided to move to the ctor
crate, which is more widely adopted and maintained.
This should fix the sudden errors for those who were using the router as a library or attempting to scaffold a new plugin using cargo scaffold
.
macOS: Update Xcode build version from 11.7 to 13.4 (PR #1702)
We now build our macOS binaries with Xcode 13.4 rather than 11.7. This may result in the Router not working on very old versions of macOS but we'd rather get this out of the way before CircleCI potentially deprecates 11.x images themselves and we're unable to test on them anymore.
v1.0.0-alpha.1
👋 We're getting closer to our release candidate stages so there are far less breaking changes to the API in this version, rather changes to configuration. We'll have a bit more in the next release, but nothing as bad as the bumps from 0.15.x, through 0.16.0 and on to v1.0.0-alpha.0
❗ BREAKING ❗
Preserve plugin response Vary
headers (PR #1660)
It is now possible to set a Vary
header in a client response from a plugin.
Note: This is a breaking change because the prior behaviour provided three default
Vary
headers and we've had to drop those to enable this change. If, after all plugin processing, there is noVary
header, the router will add one with a value of "origin
", as is best-practice for cache control headers with CORS.
Fix the supported defer specification version to 20220824
(PR #1652)
Since the router will ship before the @defer
specification is done, we add a parameter to the Accept
and Content-Type
headers to indicate which specification version is accepted.
The specification is fixed to graphql/graphql-spec@01d7b98
The router will now return a response with the status code 406 Not Acceptable
if the Accept
header does not match.
Change default enablement and promote experimental_defer_support
to preview_defer_support
(PR #1673)
Following up on a tremendous amount of work tracked in #80 - which brought various stages of @defer
support to the Router - this changes our designation of its status from "Experimental" to "Preview". It's worth noting that the @defer
specification has just graduated to "Stage 2 (Draft)" mode in the GraphQL Working Group, so changes may still be expected and there are two stages ahead. To help things progress:
-
We've lifted the previous requirement that users opt into defer support by setting
experimental_defer_support: true
in theserver
section of their configuration. It is now on by default. -
The option is now called
preview_defer_support
and it can be set tofalse
to specifically opt out of it existing at all. This might be desired if you would prefer that it not even show up in introspection or be possible to use even if a client requests it. -
Using
@defer
support requires clients set the appropriate HTTPaccept
header to use it. This puts the burden of understanding the risks of an early-preview on the clients who will need to consume the Router's responses. This is particularly important for clients who have long-lived support requirements (like native mobile apps).To see which headers are required, see #1648.
🚀 Features
Return an error when nullifying a non-null field (Issue #1304)
Nullability rules may remove parts of the response without indicating why. Error messages now indicate which part of the response triggered nullability rules.
router now provides TraceId (PR #1663)
If you need a reliable way to link together the various stages of pipeline processing, you can now use
apollo_router::tracer::TraceId::new()
🐛 Fixes
Docker images: Use absolute path for ENTRYPOINT
(PR #1684)
This restores the absolute path in ENTRYPOINT
in our Dockerfile
s (and published images) to allow users to change their working directory without consequence (and without needing to change it back to /dist
or override the entrypoint
).
Update our helm documentation to illustrate how to use our registry (#1643)
Updated documentation for helm charts to point to Apollo OCI registry.
Update router-bridge to query-planner
v2.1.1 (PR #1650 PR #1672)
The 2.1.0 release of the query planner comes with fixes to fragment interpretation and reduced memory usage.
The 2.1.1 release of the query planner fixes an issue with the @defer
directive's if
argument being ignored.
Do not nullify the entire query if the root operation is not present (PR #1674)
If a root field was not returned by the subgraph (e.g., when there's an error) the entire data object should not be nullified. Instead, the root field that should be null (unless it is non nullable).
Propagate graphql response regardless of the subgraph HTTP status code. (#1664)
Subgraph service calls no longer return an error when the received HTTP status code isn't 200. The GraphQL specification does not specify HTTP status code behavior since the GraphQL specification is transport agnostic.
This commit removes our HTTP status code check in the subgraph_service
.
By @o0Ignition0o in #1664
🛠 Maintenance
Remove cache layer (PR #1647)
ServiceBuilderExt::cache
was removed in v0.16.0. The unused CacheLayer
has now also been removed.
Refactor SupergraphService
(PR #1615)
The SupergraphService
code became too complex, so much that rustfmt
could not modify it anymore.
This breaks up the code in more manageable functions.
Conditionally use HorizontalPodAutoscaler
api version autoscaling/v2
(PR #1635)
The helm chart HorizontalPodAutoscaler
resource now will use API version autoscaling/v2
on Kubernetes hosts greater than 1.23 when the version is available. Fallback to version autoscaling/v2beta1
will still be utilised when this version is unavailable
By @damienpontifex in #1635
v1.0.0-alpha.0
❗ BREAKING ❗
Move cors
configuration from server
to root-level (PR #1586)
The cors
configuration is now located at the root-level of the configuration file, rather than inside server
.
For example:
- server:
- cors:
- origins:
- - https://yourdomain.com
+ cors:
+ origins:
+ - https://yourdomain.com
Exit the router after logging panic details (PR #1602)
The Router will now terminate in the (unlikely) case where it panics.
Rename the endpoint
parameter to graphql_path
(#1606)
The endpoint
parameter within the server
portion of the YAML configuration has been renamed to graphql_path
to more accurately reflect its behavior.
If you used this option, the necessary change would look like:
- server:
- endpoint: /graphql
+ server:
+ graphql_path: /graphql
Remove activate()
from the plugin API (PR #1569)
Recent changes to configuration reloading means that the only known consumer of this API, telemetry, is no longer using it.
Let's remove it since it's simple to add back if later required.
Rename TestHarness methods (PR #1579)
Some methods of apollo_router::TestHarness
were renamed:
extra_supergraph_plugin
→supergraph_hook
extra_execution_plugin
→execution_hook
extra_subgraph_plugin
→subgraph_hook
By @SimonSapin in #1579
Request
and Response
types from apollo_router::http_ext
are private (Issue #1589)
These types were wrappers around the Request
and Response
types from the http
crate.
Now the latter are used directly instead.
By @SimonSapin in #1589
Changes to IntoHeaderName
and IntoHeaderValue
(PR #1607)
Note: These types are typically not used directly, so we expect most user code to require no changes.
- Move from
apollo_router::http_ext
toapollo_router::services
- Rename to
TryIntoHeaderName
andTryIntoHeaderValue
- Make contents opaque
- Replace generic
From<T: Display>
conversion with multiple specific conversions
that are implemented byhttp::headers::Header{Name,Value}
.
By @SimonSapin in #1607
QueryPlan::usage_reporting
and QueryPlannerContent
are private (Issue #1556)
These items have been removed from the public API of apollo_router::services::execution
.
By @SimonSapin in #1568
Insert the full target triplet in the package name, and prefix with v
(Issue #1385)
The release tarballs now contain the full target triplet in their name along with a v
prefix to be consistent with our other packaging techniques (e.g., Rover).
For example:
router-0.16.0-x86_64-linux.tar.gz
becomesrouter-v0.16.0-x86_64-unknown-linux-gnu.tar.gz
router-0.16.0-x86_64-macos.tar.gz
becomesrouter-v0.16.0-x86_64-apple-darwin.tar.gz
router-0.16.0-x86_64-windows.tar.gz
becomesrouter-v0.16.0-x86_64-pc-windows-msvc.tar.gz
By @abernix and @Geal in #1433 (which re-lands work done in #1393)
Many structs and enums are now #[non_exhaustive]
(Issue #1550)
This means we may adjust struct
fields or enum
variants in additive ways in the future without breaking changes. To prepare for that eventuality:
- When using a struct pattern (such as for deconstructing a value into its fields),
use..
to allow further fields:
-let PluginInit { config, supergraph_sdl } = init;
+let PluginInit { config, supergraph_sdl, .. } = init;
- Use field access instead:
-let PluginInit { config, supergraph_sdl } = init;
+let config = init.config;
+let supergraph_sdl = init.supergraph_sdl;
- When constructing a struct, use a builder or constructor method instead of struct literal syntax:
-let error = graphql::Error {
- message: "something went wrong".to_string(),
- ..Default::default()
-};
+let error = graphql::Error::builder()
+ .message("something went wrong")
+ .build();
- When matching on an enum, add a wildcard match arm:
match error {
ApolloRouterError::StartupError => "StartupError",
ApolloRouterError::HttpServerLifecycleError => "HttpServerLifecycleError",
ApolloRouterError::NoConfiguration => "NoConfiguration",
ApolloRouterError::NoSchema => "NoSchema",
ApolloRouterError::ServiceCreationError(_) => "ServiceCreationError",
ApolloRouterError::ServerCreationError(_) => "ServerCreationError",
+ _ => "other error",
}
By @SimonSapin in #1614
Some error enums or variants were removed (Issue #81)
They were not used anymore in the public API (or at all).
By @SimonSapin in #1621
🚀 Features
Instrument the rhai plugin with a tracing span (PR #1598)
If you have an active rhai script in your router, you will now see a "rhai plugin" span in tracing.
🐛 Fixes
Only send one report for a response with deferred responses (PR #1576)
The router was sending one report per response (even deferred ones), while Studio was expecting one report for the entire
response. The router now sends one report which is inclusive of the latency of the entire operation.
Include formatted query plan when exposing the query plan (#1557)
Move the location of the text
field when exposing the query plan and fill it with a formatted query plan.
Change state machine log messages to trace
(#1578)
We no longer show internal state machine log events at the info
level since they are unnecessary during normal operation. They are instead emitted at the trace
level and can be enabled selectively using the --log trace
flag.
Formatting problem fix of scalar fields selected several times (PR #1583)
Fixed a bug where querying scalar fields several times would put null
s instead of expected values.
Fix typo on HTTP errors from subgraph (#1593)
Remove the closed parenthesis at the end of error messages resulting from HTTP errors from subgraphs.
By @nmoutschen in #1593
Only send one report for a response with deferred responses (PR #1596)
Deferred responses come as multipart/mixed
elements and are sent as individual HTTP response chunks. When a client receives one chunk,
that chunk should contain the next delimiter. This gives the client the ability to start processing the response instead of waiting for the
next chunk just for the delimiter.
Patch async-compression
to compress responses in streaming (PR #1604)
The async-compression
crate is a dependency used for HTTP response compression. Its implementation accumulates the entire compressed response in memory before sending it. However, this created problems for @defer
responses since we want those responses to come as soon as
possible, rather than waiting until the entire total response has been received and compressed.
Queries with @defer
must have the accept: multipart/mixed
header (PR #1610)
Since deferred responses can come back as multipart responses, we must check that the client supports that content-type
.
This will allow older clients to show a meaningful error message instead of a parsing error if the @defer
directive is
used but they don't support it.
🛠 Maintenance
Depend on published router-bridge
(PR #1613)
The router-bridge
package is now published which means the router
repository no longer depends on having Node.js installed to build.
By @o0Ignition0o in #1613
Re-organize our release steps check...
v0.16.0
We're getting closer and closer to our 1.0 release and with that we have a lot of polish that we're applying to our API to get it ready for it to be a durable surface area for our consumers to depend on. Due to various learnings we've had during the pre-1.0 phases of the Router, we are evolving our API to match what we now know.
We do not intend on doing this much moving around of things again soon, but anyone who has been following the repository the last couple weeks knows there has been a lot of activity and discussion about where things should live. This means that this release has an abnormally high number of breaking changes, though we believe you'll find most of them to be relatively straightforward to pivot away from.
Please review the full change log to get all the details, but for the most part the changes in this release consist of:
- a lot of renames of existing symbols
- the re-location of exported symbols to more appropriate modules
- the privatization of functions which we don't believe users needed directly (see below if any of these turn out to be a problem).
During each step of the migration, we recommend searching this changelog for a symbol to find advice on how to migrate it. We've tried to make the instructions and path forward as clear as possible.
- If you find yourself needing help migrating to the new patterns, please first take a close look at the examples provided in this change log and if you still need help, please open a discussion.
- If you find yourself unable to do something you had previously been able to do, please open an issue. Please make sure you include your use-case so we can understand better and document it for posterity!
We appreciate your patience working through these and we're excited for the steps ahead!
❗ BREAKING ❗
Remove QueryPlannerService
(PR #1552)
This service was redundant, since anything done as part of the QueryPlannerService
could be done either at the SupergraphService
or at the ExecutionService
level.
By @o0Ignition0o in #1552
Rename map_future_with_context
to map_future_with_request_data
(PR #1547)
The function is not very well named since it's in fact used to extract any data from a request for use in a future. This rename makes it clear.
Rename traffic shaping deduplication options (PR #1540)
In the traffic shaping module:
variables_deduplication
configuration option is renamed todeduplicate_variables
.query_deduplication
configuration option is renamed todeduplicate_query
.
- traffic_shaping:
- variables_deduplication: true # Enable the variables deduplication optimization
- all:
- query_deduplication: true # Enable query deduplication for all subgraphs.
- subgraphs:
- products:
- query_deduplication: false # Disable query deduplication for products.
+ traffic_shaping:
+ deduplicate_variables: true # Enable the variables deduplication optimization
+ all:
+ deduplicate_query: true # Enable query deduplication for all subgraphs.
+ subgraphs:
+ products:
+ deduplicate_query: false # Disable query deduplication for products.
Make query_plan_options
private and wrap QueryPlanContent
in an opaque type (PR #1486)
QueryPlanOptions::query_plan_options
is no longer public. If you still necessitate usage of this, please open an issue with your use case.
Removed delay_interval
in telemetry configuration. (PR #1498)
It was doing nothing.
telemetry:
metrics:
common:
# Removed, will now cause an error on Router startup:
delay_interval:
secs: 9
nanos: 500000000
By @SimonSapin in #1498
Remove telemetry configuration hot reloading (PR #1463)
Configuration hot reloading is not very useful for telemetry, and is the
source of regular bugs that are hard to fix.
This removes the support for configuration reloading entirely. Now, the
router will reject a configuration reload with an error log if the
telemetry configuration changed.
It is now possible to create a subscriber and pass it explicitely to the telemetry plugin
when creating it. It will then be modified to integrate the telemetry plugin's layer.
Reorder query planner execution (PR #1484)
Query planning is deterministic and only depends on the query, operation name and query planning
options. As such, we can cache the result of the entire process.
This changes the pipeline to apply query planner plugins between the cache and the bridge planner,
so those plugins will only be called once on the same query. If changes must be done per query,
they should happen in a supergraph service.
Remove Buffer
from Mock*Service
(PR #1440
This removes the usage of tower_test::mock::Mock
in mocked services because it isolated the service in a task
so panics triggered by mockall were not transmitted up to the unit test that should catch it.
This rewrites the mocked services API to remove the build()
method, and make them clonable if needed,
using an expect_clone
call with mockall.
Some items were renamed or moved (PR #1487 PR #1534 PR #1555 PR #1563)
At the crate root:
SchemaKind
→SchemaSource
SchemaKind::String(String)
→SchemaSource::Static { schema_sdl: String }
ConfigurationKind
→ConfigurationSource
ConfigurationKind::Instance
→ConfigurationSource::Static
ShutdownKind
→ShutdownSource
ApolloRouter
→RouterHttpServer
In the apollo_router::plugin::Plugin
trait:
router_service
→supergraph_service
In the apollo_router::services
module, to new public sub-modules:
SupergraphRequest
→supergraph::Request
SupergraphResponse
→supergraph::Response
ExecutionRequest
→execution::Request
ExecutionResponse
→execution::Response
SubgraphRequest
→subgraph::Request
SubgraphResponse
→subgraph::Response
For convenience, these new sub-modules each contain type aliases
base on their respective Request
and Response
types.
pub type BoxService = tower::util::BoxService<Request, Response, tower::BoxError>;
pub type BoxCloneService = tower::util::BoxCloneService<Request, Response, tower::BoxError>;
pub type ServiceResult = Result<Response, tower::BoxError>;
Migration example:
-use tower::util::BoxService;
-use tower::BoxError;
-use apollo_router::services::{RouterRequest, RouterResponse};
+use apollo_router::services::router;
-async fn example(service: BoxService<RouterRequest, RouterResponse, BoxError>) -> RouterResponse {
+async fn example(service: router::BoxService) -> router::Response {
- let request = RouterRequest::builder()/*…*/.build();
+ let request = router::Request::builder()/*…*/.build();
service.oneshot(request).await
}
By @SimonSapin in #1487, #1534, #1555, #1563
Some items were removed from the public API (PR #1487 PR #1535)
If you used some of them and don’t find a replacement,
please file an issue
with details about the use case.
apollo_router::Configuration::boxed
apollo_router::Configuration::is_compatible
apollo_router::errors::CacheResolverError
apollo_router::errors::JsonExtError
apollo_router::errors::ParsesError::print
apollo_router::errors::PlanError
apollo_router::errors::PlannerError
apollo_router::errors::PlannerErrors
apollo_router::errors::QueryPlannerError
apollo_router::errors::ServiceBuildError
apollo_router::json_ext
apollo_router::layers::ServiceBuilderExt::cache
apollo_router::mock_service!
apollo_router::plugins
apollo_router::plugin::plugins
apollo_router::plugin::PluginFactory
apollo_router::plugin::DynPlugin
apollo_router::plugin::Handler
apollo_router::plugin::test::IntoSchema
apollo_router::plugin::test::MockSubgraphFactory
apollo_router::plugin::test::PluginTestHarness
apollo_router::query_planner::QueryPlan::execute
apollo_router::services
apollo_router::Schema
By @SimonSapin...
v0.15.1
⚠️ SECURITY ⚠️
Landing page: Remove unsanitized example input
The default landing page contained HTML to display a sample curl
command which is made visible if the full landing page bundle could not be fetched from Apollo's CDN. The server's URL is directly interpolated into this command inside the browser from window.location.href
. On some older browsers such as IE11, this value is not URI-encoded. On such browsers, opening a malicious URL pointing at an Apollo Router could cause execution of attacker-controlled JavaScript. In this release, the fallback page does not display a curl
command.
More details are available at the security advisory.
Full Changelog: v0.15.0...v0.15.1
v0.15.0
❗ BREAKING ❗
CORS: Deprecate newly-added allow_any_header
option and return to previous behavior (PR https://github.com/apollographql/router/pull/1480)
We've re-considered and reverted changes we shipped in the last release with regards to how we handle the Access-Control-Request-Headers
request header and its corresponding Access-Control-Allow-Headers
response header. We've reverted to the previous releases' behavior, including the removal of the recently-added allow_any_header
option.
The previous default behavior was to reflect the client's Access-Control-Request-Headers
request header values back in the Access-Control-Allow-Headers
response header. This previous behavior is in fact a common default behavior in other CORS libraries as well, including the cors
Node.js package and we think it's worth keeping as it was previously, rather than requiring users to specify allow_any_header
for the majority of use cases. We believe this to be a safe and secure default that is also more user-friendly.
It is not typically necessary to change this default behavior, but if you wish to allow a more specific set of headers, you can disable the default header reflection and specify a list of headers using the allow_headers
option, which will allow only those headers in negotiating a response:
server:
cors:
allow_any_origin: true
# Including this `allow_headers` isn't typically necessary (can be removed) but
# will *restrict* the permitted Access-Control-Allow-Headers response values.
allow_headers:
- Content-Type
- Authorization
- x-my-custom-header
By @o0Ignition0o in #1480
Reference-counting for the schema string given to plugins (PR https://github.com/apollographql/router/pull/1462)
The type of the supergraph_sdl
field of the apollo_router::plugin::PluginInit
struct
was changed from String
to Arc<String>
.
This reduces the number of copies of this string we keep in memory, as schemas can get large.
By @SimonSapin in #1462
🐛 Fixes
Update span attributes to be compliant with the opentelemetry for GraphQL specs (PR https://github.com/apollographql/router/pull/1449)
Change attribute name query
to graphql.document
and operation_name
to graphql.operation.name
in spans.
Configuration handling enhancements (PR https://github.com/apollographql/router/pull/1454)
Router config handling now:
- Allows completely empty configuration without error.
- Prevents unknown tags at the root of the configuration from being silently ignored.
By @BrynCooke in #1454
📚 Documentation
CORS: Fix trailing slashes, and display defaults (PR https://github.com/apollographql/router/pull/1471)
The CORS documentation now displays a valid origins
configuration (without trailing slash!), and the full configuration section displays its default settings.
By @o0Ignition0o in #1471
Add helm OCI example (PR https://github.com/apollographql/router/pull/1457)
Update existing filesystem based example to illustrate how to do the same thing using our OCI stored helm chart.
v0.14.0
❗ BREAKING ❗
Regex allow_any_origin
behavior changed (PR #1444)
Setting allow_any_origin
to true in the router configuration would previously automatically mirror the requested headers.
If you relied on this behavior, you now also need to set allow_any_header
to true
, as explained in the CORS documentation.
server:
cors:
allow_any_origin: true
allow_any_header: true # mirror client's headers
The default CORS headers configuration of the router allows content-type
, apollographql-client-version
and apollographql-client-name
.
By @o0Ignition0o in #1444
Modify the plugin new
method to pass an initialisation structure (PR #1446)
This change alters the new
method for plugins to pass a PluginInit
struct.
We are making this change so that we can pass more information during plugin startup. The first change is that in addition to passing
the plugin configuration, we are now also passing the router supergraph sdl (Schema Definition Language) as a string.
There is a new example (supergraph_sdl
) which illustrates how to use this new capability.
Remove the generic stream type from RouterResponse
and ExecutionResponse
(PR #1420)
This generic type complicates the API with limited benefit because we use BoxStream
everywhere in plugins:
RouterResponse<BoxStream<'static, Response>>
->RouterResponse
ExecutionResponse<BoxStream<'static, Response>>
->ExecutionResponse
Remove the HTTP request from QueryPlannerRequest
(PR #1439)
The content of QueryPlannerRequest
is used as argument to the query planner and as a cache key,
so it should not change depending on the variables or HTTP headers.
Change PluggableRouterServiceBuilder
methods (PR #1437)
with_naive_introspection
and with_defer_support
where two parameter-less methods
of this builder that enabled boolean configuration flags.
They have been removed and replaced by with_configuration
which takes Arc<apollo_router::Configuration>
.
A Configuration
value can be created from various formats by deserializing with serde
.
The removed methods correspond to server.introspection
and server.experimental_defer_support
configuration keys respectively.
By @SimonSapin in #1437
Changes to the SchemaKind
enum (PR #1437)
The Instance
variant is replaced with a variant named String
that contains…
a String
instead of Box<apollo_router::Schema>
,
so you no longer need to parse the schema before giving it to the router.
Similarly, the Stream
variant now contains a stream of String
s
instead of a stream of already-parsed Schema
s.
By @SimonSapin in #1437
Schema
no longer implements FromStr
(PR #1437)
This means that str.parse::<apollo_router::Schema>()
is no longer available.
If you still need a parsed Schema
(see above),
use apollo_router::Schema(str, &configuration)
instead.
To use the default apollo_router::Configuration
you can call apollo_router::Schema(str, &Default::default())
.
By @SimonSapin in #1437
🚀 Features
Publish helm chart to OCI registry (PR #1447)
When we make a release, publish our helm chart to the same OCI registry that we use for our docker images.
For more information about using OCI registries with helm, see the helm documentation.
Configure Regex based CORS rules (PR #1444)
The router now supports regex based CORS rules, as explained in the docs
It also supports the allow_any_header
setting that will mirror client's requested headers.
server:
cors:
match_origins:
- "https://([a-z0-9]+[.])*api[.]example[.]com" # any host that uses https and ends with .api.example.com
allow_any_header: true # mirror client's headers
The default CORS headers configuration of the router allows content-type
, apollographql-client-version
and apollographql-client-name
.
By @o0Ignition0o in #1444
Add support of error section in telemetry to add custom attributes (PR #1443)
The telemetry is now able to hook at the error stage if router or a subgraph is returning an error. Here is an example of configuration:
telemetry:
metrics:
prometheus:
enabled: true
common:
attributes:
subgraph:
all:
errors: # Only works if it's a valid GraphQL error
include_messages: true # Will include the error message in a message attribute
extensions: # Include extension data
- name: subgraph_error_extended_type # Name of the attribute
path: .type # JSON query path to fetch data from extensions
Experimental support for the @defer
directive (PR #1182)
The router can now understand the @defer
directive, used to tag parts of a query so the response is split into
multiple parts that are sent one by one.
To activate it, add this option to the configuration file:
server:
experimental_defer_support: true
Rewrite the caching API (PR #1281)
This introduces a new asynchronous caching API that opens the way to multi level caching (in memory and
database). The API revolves around an Entry
structure that allows query deduplication and lets the
client decide how to generate the value to cache, instead of a complicated delegate system inside the
cache.
🐛 Fixes
Update serialization format for telemetry.tracing.otlp.grpc.metadata (PR #1391)
The metadata format now uses IndexMap<String, Vec<String>>
.
Update the scaffold template so it targets router v0.14.0 (PR #1431)
The cargo scaffold template will target the latest version of the router.
By @o0Ignition0o in #1248
Selection merging on non-object field aliases (PR #1406)
Fixed a bug where merging aliased fields would sometimes put null
s instead of expected values.
By @o0Ignition0o in #1432
A Rhai error instead of a Rust panic ([PR #1414 https://github.com//pull/1414))
In Rhai plugins, accessors that mutate the originating request are not available when in the subgraph phase. Previously, trying to mutate anyway would cause a Rust panic. This has been changed to a Rhai error instead.
By @SimonSapin in #1414
Optimizations (PR #1423)
- Do not clone the client request during query plan execution
- Do not clone the usage reporting
- Avoid path allocations when iterating over JSON values
The benchmarks show that this change brings a 23% gain in requests per second compared to the main branch.
do not perform nested fetches if the parent one returned null (PR #1332
In a query of the form:
mutation {
mutationA {
mutationB
}
}
If mutationA
returned null, we should not execute mutationB
.
🛠 Maintenance
📚 Documentation
Updates wording and formatting of README.md
By @EverlastingBugstopper in #1445
What's Changed
- CI: Upgrade the macOS image version by @SimonSapin in #1418
- Remove the ...