Skip to content

[🐛 Bug]: BidiCore does not send headers declared in wdio.conf.js on the upgrade GET request. #13153

@ntinkler-calendly

Description

@ntinkler-calendly

Have you read the Contributing Guidelines on issues?

WebdriverIO Version

8.38.2

Node.js Version

v18.14.0

Mode

WDIO Testrunner

Which capabilities are you using?

{
  browserName: 'chrome',
  webSocketUrl: true,
  acceptInsecureCerts: true,
  'cal:nodeOptions': { debug: true },
  'goog:chromeOptions': {
    extensions: [chromeExtension],
    args: ['--no-sandbox', '--disable-infobars']
  },
}

What happened?

We use CloudFlare to protect internal domains, including the domain for a selenium grid.

We have a header declared in wdio.conf.js to provide cf-access-token on all requests made by the driver to the grid. This has usually worked just fine - it's supported for standard requests, as well as cdp websockets.

ex: our WDIO config starts with:

exports.config = {
  //
  // ====================
  // Runner Configuration
  // ====================
  runner: 'local',
  hostname: 'cf.protected.domain',
  port: 443,
  path: '/wd/hub',
  protocol: 'https',
  headers: {
    'cf-access-token': token,
  }
  ...

I have been experimenting with the new Bidi protocol support, and when I run an unprotected selenium grid locally, things work just fine (I am able to connect successfully, calls work as expected).

However when I point at the protected grid, I started encountering 302 errors because the initial upgrade request does not contain the header declared in the conf file, see request captured with BurpSuite:

GET /session/eaf58f4c46c0085af16d64833dffd782/se/bidi HTTP/2
Host: cf.protected.domain
Sec-Websocket-Version: 13
Sec-Websocket-Key: VXb45CB2mKTB0Q9Itu73Yw==
Connection: Upgrade
Upgrade: websocket

I can manually patch BidiCore and pass the header into the WebSocket constructor here:

this.#ws = new Socket(this._webSocketUrl, opts) as WebSocket
and things work.

GET /session/c052b894e06f0d2e24215cba6b1ba7a2/se/bidi HTTP/2
Host: cf.protected.domain
Cf-Access-Token: ABCD...
Sec-Websocket-Version: 13
Sec-Websocket-Key: OJeok1BuGE69MPkIYsEipQ==
Connection: Upgrade
Upgrade: websocket

I am not entirely sure if this will cause issues with the folks who are using the runner: 'browser' configuration (I don't believe WebSocket accepts a header param in that instance) and I believe Bidi was intended to also support that case?

But as it stands - this was unexpected behavior when I have declared a "header" setting in the config.

What is your expected behavior?

Headers declared in wdio.conf.js are included in the GET request for Bidi socket upgrades.

How to reproduce the bug.

Create a wdio.conf.js file that declares a header option:

exports.config = {
  //
  // ====================
  // Runner Configuration
  // ====================
  runner: 'local',
  hostname: 'cf.protected.domain',
  port: 443,
  path: '/wd/hub',
  protocol: 'https',
  headers: {
    'cf-access-token': token,
  }
  ...

Make a request to a Bidi method

    const sessStatus = await browser.sessionStatus({});
    console.log(sessStatus);

Observe that the socket upgrade request does not include the header.

Relevant log output

[0-0] ----Debug session for chrome----
[0-0] 
[0-0] https://cf.protected.domain
[0-0] 
[0-0] 
[0-0] 2024-07-12T16:36:25.056Z DEBUG @wdio/runner: init remote session
[0-0] 2024-07-12T16:36:25.150Z DEBUG @wdio/runner: init remote session
[0-0] 2024-07-12T16:36:25.151Z INFO webdriver: Initiate new session using the WebDriver protocol
[0-0] 2024-07-12T16:36:25.151Z INFO @wdio/utils: Connecting to existing driver at https://cf.protected.domain:443/wd/hub
[0-0] 2024-07-12T16:36:25.294Z INFO webdriver: [POST] https://cf.protected.domain/wd/hub/session
[0-0] 2024-07-12T16:36:25.294Z INFO webdriver: DATA {
[0-0]   capabilities: {
[0-0]     alwaysMatch: {
[0-0]       browserName: 'chrome',
[0-0]       webSocketUrl: true,
[0-0]       acceptInsecureCerts: true,
[0-0]       'cal:nodeOptions': [Object],
[0-0]       'goog:chromeOptions': [Object]
[0-0]     },
[0-0]     firstMatch: [ {} ]
[0-0]   },
[0-0]   desiredCapabilities: {
[0-0]     browserName: 'chrome',
[0-0]     webSocketUrl: true,
[0-0]     acceptInsecureCerts: true,
[0-0]     'cal:nodeOptions': { debug: true },
[0-0]     'goog:chromeOptions': { extensions: [Array], args: [Array] }
[0-0]   }
[0-0] }
[0-0] RUNNING in chrome - file:///apps/wdio-e2e/src/specs/login.spec.ts
[0-0] 2024-07-12T16:36:30.119Z INFO webdriver: Register BiDi handler for session with id 6bc8d1a963f2eb8f225395327ff8cd68
[0-0] 2024-07-12T16:36:30.119Z INFO webdriver: Connect to webSocketUrl wss://cf.protected.domain/session/6bc8d1a963f2eb8f225395327ff8cd68/se/bidi
[0-0] /Users/n.tinkler/projects/calendly/client-core/node_modules/ws/lib/websocket.js:912
[0-0]       abortHandshake(
[0-0]       ^
[0-0] Error: Unexpected server response: 302
[0-0]     at ClientRequest.<anonymous> (/Users/n.tinkler/projects/calendly/client-core/node_modules/ws/lib/websocket.js:912:7)
[0-0]     at ClientRequest.emit (node:events:513:28)
[0-0]     at ClientRequest.emit (node:domain:489:12)
[0-0]     at HTTPParser.parserOnIncomingClient (node:_http_client:701:27)
[0-0]     at HTTPParser.parserOnHeadersComplete (node:_http_common:119:17)
[0-0]     at TLSSocket.socketOnData (node:_http_client:542:22)
[0-0]     at TLSSocket.emit (node:events:513:28)
[0-0]     at TLSSocket.emit (node:domain:489:12)
[0-0]     at addChunk (node:internal/streams/readable:324:12)
[0-0]     at readableAddChunk (node:internal/streams/readable:297:9)
2024-07-12T16:36:30.244Z DEBUG @wdio/local-runner: Runner 0-0 finished with exit code 1
[0-0] FAILED in chrome - file:///apps/wdio-e2e/src/specs/login.spec.ts

Code of Conduct

  • I agree to follow this project's Code of Conduct

Is there an existing issue for this?

  • I have searched the existing issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    Bug 🐛help wantedIssues that are free to take by anyone interested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions