Repository navigation
browser: add proxy option to browser contexts - #5924
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for configuring a Chromium context-level proxy via the k6 browser API by introducing a proxy option on browser.newContext() / browser.newPage() context options and wiring it to CDP Target.createBrowserContext parameters.
Changes:
- Introduces
proxyconfiguration (server,bypass) onBrowserContextOptions, including early validation thatproxy.serveris required whenproxyis provided. - Wires
proxyServerandproxyBypassListinto the CDPTarget.createBrowserContextcall when creating a new browser context. - Adds unit tests covering proxy mapping/parsing, CDP parameter wiring, and validation errors.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| internal/js/modules/k6/browser/common/browser.go | Validates proxy options and forwards proxy settings to CDP context creation. |
| internal/js/modules/k6/browser/common/browser_test.go | Adds unit tests ensuring proxy fields are sent (and omitted) correctly and invalid proxy config fails early. |
| internal/js/modules/k6/browser/common/browser_context_options.go | Extends context options with ProxyOptions and adds validation for required server. |
| internal/js/modules/k6/browser/browser/browser_mapping.go | Validates parsed proxy options when mapping JS values into Go options. |
| internal/js/modules/k6/browser/browser/browser_context_options_test.go | Adds JS-side parsing tests for proxy and integrates it into the âall optionsâ test. |
ðĄ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Thanks for your contribution ð Current tests only verify internals. Please remove all current tests and instead add an integration test in the tests/ pkg that runs a fake proxy server to test the behavior of using a proxy server + the data transferred with and without the proxy options set. LMK if you have any questions.
|
|
||
| const browserContextID cdp.BrowserContextID = "42" | ||
|
|
||
| ctx, cancel := context.WithCancel(context.Background()) |
There was a problem hiding this comment.
Please use t.Context() in all tests.
|
Addressed in 38d0792. Changes:
Ran:
|
| } | ||
| w.WriteHeader(resp.StatusCode) | ||
| _, err = io.Copy(w, resp.Body) | ||
| require.NoError(t, err) |
There was a problem hiding this comment.
Same: require.NoError in handler goroutine.
| ThroughProxy bool | ||
| } | ||
|
|
||
| func TestBrowserContextProxy(t *testing.T) { |
There was a problem hiding this comment.
Missing validation error test. Old unit tests covered "proxy without server" â now untested. Add a case: browser.newContext({ proxy: { bypass: 'foo' } }) asserting the error.
|
Addressed the latest review feedback in b81ec5c. The review threads are resolved now; could you take another look when you have a chance? |
|
Thanks, @nightt5879. Please check if the test errors are introduced by your changes or not. |
|
I checked the failing CI jobs to confirm whether they look related to this PR. The previous red jobs were the The failures I found were in existing HTTP/TLS/HTTP2-related tests, for example:
The common error pattern was around TLS/HTTP2 behavior under gotip, e.g. This PR only changes the browser context proxy implementation/tests, and in the same failed job the browser packages themselves passed, for example: So from the logs, I don't think those CI failures were introduced by this PR. They look like gotip / Go HTTP-TLS behavior changes affecting existing tests outside the browser proxy changes. Update after syncing with current
Once the Actions workflows are approved/rerun, I can re-check the new CI result. |
|
cc: @szkiba I've approved this PR. |
k6 2.1.0 Created-by: HarmonybrewBot Commit-by: HarmonybrewBot Merged-by: HarmonybrewBot Description: Created by `brew bump` --- Created with `brew bump-formula-pr`.<details> <summary>release notes</summary> <pre>k6 `v2.1.0` is here ð This release includes: - An opt-in feature-flag system â `--features`, the `K6_FEATURES` environment variable, and a `k6 features` discovery command â shipping with experimental native histograms for trend metrics as its first flag. - A context-level `proxy` option for browser contexts. - Subcommand discovery in `k6 x`, so binaries can report which extension commands they expose. ## Breaking changes There are no breaking changes in this release. ## New features ### `k6 cloud test list` command [#6007](grafana/k6#6007) A new `k6 cloud test` command group has been added, with a `k6 cloud test list` subcommand that lists the load tests of a Grafana Cloud k6 project. It complements the `k6 cloud project list` command introduced in v2.0.0. The project to list tests for is resolved in the following order: 1. The `--project-id` flag. 2. The `K6_CLOUD_PROJECT_ID` environment variable (cloud config `projectID`). 3. The default project of the configured stack, populated by `k6 cloud login`. Output defaults to a human-readable table. Pass `--json` to emit a JSON array instead, mirroring the format established by `k6 cloud project list`. ```shell k6 cloud test list k6 cloud test list --project-id 12345 k6 cloud test list --json ``` ### Feature flags and experimental native histograms [#6055](grafana/k6#6055), [#6056](grafana/k6#6056) k6 now has an opt-in feature-flag mechanism for trialing new, not-yet-stable behavior without affecting existing runs. Flags can be enabled on `k6 run` and `k6 cloud run` through the `--features` flag (comma-separated or repeated), the `K6_FEATURES` environment variable, or the `features` key in `config.json`. Enabled flags are surfaced as metric tags and propagated into archives and cloud workers so a run behaves consistently wherever it executes. Use `k6 features` (or `k6 features --json`) to discover the available flags and their lifecycle: ```console $ k6 features FEATURE LIFECYCLE DESCRIPTION native-histograms Experimental Use native histograms for trend metrics ``` The first flag shipped is `native-histograms`, an experimental flag that makes k6 use native histograms for trend metrics: ```shell k6 run --features native-histograms script.js # or K6_FEATURES=native-histograms k6 run script.js ``` ### Subcommand discovery in `k6 x` [#5972](grafana/k6#5972) Running `k6 x` now lists the available subcommands â both the ones baked into the binary and those advertised by the extension registry (official and community). Tab-completion surfaces the same set once the catalog has been cached locally by a prior `k6 x` run, so completion never blocks on the network. ```text $ k6 x ... Available Commands: agent Bootstrap an AI-assisted k6 testing workflow in any editor docs CLI k6 docs for AI agents and users explore Explore k6 extensions for Automatic Resolution mcp An MCP server for k6 for AI agents ``` This makes a k6 binary self-describing â particularly useful for AI agents driving k6, which previously had no way to introspect which extension subcommands were available. ### Browser context proxy option [#5924](grafana/k6#5924) Browser contexts can now be configured with a context-level `proxy` option, letting you route a context's traffic through a proxy without launching a custom-built binary or relying on environment proxy variables (which only affected k6's DevTools WebSocket connection). The option is wired to Chromium through `Target.createBrowserContext`, and invalid proxy configuration now fails early when `proxy.server` is missing. Thanks, @nightt5879! ```js const context = await browser.newContext({ proxy: { server: 'http://proxy.test:8080', bypass: 'localhost,127.0.0.1', }, }); ``` ### Browser `locator.isInViewport()` [#6023](grafana/k6#6023) A new `locator.isInViewport()` method reports whether an element intersects the browser viewport. It accepts an optional `ratio` (0 to 1) that sets how much of the element must be visible, defaulting to `0` so any visible pixel counts, matching Playwright's `toBeInViewport` semantics. The call waits for the element to attach, honoring the `timeout` option, then measures the intersection once. Thanks, @Anuragp22! ```js const button = page.locator('button#submit'); if (await button.isInViewport()) { await button.click(); } ``` ### Basic auth for the OpenTelemetry HTTP exporter [#5997](grafana/k6#5997) The OpenTelemetry output's HTTP exporter can now send HTTP Basic Auth credentials. Set them through the `K6_OTEL_HTTP_EXPORTER_USERNAME` and `K6_OTEL_HTTP_EXPORTER_PASSWORD` environment variables, or the `username` and `password` keys in the output config. ```shell K6_OTEL_HTTP_EXPORTER_USERNAME=user \ K6_OTEL_HTTP_EXPORTER_PASSWORD=secret \ k6 run --out opentelemetry script.js ``` ### `single()` selection helper in `k6/html` [#6002](grafana/k6#6002) `Selection.single(selector)` returns at most one matching element, backed by goquery's `Single` matcher for a faster lookup than `find()` when you only need the first match. Thanks, @rohan-patnaik! ```js import { parseHTML } from 'k6/html'; const doc = parseHTML(content); const title = doc.single('h1').text(); ``` ## UX improvements and enhancements - [#5971](grafana/k6#5971) Tags browser API failures with `module=browser` so that browser errors surfaced in Grafana Cloud Logs can be filtered separately from other log sources. ## Bug fixes - [#5794](grafana/k6#5794) Makes the `--vus` flag work as a standalone execution shortcut instead of being silently ignored when a script defines scenarios. Running `k6 run script.js --vus N` now creates a `shared-iterations` scenario with `N` VUs and `N` iterations, overriding any script-defined scenarios with a warning â consistent with how `--iterations`, `--duration`, and `--stages` already behave. Thanks, @Reranko05! - [#6013](grafana/k6#6013) Rejects invalid threshold percentiles. A percentile aggregation value outside the 0 to 100 range (or `NaN`) now fails parsing with a clear message instead of being silently accepted. Thanks, @immanuwell! - [#6011](grafana/k6#6011) Writes the on-disk k6 config file with owner-only permissions (`0o600`, inside a `0o700` directory). The file can hold the Grafana Cloud API token (`collectors.cloud.token`), so tightening it keeps other local users on shared hosts (CI runners, multi-user boxes, sidecar containers) from reading the token. Existing configs are upgraded on the next write, for example the next `k6 cloud login`. ## Maintenance and internal improvements - [#6033](grafana/k6#6033) Moves Docker Hub image publishing to a Google Artifact Registry mirror. - [#5953](grafana/k6#5953) Installs `s3cmd` via `apt` instead of `pip` to fix the `k6packager` image build. - [#6052](grafana/k6#6052) Fixes the browser end-to-end test workflow. - [#5984](grafana/k6#5984) Routes per-test logger output to the test instance instead of the global `logrus`, improving test isolation. - [#5985](grafana/k6#5985) Fixes the flaky `TestPageScreenshotFullpage` browser test. - [#5981](grafana/k6#5981) Lets Renovate track the Go minor version in the `setup-go` workflows. - [#5968](grafana/k6#5968) Honors the caller-pinned ref in the shared lint action. - [#6041](grafana/k6#6041), [#6054](grafana/k6#6054) Aligns the Go module directive and toolchain (1.25.0 / 1.25.11). - [#5967](grafana/k6#5967) Updates the release notes template after v2.0.0. - [#6015](grafana/k6#6015) Updates `golang.org/x/net` to `v0.55.0` [security]. - [#6026](grafana/k6#6026) Updates `golang.org/x/crypto` to `v0.52.0` [security]. - [#5962](grafana/k6#5962), [#6028](grafana/k6#6028) Updates `google.golang.org/grpc` to `v1.81.1`. - [#5960](grafana/k6#5960) Updates `grafana/shared-workflows/get-vault-secrets` to `v1.3.2`. - [#5958](grafana/k6#5958) Updates `grafana/shared-workflows/azure-trusted-signing` to `v1.0.2`. - [#5957](grafana/k6#5957) Updates `github/codeql-action` to `v4.35.4`. - [#5959](grafana/k6#5959) Updates `grafana/shared-workflows/dockerhub-login` to `v1.0.4`. - [#6009](grafana/k6#6009) Moves the browser `PageScreenshotOptions` parsing into the mapping layer. - [#5964](grafana/k6#5964) Adds the k6 feature-flags specification under `openspec/`. - [#6067](grafana/k6#6067) Forces the legacy `x/net/http2` implementation on the `gotip` CI test job. - [#6065](grafana/k6#6065) Lets Renovate update the `Dockerfile` on the v1.x branch. - [#6031](grafana/k6#6031) Updates `go.opentelemetry.io/otel` to `v1.44.0`. - [#6086](grafana/k6#6086) Updates `golang.org/x` dependencies (`crypto` to `v0.53.0`, `net` to `v0.56.0`, `term` to `v0.44.0`). - [#6061](grafana/k6#6061) Updates `golang.org/x/sync` to `v0.21.0`. - [#6030](grafana/k6#6030) Updates `github.com/tidwall/gjson` to `v1.19.0`. - [#6029](https: See merge request: Harmonybrew/homebrew-core!13169
What?
Adds a
proxyoption to browser context options so callers can configure Chromium context-level proxy settings with:The option is wired to CDP
Target.createBrowserContextthroughproxyServerandproxyBypassList, and invalid proxy options now fail early whenproxy.serveris missing.Why?
Browser traffic currently cannot be routed through a proxy via the browser API. Environment proxy variables only affect k6's DevTools WebSocket connection, and global Chromium launch args are not equivalent to a browser context option.
This makes proxy configuration explicit in browser context options and keeps the behavior scoped to the created browser context.
Checklist
make check) and all pass.Targeted tests run locally:
go test ./internal/js/modules/k6/browser/common ./internal/js/modules/k6/browser/browserChecklist: Documentation (only for k6 maintainers and if relevant)
Please do not merge this PR until the following items are filled out.
Related PR(s)/Issue(s)
Closes #4432