pagespeed-quest
Version:
A framework for efficient web front-end speed improvement
99 lines • 9.84 kB
JavaScript
import { Proxy } from './proxy.js';
export class RecordingProxy extends Proxy {
startedAt;
transactions = [];
async setup() {
this.startedAt = new Date();
let requestNumber = 1;
this.proxy.onRequest((ctx, onRequestComplete) => {
const number = requestNumber++;
// Skip websocket
if (ctx.clientToProxyRequest.headers?.upgrade === 'websocket') {
this.dependency.logger?.warn({ number }, `Request #${number} ${ctx.clientToProxyRequest.url} skipped (websocket)`);
return;
}
// Throttling
const filter = this.createThrottlingTransform();
if (filter)
ctx.addResponseFilter(filter);
const identifier = Proxy.contextRequest(ctx);
const transaction = {
startedAt: new Date(),
...identifier,
contentChunks: [],
};
this.dependency.logger?.debug({ number, identifier }, `Request #${number} ${transaction.url} started`);
ctx.onError((_, err, errKind) => {
transaction.responseStartedAt = new Date();
transaction.err = err;
transaction.errKind = errKind;
this.dependency.logger?.warn({ number, identifier, err }, `Request #${number} ${transaction.url} failed: ${err.message}`);
});
ctx.onResponse((_, onResponseComplete) => {
transaction.responseStartedAt = new Date();
transaction.statusCode = ctx.serverToProxyResponse.statusCode;
transaction.incomingHttpHeaders = ctx.serverToProxyResponse.headers;
this.dependency.logger?.debug({ number, identifier }, `Request #${number} ${transaction.url} responded`);
onResponseComplete();
});
ctx.onResponseData((_, chunk, onResponseDataComplete) => {
transaction.contentChunks.push(chunk);
onResponseDataComplete(null, chunk);
});
ctx.onResponseEnd((_, onResponseEndComplete) => {
transaction.responseEndedAt = new Date();
this.transactions.push(transaction);
this.dependency.logger?.debug({ number, identifier }, `Request #${number} ${transaction.url} completed`);
onResponseEndComplete();
});
onRequestComplete();
});
}
async saveInventory() {
const transactions = [];
for (const requestTransaction of this.transactions) {
const transaction = {
method: requestTransaction.method,
url: requestTransaction.url,
ttfbMs: 0,
content: Buffer.concat(requestTransaction.contentChunks),
};
// ttfb and duration
if (requestTransaction.responseStartedAt) {
transaction.ttfbMs = +requestTransaction.responseStartedAt - +requestTransaction.startedAt;
if (requestTransaction.responseEndedAt) {
transaction.durationMs = +requestTransaction.responseEndedAt - +requestTransaction.responseStartedAt;
}
}
// error
if (requestTransaction.err) {
transaction.errorMessage = requestTransaction.err.message;
}
// status code
if (requestTransaction.statusCode) {
transaction.statusCode = requestTransaction.statusCode;
}
// headers
if (requestTransaction.incomingHttpHeaders) {
transaction.rawHeaders = {};
for (const [key, value] of Object.entries(requestTransaction.incomingHttpHeaders)) {
transaction.rawHeaders[key.toLowerCase()] = value.toString();
}
}
transactions.push(transaction);
}
const resources = await this.inventoryRepository.saveTransactions(transactions);
const inventory = { entryUrl: this.entryUrl, deviceType: this.deviceType, resources };
await this.inventoryRepository.saveInventory(inventory);
}
async shutdown() {
await this.saveInventory();
}
}
export async function withRecordingProxy(options, dependency, cb) {
const proxy = new RecordingProxy(options, dependency);
await proxy.start();
await cb(proxy);
await proxy.stop();
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3JkaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JlY29yZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUUsS0FBSyxFQUFpQyxNQUFNLFlBQVksQ0FBQTtBQW9CakUsTUFBTSxPQUFPLGNBQWUsU0FBUSxLQUFLO0lBQ3ZDLFNBQVMsQ0FBTztJQUNoQixZQUFZLEdBQTJCLEVBQUUsQ0FBQTtJQUV6QyxLQUFLLENBQUMsS0FBSztRQUNULElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQTtRQUUzQixJQUFJLGFBQWEsR0FBRyxDQUFDLENBQUE7UUFDckIsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFHLEVBQUUsaUJBQWlCLEVBQUUsRUFBRTtZQUM5QyxNQUFNLE1BQU0sR0FBRyxhQUFhLEVBQUUsQ0FBQTtZQUU5QixpQkFBaUI7WUFDakIsSUFBSSxHQUFHLENBQUMsb0JBQW9CLENBQUMsT0FBTyxFQUFFLE9BQU8sS0FBSyxXQUFXLEVBQUU7Z0JBQzdELElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLElBQUksQ0FDMUIsRUFBRSxNQUFNLEVBQUUsRUFDVixZQUFZLE1BQU0sSUFBSSxHQUFHLENBQUMsb0JBQW9CLENBQUMsR0FBRyxzQkFBc0IsQ0FDekUsQ0FBQTtnQkFDRCxPQUFNO2FBQ1A7WUFFRCxhQUFhO1lBQ2IsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUE7WUFDL0MsSUFBSSxNQUFNO2dCQUFFLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUV6QyxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQzVDLE1BQU0sV0FBVyxHQUF5QjtnQkFDeEMsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFO2dCQUNyQixHQUFHLFVBQVU7Z0JBQ2IsYUFBYSxF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