diff --git a/src/util/recorder.ts b/src/util/recorder.ts index be36cc3b..e6a90942 100644 --- a/src/util/recorder.ts +++ b/src/util/recorder.ts @@ -1755,6 +1755,14 @@ function createResponse( "WARC-Page-ID": pageid, }; + if (reqresp.protocols.length) { + warcHeaders["WARC-Protocol"] = reqresp.protocols.join(", "); + } + + if (reqresp.cipher) { + warcHeaders["WARC-Cipher-Suite"] = reqresp.cipher; + } + if (reqresp.resourceType) { warcHeaders["WARC-Resource-Type"] = reqresp.resourceType; } diff --git a/src/util/reqresp.ts b/src/util/reqresp.ts index 5548cb5b..1ed47ed9 100644 --- a/src/util/reqresp.ts +++ b/src/util/reqresp.ts @@ -25,7 +25,9 @@ export class RequestResponseInfo { method?: string; url!: string; - protocol?: string = "HTTP/1.1"; + + protocols: string[] = []; + cipher?: string; mimeType?: string; @@ -132,7 +134,9 @@ export class RequestResponseInfo { this.setStatus(response.status, response.statusText); - this.protocol = response.protocol; + if (response.protocol) { + this.protocols.push(response.protocol); + } if (resourceType) { this.resourceType = resourceType.toLowerCase(); @@ -153,11 +157,16 @@ export class RequestResponseInfo { this.fromServiceWorker = !!response.fromServiceWorker; - if (response.securityDetails) { - const issuer: string = response.securityDetails.issuer || ""; + const { securityDetails } = response; + + if (securityDetails) { + this.protocols.push( + securityDetails.protocol.replaceAll(" ", "/").toLowerCase(), + ); + this.cipher = getCipher(securityDetails); + const issuer: string = securityDetails.issuer || ""; const ctc: string = - response.securityDetails.certificateTransparencyCompliance === - "compliant" + securityDetails.certificateTransparencyCompliance === "compliant" ? "1" : "0"; this.extraOpts.cert = { issuer, ctc }; @@ -204,21 +213,6 @@ export class RequestResponseInfo { this.requestHeaders = params.headers; } - getResponseHeadersText() { - let headers = `${this.protocol} ${this.status} ${this.statusText}\r\n`; - - if (this.responseHeaders) { - for (const header of Object.keys(this.responseHeaders)) { - headers += `${header}: ${this.responseHeaders[header].replace( - /\n/g, - ", ", - )}\r\n`; - } - } - headers += "\r\n"; - return headers; - } - hasRequest() { return this.method && (this.requestHeaders || this.requestHeadersText); } @@ -417,3 +411,20 @@ export function isHTMLMime(mime: string) { export function isRedirectStatus(status: number) { return status >= 300 && status < 400 && status !== 304; } + +function getCipher({ + keyExchange, + keyExchangeGroup, + cipher, +}: Protocol.Network.SecurityDetails): string { + const key = `${keyExchange} ${keyExchangeGroup} ${cipher}`; + const mapping: Record = { + " X25519Kyber768Draft00 AES_128_GCM": "TLS_AES_128_GCM_SHA256", + " X25519 AES_128_GCM": "TLS_AES_128_GCM_SHA256", + "ECDHE_RSA X25519 AES_128_GCM": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + " X25519Kyber768Draft00 AES_256_GCM": "TLS_AES_256_GCM_SHA384", + " X25519 AES_256_GCM": "TLS_AES_256_GCM_SHA384", + "ECDHE_RSA X25519 AES_256_GCM": "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + }; + return mapping[key] || ""; +}