-
Notifications
You must be signed in to change notification settings - Fork 125
Enhancement: preflight to provide headers #7453
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
Conversation
Summary of ChangesHello @mskorokhodov, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces the capability for preflight scripts within the laboratory environment to define and manage HTTP headers. It integrates these preflight-generated headers into the request execution flow, ensuring they are applied to subsequent HTTP and WebSocket operations. This enhancement provides greater control and flexibility for users to customize network requests, aligning the new laboratory experience with existing functionalities. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🚀 Snapshot Release (
|
| Package | Version | Info |
|---|---|---|
@graphql-hive/apollo |
0.46.0-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
@graphql-hive/cli |
0.57.0-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
@graphql-hive/core |
0.19.0-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
@graphql-hive/envelop |
0.40.1-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
@graphql-hive/yoga |
0.46.1-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
hive |
8.14.0-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
hive-apollo-router-plugin |
2.3.6-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
hive-console-sdk-rs |
0.2.3-alpha-20251222153343-a5c356673e557e495ebef138e78b032df430b2bc |
npm ↗︎ unpkg ↗︎ |
📚 Storybook DeploymentThe latest changes are available as preview in: https://pr-7453.hive-storybook.pages.dev |
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.
Code Review
This pull request adds the ability to set headers from the preflight script. The implementation is solid and the changes are consistent across the affected files. I've found a potential correctness issue regarding handling of HTTP headers with multiple values (like Set-Cookie) and have provided a series of suggestions to address it. The proposed changes involve using string[][] to represent headers and leveraging the standard Headers object to correctly merge and use them in fetch requests. Other than that, the code looks good.
| endpoint: string, | ||
| options?: { | ||
| env?: LaboratoryEnv; | ||
| headers?: Record<string, string>; |
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.
| let env: LaboratoryEnv; | ||
| let headers: Record<string, string>; | ||
|
|
||
| if (options?.env) { | ||
| env = options.env; | ||
| headers = options.headers ?? {}; | ||
| } else { | ||
| const preflightResult = await props.preflightApi?.runPreflight?.(); | ||
| env = preflightResult?.env ?? { variables: {} }; | ||
| headers = preflightResult?.headers ?? {}; | ||
| } | ||
|
|
||
| if (env && Object.keys(env.variables).length > 0) { | ||
| props.envApi?.setEnv(env); | ||
| } else { | ||
| env = props.envApi?.env ?? { variables: {} }; | ||
| } | ||
|
|
||
| const headers = activeOperation.headers | ||
| const parsedHeaders = activeOperation.headers | ||
| ? JSON.parse(handleTemplate(activeOperation.headers, env)) | ||
| : {}; | ||
|
|
||
| const mergedHeaders = { | ||
| ...headers, | ||
| ...parsedHeaders, | ||
| }; |
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.
To correctly handle multiple header values, the headers variable should be typed as string[][]. The merging logic should then use the Headers object to preserve these multiple values. This mergedHeaders object will be a Headers instance, and subsequent comments will adjust its usage for WebSocket connections and fetch requests.
This change ensures that headers like Set-Cookie are not lost during the merging process.
let env: LaboratoryEnv;
let headers: string[][];
if (options?.env) {
env = options.env;
headers = (options.headers as string[][] | undefined) ?? [];
} else {
const preflightResult = await props.preflightApi?.runPreflight?.();
env = preflightResult?.env ?? { variables: {} };
headers = preflightResult?.headers ?? [];
}
if (env && Object.keys(env.variables).length > 0) {
props.envApi?.setEnv(env);
} else {
env = props.envApi?.env ?? { variables: {} };
}
const parsedHeaders = activeOperation.headers
? JSON.parse(handleTemplate(activeOperation.headers, env))
: {};
const mergedHeaders = new Headers(headers);
for (const [key, value] of Object.entries(parsedHeaders)) {
mergedHeaders.set(key, String(value));
}| connectionParams: { | ||
| ...headers, | ||
| ...mergedHeaders, | ||
| }, |
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.
Since mergedHeaders is now a Headers object, it needs to be converted to a plain object for the graphql-ws connection parameters. Note that Object.fromEntries(mergedHeaders.entries()) will lose multiple values for the same header, which is a limitation for WebSocket connection headers here, but it's better to be explicit about it.
connectionParams: Object.fromEntries(mergedHeaders.entries()),| headers: { | ||
| ...headers, | ||
| ...mergedHeaders, | ||
| 'Content-Type': 'application/json', | ||
| }, |
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.
| error?: string; | ||
| logs: LaboratoryPreflightLog[]; | ||
| env: LaboratoryEnv; | ||
| headers: Record<string, string>; |
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.
Using Record<string, string> for headers will cause issues with headers that can appear multiple times, like Set-Cookie. The Headers API handles this, and it can be converted to string[][] which preserves all values. I recommend changing this type to string[][] to correctly support this.
| headers: Record<string, string>; | |
| headers: string[][]; |
| await new AsyncFunction('lab', 'CryptoJS', 'with(lab){' + event.data.script + '}')(lab, CryptoJS); | ||
| self.postMessage({ type: 'result', env: env }); | ||
| self.postMessage({ type: 'result', env: env, headers: Object.fromEntries(lab.headers.entries()) }); |
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.
To align with using string[][] for headers and to preserve multiple values for the same header key, Array.from(lab.headers.entries()) should be used instead of Object.fromEntries. This will correctly serialize the Headers object.
| self.postMessage({ type: 'result', env: env, headers: Object.fromEntries(lab.headers.entries()) }); | |
| self.postMessage({ type: 'result', env: env, headers: Array.from(lab.headers.entries()) }); |
| if (Object.keys(data.headers).length > 0) { | ||
| logs.push({ | ||
| level: 'system', | ||
| message: [`Headers:\n${JSON.stringify(data.headers, null, 2)}`], | ||
| createdAt: new Date().toISOString(), | ||
| }); | ||
| } |
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.
With data.headers now being string[][], the condition to check for presence of headers should be data.headers.length > 0. For logging purposes, converting it back to an object using Object.fromEntries is acceptable for readability, even if it might not show all values for a multi-valued header in the log output.
| if (Object.keys(data.headers).length > 0) { | |
| logs.push({ | |
| level: 'system', | |
| message: [`Headers:\n${JSON.stringify(data.headers, null, 2)}`], | |
| createdAt: new Date().toISOString(), | |
| }); | |
| } | |
| if (data.headers.length > 0) { | |
| logs.push({ | |
| level: 'system', | |
| message: [`Headers:\n${JSON.stringify(Object.fromEntries(data.headers), null, 2)}`], | |
| createdAt: new Date().toISOString(), | |
| }); | |
| } |
| error: error.message, | ||
| logs, | ||
| env, | ||
| headers: {}, |
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.
|
🐋 This PR was built and pushed to the following Docker images: Targets: Platforms: Image Tag: |
💻 Website PreviewThe latest changes are available as preview in: https://pr-7453.hive-landing-page.pages.dev |
9b7e432 to
8f86a6c
Compare
8f86a6c to
a5c3566
Compare
Background
Description
Checklist