-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New error extension http
for setting status/headers in context, resolvers
#6857
New error extension http
for setting status/headers in context, resolvers
#6857
Conversation
✅ Deploy Preview for apollo-server-docs ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 1f44004:
|
8962d40
to
e6f450c
Compare
…olvers You can now add a `Partial<HTTPGraphqlHead>` as an `http` error extension, which provides an easier way of setting HTTP response headers or status codes. These are honored when thrown from resolvers and `context` functions (and are also used internally to implement bad request errors etc). Multiple resolver errors can have `http` extensions to set status code and distinct headers separately; we do not commit to the semantics of what happens if multiple errors set the status code or set the same header. Now that you have more control over `context` error handling, simplify the default behavior: if the error thrown from `context` is not a `GraphQLError` with an `http` extension with a `status`, the default status code is 500 rather than sometimes being 400 based on `extensions.code`. Only prepend `Context creation failed: ` to the error message if the error is not already a GraphQLError. This still keeps the helpful message for developers while allowing you to remove it if you don't want it to be visible in your app. Fixes #6140. Fixes #5636. Fixes #6840.
e6f450c
to
d44b9e0
Compare
http
for setting status/headers in context, resolvers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested some changes for tone :)
Co-authored-by: Rose M Koron <[email protected]>
Co-authored-by: Rose M Koron <[email protected]>
Co-authored-by: Rose M Koron <[email protected]>
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to version-4, this PR will be updated.⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ `version-4` is currently in **pre mode** so this branch has prereleases rather than normal releases. If you want to exit prereleases, run `changeset pre exit` on `version-4`.⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️ # Releases ## @apollo/[email protected] ### Patch Changes - [#6857](#6857) [`15b1cb2e9`](15b1cb2) Thanks [@glasser](https://github.com/glasser)! - Errors thrown in resolvers and context functions can use `extensions.http` to affect the response status code and headers. The default behavior when a context function throws is now to always use status code 500 rather than comparing `extensions.code` to `INTERNAL_SERVER_ERROR`. - Updated dependencies \[[`15b1cb2e9`](15b1cb2)]: - @apollo/[email protected] ## @apollo/[email protected] ### Patch Changes - [#6857](#6857) [`15b1cb2e9`](15b1cb2) Thanks [@glasser](https://github.com/glasser)! - Errors thrown in resolvers and context functions can use `extensions.http` to affect the response status code and headers. The default behavior when a context function throws is now to always use status code 500 rather than comparing `extensions.code` to `INTERNAL_SERVER_ERROR`. Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
There are three ways to change an HTTP status code or set custom response headers, you can: throw an error in a resolver, throw an error in your `context` function, or write a [plugin](/apollo-server/integrations/plugins). | ||
|
||
While Apollo Server does enable you to set HTTP status codes based on errors thrown by resolvers, best practices for GraphQL over HTTP encourage sending 200 whenever an operation executes. So, we don't recommend using this mechanism in resolvers, just in the `context` function or in a plugin hooking into an early stage of the request pipeline. | ||
|
||
Be aware that GraphQL client libraries might not treat all response status codes the same, so it will be up to your team to decide which patterns to use. | ||
|
||
To change the HTTP status code and response headers based on an error thrown in either a resolver or `context` function, throw a `GraphQLError` with an `http` extension, like so: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@glasser Maybe we should present the resolver example after the plugin example if it's not our official recommendation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, my intention is mostly to say that setting the status code from errors is bad, less so than headers.
@@ -450,6 +450,33 @@ context: async () => ({ | |||
} | |||
``` | |||
|
|||
#### Throwing errors in `context` | |||
|
|||
By default, if your `context` function throws an error, Apollo Server returns that error to the user in a JSON response with an HTTP status code of 500. If the thrown error is not a `GraphQLError`, the error's message will be prepended with `"Context creation failed: "`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra whitespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After the colon in the string? That's intentional and accurate.
I see an extra space after JSON, I can fix that though I don't think it makes a difference when rendered...
In Apollo Server 3, if your `context` function throws, then the string `"Context creation failed: "` is *always* prepended to its message, and the error is rendered with HTTP status code 500 (if the error is a GraphQLError with `extensions.code` equal to `INTERNAL_SERVER_ERROR`) or 400. You cannot select a different HTTP status code or control HTTP response headers. | ||
|
||
In Apollo Server 4, if either the `resolveOperation` or `execute` function throws an error, that error is rendered with the HTTP status code 500 (rather than 400). Note that the `execute` function commonly returns a non-empty list of errors rather than throwing an explicit error. | ||
|
||
In Apollo Server 4, if your `context` function throws, the string `"Context creation failed: "` is only prepended to the message if the thrown error was not a `GraphQLError`. There is no special-casing of `extensions.code`; instead, you can use [`extensions.http`](./data/errors/#setting-http-status-code-and-headers) to set the HTTP status code or headers. If this extension is not provided, the status code defaults to 500 (not 400). | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 2 paragraphs about errors thrown during context creation seem oddly broken up by this paragraph between them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. Also resolveOperation
isn't actually a thing.
You can now add a
Partial<HTTPGraphqlHead>
as anhttp
errorextension, which provides an easier way of setting HTTP response headers
or status codes. These are honored when thrown from resolvers and
context
functions (and are also used internally to implement badrequest errors etc).
Multiple resolver errors can have
http
extensions to set status codeand distinct headers separately; we do not commit to the semantics of
what happens if multiple errors set the status code or set the same
header.
Now that you have more control over
context
error handling, simplifythe default behavior: if the error thrown from
context
is not aGraphQLError
with anhttp
extension with astatus
, the defaultstatus code is 500 rather than sometimes being 400 based on
extensions.code
.Only prepend
Context creation failed:
to the error message if theerror is not already a GraphQLError. This still keeps the helpful
message for developers while allowing you to remove it if you don't want
it to be visible in your app.
Fixes #6140. Fixes #5636. Fixes #6840.