Skip to content

Conversation

@mskorokhodov
Copy link
Collaborator

Background

  • Old lab has headers object provided in order to add them to request

Description

  • Implemented headers object in new lab preflight

Checklist

  • Input validation
  • Output encoding
  • Authentication management
  • Session management
  • Access control
  • Cryptographic practices
  • Error handling and logging
  • Data protection
  • Communication security
  • System configuration
  • Database security
  • File management
  • Memory management
  • Testing

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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

  • Preflight Header Support: The preflight script environment now includes a headers object, allowing users to programmatically set HTTP headers that will be applied to subsequent network requests.
  • Header Propagation and Merging: Headers defined in the preflight script are collected and merged with any operation-specific headers, ensuring a comprehensive set of headers is applied to both HTTP and WebSocket requests.
  • Enhanced Preflight Logging: New info and system log levels have been introduced and styled for better visibility of preflight execution details, including a summary of the headers generated by the preflight script.

🧠 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 Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 22, 2025

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

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 ↗︎

@github-actions
Copy link
Contributor

github-actions bot commented Dec 22, 2025

📚 Storybook Deployment

The latest changes are available as preview in: https://pr-7453.hive-storybook.pages.dev

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To support multiple values for the same header (e.g., Set-Cookie), this type should be string[][] instead of Record<string, string>. This allows preserving all header values from the preflight script.

Suggested change
headers?: Record<string, string>;
headers?: string[][];

Comment on lines +334 to +359
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,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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));
      }

Comment on lines 371 to 373
connectionParams: {
...headers,
...mergedHeaders,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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()),

Comment on lines 436 to 439
headers: {
...headers,
...mergedHeaders,
'Content-Type': 'application/json',
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The fetch API can consume the Headers object directly. This is the key to preserving multiple header values. We also need to make sure the Content-Type is set.

        headers: (() => {
          mergedHeaders.set('Content-Type', 'application/json');
          return mergedHeaders;
        })(),

error?: string;
logs: LaboratoryPreflightLog[];
env: LaboratoryEnv;
headers: Record<string, string>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
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()) });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

Suggested change
self.postMessage({ type: 'result', env: env, headers: Object.fromEntries(lab.headers.entries()) });
self.postMessage({ type: 'result', env: env, headers: Array.from(lab.headers.entries()) });

Comment on lines +179 to +177
if (Object.keys(data.headers).length > 0) {
logs.push({
level: 'system',
message: [`Headers:\n${JSON.stringify(data.headers, null, 2)}`],
createdAt: new Date().toISOString(),
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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: {},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To align with the recommended change of the headers type to string[][], the default value in case of an error should be an empty array.

Suggested change
headers: {},
headers: [],

@github-actions
Copy link
Contributor

github-actions bot commented Dec 22, 2025

🐋 This PR was built and pushed to the following Docker images:

Targets: build

Platforms: linux/amd64

Image Tag: a5c356673e557e495ebef138e78b032df430b2bc

@github-actions
Copy link
Contributor

github-actions bot commented Dec 22, 2025

💻 Website Preview

The latest changes are available as preview in: https://pr-7453.hive-landing-page.pages.dev

@mskorokhodov mskorokhodov force-pushed the enhancement/new-lab-preflight-headers branch from 9b7e432 to 8f86a6c Compare December 22, 2025 15:31
@n1ru4l n1ru4l merged commit d00dd22 into main Jan 7, 2026
25 of 26 checks passed
@n1ru4l n1ru4l deleted the enhancement/new-lab-preflight-headers branch January 7, 2026 12:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants