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.
|
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
|
## method: Response.status
|
||||||
- returns: <[int]>
|
- returns: <[int]>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import { URLSearchParams } from 'url';
|
||||||
import * as channels from '../protocol/channels';
|
import * as channels from '../protocol/channels';
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
import { Frame } from './frame';
|
import { Frame } from './frame';
|
||||||
import { Headers, WaitForEventOptions } from './types';
|
import { Headers, RemoteAddr, SecurityDetails, WaitForEventOptions } from './types';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as mime from 'mime';
|
import * as mime from 'mime';
|
||||||
import { isString, headersObjectToArray, headersArrayToObject } from '../utils/utils';
|
import { isString, headersObjectToArray, headersArrayToObject } from '../utils/utils';
|
||||||
|
|
@ -325,6 +325,14 @@ export class Response extends ChannelOwner<channels.ResponseChannel, channels.Re
|
||||||
frame(): Frame {
|
frame(): Frame {
|
||||||
return this._request.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 {
|
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[];
|
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> {
|
async body(): Promise<channels.ResponseBodyResult> {
|
||||||
return { binary: (await this._object.body()).toString('base64') };
|
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 {
|
export class RouteDispatcher extends Dispatcher<Route, channels.RouteInitializer> implements channels.RouteChannel {
|
||||||
|
|
|
||||||
|
|
@ -2372,6 +2372,8 @@ export type ResponseInitializer = {
|
||||||
export interface ResponseChannel extends Channel {
|
export interface ResponseChannel extends Channel {
|
||||||
body(params?: ResponseBodyParams, metadata?: Metadata): Promise<ResponseBodyResult>;
|
body(params?: ResponseBodyParams, metadata?: Metadata): Promise<ResponseBodyResult>;
|
||||||
finished(params?: ResponseFinishedParams, metadata?: Metadata): Promise<ResponseFinishedResult>;
|
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 ResponseBodyParams = {};
|
||||||
export type ResponseBodyOptions = {};
|
export type ResponseBodyOptions = {};
|
||||||
|
|
@ -2383,6 +2385,29 @@ export type ResponseFinishedOptions = {};
|
||||||
export type ResponseFinishedResult = {
|
export type ResponseFinishedResult = {
|
||||||
error?: string,
|
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 -----------
|
// ----------- WebSocket -----------
|
||||||
export type WebSocketInitializer = {
|
export type WebSocketInitializer = {
|
||||||
|
|
|
||||||
|
|
@ -1927,6 +1927,31 @@ Response:
|
||||||
returns:
|
returns:
|
||||||
error: string?
|
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:
|
WebSocket:
|
||||||
type: interface
|
type: interface
|
||||||
|
|
|
||||||
|
|
@ -943,6 +943,19 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
||||||
});
|
});
|
||||||
scheme.ResponseBodyParams = tOptional(tObject({}));
|
scheme.ResponseBodyParams = tOptional(tObject({}));
|
||||||
scheme.ResponseFinishedParams = 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({
|
scheme.BindingCallRejectParams = tObject({
|
||||||
error: tType('SerializedError'),
|
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(serverIPAddress).toMatch(/^127\.0\.0\.1|\[::1\]/);
|
||||||
expect(port).toBe(server.PORT);
|
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;
|
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).
|
* Contains the status code of the response (e.g., 200 for a success).
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue