feat(response): expose connection details in API (#7150)
This commit is contained in:
parent
5e471a3ece
commit
219e5138be
|
|
@ -48,6 +48,27 @@ Contains a boolean stating whether the response was successful (status in the ra
|
|||
|
||||
Returns the matching [Request] object.
|
||||
|
||||
## async method: Response.securityDetails
|
||||
- returns: <[null]|[Object]>
|
||||
- `issuer` <[string]> Common Name component of the Issuer field.
|
||||
from the certificate. This should only be used for informational purposes. Optional.
|
||||
- `protocol` <[string]> The specific TLS protocol used. (e.g. `TLS 1.3`). Optional.
|
||||
- `subjectName` <[string]> Common Name component of the Subject
|
||||
field from the certificate. This should only be used for informational purposes. Optional.
|
||||
- `validFrom` <[int]> Unix timestamp (in seconds) specifying
|
||||
when this cert becomes valid. Optional.
|
||||
- `validTo` <[int]> Unix timestamp (in seconds) specifying
|
||||
when this cert becomes invalid. Optional.
|
||||
|
||||
Returns SSL and other security information.
|
||||
|
||||
## async method: Response.serverAddr
|
||||
- returns: <[null]|[Object]>
|
||||
- `ipAddress` <[string]> IPv4 or IPV6 address of the server.
|
||||
- `port` <[int]>
|
||||
|
||||
Returns the IP address and port of the server.
|
||||
|
||||
## method: Response.status
|
||||
- returns: <[int]>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import { URLSearchParams } from 'url';
|
|||
import * as channels from '../protocol/channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Frame } from './frame';
|
||||
import { Headers, WaitForEventOptions } from './types';
|
||||
import { Headers, RemoteAddr, SecurityDetails, WaitForEventOptions } from './types';
|
||||
import fs from 'fs';
|
||||
import * as mime from 'mime';
|
||||
import { isString, headersObjectToArray, headersArrayToObject } from '../utils/utils';
|
||||
|
|
@ -325,6 +325,14 @@ export class Response extends ChannelOwner<channels.ResponseChannel, channels.Re
|
|||
frame(): Frame {
|
||||
return this._request.frame();
|
||||
}
|
||||
|
||||
async serverAddr(): Promise<RemoteAddr|null> {
|
||||
return (await this._channel.serverAddr()).value || null;
|
||||
}
|
||||
|
||||
async securityDetails(): Promise<SecurityDetails|null> {
|
||||
return (await this._channel.securityDetails()).value || null;
|
||||
}
|
||||
}
|
||||
|
||||
export class WebSocket extends ChannelOwner<channels.WebSocketChannel, channels.WebSocketInitializer> implements api.WebSocket {
|
||||
|
|
|
|||
|
|
@ -111,3 +111,6 @@ export type SelectorEngine = {
|
|||
*/
|
||||
queryAll(root: HTMLElement, selector: string): HTMLElement[];
|
||||
};
|
||||
|
||||
export type RemoteAddr = channels.RemoteAddr;
|
||||
export type SecurityDetails = channels.SecurityDetails;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,14 @@ export class ResponseDispatcher extends Dispatcher<Response, channels.ResponseIn
|
|||
async body(): Promise<channels.ResponseBodyResult> {
|
||||
return { binary: (await this._object.body()).toString('base64') };
|
||||
}
|
||||
|
||||
async securityDetails(): Promise<channels.ResponseSecurityDetailsResult> {
|
||||
return { value: await this._object.securityDetails() || undefined };
|
||||
}
|
||||
|
||||
async serverAddr(): Promise<channels.ResponseServerAddrResult> {
|
||||
return { value: await this._object.serverAddr() || undefined };
|
||||
}
|
||||
}
|
||||
|
||||
export class RouteDispatcher extends Dispatcher<Route, channels.RouteInitializer> implements channels.RouteChannel {
|
||||
|
|
|
|||
|
|
@ -2372,6 +2372,8 @@ export type ResponseInitializer = {
|
|||
export interface ResponseChannel extends Channel {
|
||||
body(params?: ResponseBodyParams, metadata?: Metadata): Promise<ResponseBodyResult>;
|
||||
finished(params?: ResponseFinishedParams, metadata?: Metadata): Promise<ResponseFinishedResult>;
|
||||
securityDetails(params?: ResponseSecurityDetailsParams, metadata?: Metadata): Promise<ResponseSecurityDetailsResult>;
|
||||
serverAddr(params?: ResponseServerAddrParams, metadata?: Metadata): Promise<ResponseServerAddrResult>;
|
||||
}
|
||||
export type ResponseBodyParams = {};
|
||||
export type ResponseBodyOptions = {};
|
||||
|
|
@ -2383,6 +2385,29 @@ export type ResponseFinishedOptions = {};
|
|||
export type ResponseFinishedResult = {
|
||||
error?: string,
|
||||
};
|
||||
export type ResponseSecurityDetailsParams = {};
|
||||
export type ResponseSecurityDetailsOptions = {};
|
||||
export type ResponseSecurityDetailsResult = {
|
||||
value?: SecurityDetails,
|
||||
};
|
||||
export type ResponseServerAddrParams = {};
|
||||
export type ResponseServerAddrOptions = {};
|
||||
export type ResponseServerAddrResult = {
|
||||
value?: RemoteAddr,
|
||||
};
|
||||
|
||||
export type SecurityDetails = {
|
||||
issuer?: string,
|
||||
protocol?: string,
|
||||
subjectName?: string,
|
||||
validFrom?: number,
|
||||
validTo?: number,
|
||||
};
|
||||
|
||||
export type RemoteAddr = {
|
||||
ipAddress: string,
|
||||
port: number,
|
||||
};
|
||||
|
||||
// ----------- WebSocket -----------
|
||||
export type WebSocketInitializer = {
|
||||
|
|
|
|||
|
|
@ -1927,6 +1927,31 @@ Response:
|
|||
returns:
|
||||
error: string?
|
||||
|
||||
securityDetails:
|
||||
returns:
|
||||
value: SecurityDetails?
|
||||
|
||||
serverAddr:
|
||||
returns:
|
||||
value: RemoteAddr?
|
||||
|
||||
|
||||
SecurityDetails:
|
||||
type: object
|
||||
properties:
|
||||
issuer: string?
|
||||
protocol: string?
|
||||
subjectName: string?
|
||||
validFrom: number?
|
||||
validTo: number?
|
||||
|
||||
|
||||
RemoteAddr:
|
||||
type: object
|
||||
properties:
|
||||
ipAddress: string
|
||||
port: number
|
||||
|
||||
|
||||
WebSocket:
|
||||
type: interface
|
||||
|
|
|
|||
|
|
@ -943,6 +943,19 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
|||
});
|
||||
scheme.ResponseBodyParams = tOptional(tObject({}));
|
||||
scheme.ResponseFinishedParams = tOptional(tObject({}));
|
||||
scheme.ResponseSecurityDetailsParams = tOptional(tObject({}));
|
||||
scheme.ResponseServerAddrParams = tOptional(tObject({}));
|
||||
scheme.SecurityDetails = tObject({
|
||||
issuer: tOptional(tString),
|
||||
protocol: tOptional(tString),
|
||||
subjectName: tOptional(tString),
|
||||
validFrom: tOptional(tNumber),
|
||||
validTo: tOptional(tNumber),
|
||||
});
|
||||
scheme.RemoteAddr = tObject({
|
||||
ipAddress: tString,
|
||||
port: tNumber,
|
||||
});
|
||||
scheme.BindingCallRejectParams = tObject({
|
||||
error: tType('SerializedError'),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -363,3 +363,25 @@ it('should have connection details for failed requests', async ({ contextFactory
|
|||
expect(serverIPAddress).toMatch(/^127\.0\.0\.1|\[::1\]/);
|
||||
expect(port).toBe(server.PORT);
|
||||
});
|
||||
|
||||
it('should return server address directly from response', async ({ page, server }) => {
|
||||
const response = await page.goto(server.EMPTY_PAGE);
|
||||
const { ipAddress, port } = await response.serverAddr();
|
||||
expect(ipAddress).toMatch(/^127\.0\.0\.1|\[::1\]/);
|
||||
expect(port).toBe(server.PORT);
|
||||
});
|
||||
|
||||
it('should return security details directly from response', async ({ contextFactory, httpsServer, browserName, platform }) => {
|
||||
it.fail(browserName === 'webkit' && platform === 'linux', 'https://github.com/microsoft/playwright/issues/6759');
|
||||
|
||||
const context = await contextFactory({ ignoreHTTPSErrors: true });
|
||||
const page = await context.newPage();
|
||||
const response = await page.goto(httpsServer.EMPTY_PAGE);
|
||||
const securityDetails = await response.securityDetails();
|
||||
if (browserName === 'webkit' && platform === 'win32')
|
||||
expect(securityDetails).toEqual({subjectName: 'puppeteer-tests', validFrom: 1550084863, validTo: -1});
|
||||
else if (browserName === 'webkit')
|
||||
expect(securityDetails).toEqual({protocol: 'TLS 1.3', subjectName: 'puppeteer-tests', validFrom: 1550084863, validTo: 33086084863});
|
||||
else
|
||||
expect(securityDetails).toEqual({issuer: 'puppeteer-tests', protocol: 'TLS 1.3', subjectName: 'puppeteer-tests', validFrom: 1550084863, validTo: 33086084863});
|
||||
});
|
||||
|
|
|
|||
44
types/types.d.ts
vendored
44
types/types.d.ts
vendored
|
|
@ -10363,6 +10363,50 @@ export interface Response {
|
|||
*/
|
||||
request(): Request;
|
||||
|
||||
/**
|
||||
* Returns SSL and other security information.
|
||||
*/
|
||||
securityDetails(): Promise<null|{
|
||||
/**
|
||||
* Common Name component of the Issuer field. from the certificate. This should only be used for informational purposes.
|
||||
* Optional.
|
||||
*/
|
||||
issuer?: string;
|
||||
|
||||
/**
|
||||
* The specific TLS protocol used. (e.g. `TLS 1.3`). Optional.
|
||||
*/
|
||||
protocol?: string;
|
||||
|
||||
/**
|
||||
* Common Name component of the Subject field from the certificate. This should only be used for informational purposes.
|
||||
* Optional.
|
||||
*/
|
||||
subjectName?: string;
|
||||
|
||||
/**
|
||||
* Unix timestamp (in seconds) specifying when this cert becomes valid. Optional.
|
||||
*/
|
||||
validFrom?: number;
|
||||
|
||||
/**
|
||||
* Unix timestamp (in seconds) specifying when this cert becomes invalid. Optional.
|
||||
*/
|
||||
validTo?: number;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Returns the IP address and port of the server.
|
||||
*/
|
||||
serverAddr(): Promise<null|{
|
||||
/**
|
||||
* IPv4 or IPV6 address of the server.
|
||||
*/
|
||||
ipAddress: string;
|
||||
|
||||
port: number;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Contains the status code of the response (e.g., 200 for a success).
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue