Skip to content

feat(api): add Response.httpVersion() method#39434

Merged
dgozman merged 4 commits intomicrosoft:mainfrom
smckee-r7:response-http-version
Mar 3, 2026
Merged

feat(api): add Response.httpVersion() method#39434
dgozman merged 4 commits intomicrosoft:mainfrom
smckee-r7:response-http-version

Conversation

@smckee-r7
Copy link
Contributor

@smckee-r7 smckee-r7 commented Feb 26, 2026

Adds Response.httpVersion() to get the http version of a given response.
Issue: #39310

Previous PR #39309 was closed out with some comments. I've addressed the comments and opened a this new PR. This feature would be extremely useful to reduce bloat/boilerplate for our test suite.

Copy link
Member

@yury-s yury-s left a comment

Choose a reason for hiding this comment

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

The PR still has too many issues and lacking any tests. Unfortunately, I don't see it converging.

if (httpVersion === 'h2')
return 'HTTP/2.0';
return this._httpVersion;
if (httpVersion === 'h3')
Copy link
Member

Choose a reason for hiding this comment

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

this does not improve things and just adds confusion, don't change it

this._getResponseBodyCallback = getResponseBodyCallback;
this._request._setResponse(this);
this._httpVersion = httpVersion;
if (httpVersion)
Copy link
Member

Choose a reason for hiding this comment

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

only one client has it ready right away, make it call the new setter and remove the param

}

private _onResponse(response: network.Response) {
private async _onResponse(response: network.Response) {
Copy link
Member

Choose a reason for hiding this comment

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

we don't want async event handlers

async httpVersion(): Promise<string> {
return this._wrapApiCall(async () => {
return (await this._channel.httpVersion()).value;
}, { internal: true });
Copy link
Member

Choose a reason for hiding this comment

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

why do you have this here while it's already defined in the protocol yaml?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Your 100% right, my bad, I naively dived into this PR before understanding enough and misunderstood the architecture. Once I found the protocol.yml I added the definition there, but forgot to revert this change

@smckee-r7
Copy link
Contributor Author

The PR still has too many issues and lacking any tests. Unfortunately, I don't see it converging.

I've hopefully resolved your comments and added a basic test. I'm willing get this to a place you guys are happy with but if that's never going to happen, feel free to close the PR. However, not having this feature would be a shame since the only way to assert the httpVersion using HAR recording is currently awkward/heavy

});
if (event.metrics?.protocol)
response._setHttpVersion(event.metrics.protocol);
response._setHttpVersion(event.metrics?.protocol ?? null);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should call this from _onLoadingFailed as well, similar to calling _securityDetailsFinished().

}
if (event.protocolVersion)
response._setHttpVersion(event.protocolVersion);
response._setHttpVersion(event.protocolVersion ?? null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Call this from _onRequestFailed as well.

const httpVersion = response.httpVersion();
harEntry.request.httpVersion = httpVersion;
harEntry.response.httpVersion = httpVersion;
this._addBarrier(page || request.serviceWorker(), response.httpVersion().then(httpVersion => {
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't need two barriers for http version. Let's only have a single one in _onResponse() that sets both request and response http versions.

import { expect, test as it } from './pageTest';
import { TestServer } from '../config/testserver';

const { createHttp2Server } = require('../../packages/playwright-core/lib/utils');
Copy link
Contributor

Choose a reason for hiding this comment

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

New imports looks unused.

expect(request.existingResponse()).toBe(response);
});

it('should return http version', async ({ page, server }) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's add a test for a failing request - httpVersion() should not hang in this case. Consult Page.Events.RequestFailed from page-event-network.spec.ts to see how to trigger a failing request.

Copy link
Contributor Author

@smckee-r7 smckee-r7 Mar 3, 2026

Choose a reason for hiding this comment

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

Based on that test you mentioned, it shows that the Response object should be null if the request fails. This PR only exposes the httpVersion method on the response. Not sure how I'd test that exactly since the Response should be null.

I did briefly consider adding a httpVersion method to the Request but it didn't feel like it made sense. Since as far as I can tell, it's not available until a response payload is received anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point, you are right!

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@smckee-r7 smckee-r7 requested review from dgozman and yury-s March 3, 2026 12:43
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Test results for "tests 1"

7 failed
❌ [firefox-library] › library/har.spec.ts:883 › should not hang on slow chunked response @firefox-ubuntu-22.04-node20
❌ [webkit-library] › library/har.spec.ts:119 › should include redirectURL @webkit-ubuntu-22.04-node20
❌ [webkit-library] › library/har.spec.ts:615 › should have connection details for redirects @webkit-ubuntu-22.04-node20
❌ [webkit-library] › library/har.spec.ts:883 › should not hang on slow chunked response @webkit-ubuntu-22.04-node20
❌ [playwright-test] › playwright.spec.ts:877 › page.pause() should disable test timeout @macos-latest-node20
❌ [playwright-test] › reporter.spec.ts:251 › merged › should not have internal error when steps are finished after timeout @macos-latest-node20
❌ [playwright-test] › ui-mode-test-network-tab.spec.ts:371 › should not preserve selection across test runs @macos-latest-node20

5 flaky ⚠️ [chromium-library] › library/popup.spec.ts:260 › should not throw when click closes popup `@ubuntu-22.04-chromium-tip-of-tree`
⚠️ [chromium-library] › library/popup.spec.ts:260 › should not throw when click closes popup `@chromium-ubuntu-22.04-arm-node20`
⚠️ [firefox-library] › library/inspector/cli-codegen-1.spec.ts:1080 › cli codegen › should not throw csp directive violation errors `@firefox-ubuntu-22.04-node20`
⚠️ [firefox-library] › library/trace-viewer.spec.ts:1216 › should display language-specific locators `@firefox-ubuntu-22.04-node20`
⚠️ [webkit-library] › library/trace-viewer.spec.ts:1216 › should display language-specific locators `@webkit-ubuntu-22.04-node20`

38690 passed, 841 skipped


Merge workflow run.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Test results for "MCP"

2 failed
❌ [chrome] › mcp/roots.spec.ts:47 › check that trace is saved in workspace @mcp-windows-latest
❌ [chromium] › mcp/http.spec.ts:210 › http transport browser lifecycle (persistent) @mcp-macos-15

5209 passed, 171 skipped


Merge workflow run.

Copy link
Contributor

@dgozman dgozman left a comment

Choose a reason for hiding this comment

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

Looks great, thank you for the PR!

expect(request.existingResponse()).toBe(response);
});

it('should return http version', async ({ page, server }) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Good point, you are right!

@dgozman dgozman merged commit fd3cd92 into microsoft:main Mar 3, 2026
32 of 38 checks passed
smckee-r7 added a commit to smckee-r7/playwright that referenced this pull request Mar 4, 2026
For hanging requests in Firefox/WebKit, the HTTP version promise
never resolves, causing HAR flush to hang indefinitely. Remove
from barrier promises while keeping the non-blocking update.

Fixes issues introduced in microsoft#39434
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants