import type { DevToolsProtocol, FrameId, MonotonicTimeInSeconds, SecondsFromUnixEpoch } from "./types/HttpArchiveFormat.ts"; import type { PopulatedOptions } from "./Options.ts"; import { type WebSocketDirectionAndEvent } from "./types/HttpArchiveFormat.ts"; import type { HarPageBuilder } from "./HarPageBuilder.ts"; import type { TimeLord } from "./TimeLord.ts"; import type { Har, ISODateTimeString } from "./types"; /** * This class is responsible for building the entries of a HAR * * First, the HarEntriesBuilder class will construct it and then populate its events fields. * * Once all the events have been collected, if `isValidForPageTimeCalculations` is true, the * entry may be used for page timing even if it is not valid for inclusion in the HAR archive * (e.g. if there was no response). * * Then, for all entries that for which `isValidForInclusionInHarArchive` will have entries * generated. * * This class is organized in a declarative manner so that you can look at the HAR entry * generated at the end and work your way back to how each value is calculated by examining * the definitions. (in vscode, just use the "Go to Definition" feature.) * */ export declare class HarEntryBuilder { #private; private timelord; readonly orderArrived: number; readonly options: PopulatedOptions; priorRedirects: number; /** * The requestWillBeSentEvent is unique in two important ways. * * First, it is the only event that a HAR entry cannot exist without. So, it's * guaranteed to exist if we're generating a HAR entry. As such, we define it * with an _, and then have a get accessor that throws an exception should it * ever be accessed when _requestWillBeSentEvent is null. * * Second, requestWillBeSentEvent is the only event that may contain data for * two HAR entries. If the request is a redirect for a prior HAR entry, it will * a redirectResponse for that prior HAR entry for the prior URL, but all of * the events other fields will pertain to the redirected request to the new URL * which are placed into a new HAR entry. Hence, the redirected response is * for the prior HAR entry is omitted from the event data stored with this HAR entry. * (see the typescript `Omit<>` in its typing.) */ _requestWillBeSentEvent?: Omit; /** * Each of the following are events that may or may not exist for a given HAR entry. */ redirectResponse?: DevToolsProtocol.Network.RequestWillBeSentEvent["redirectResponse"]; responseReceivedEvent?: DevToolsProtocol.Network.ResponseReceivedEvent; requestWillBeSentExtraInfoEvent?: DevToolsProtocol.Network.RequestWillBeSentExtraInfoEvent; responseReceivedExtraInfoEvent?: DevToolsProtocol.Network.ResponseReceivedExtraInfoEvent; requestServedFromCacheEvent?: DevToolsProtocol.Network.RequestServedFromCacheEvent; loadingFinishedEvent?: DevToolsProtocol.Network.LoadingFinishedEvent; loadingFailedEvent?: DevToolsProtocol.Network.LoadingFailedEvent; resourceChangedPriorityEvent?: DevToolsProtocol.Network.ResourceChangedPriorityEvent; getResponseBodyResponse?: DevToolsProtocol.Network.GetResponseBodyResponse; dataReceivedEvents: DevToolsProtocol.Network.DataReceivedEvent[]; /** * We need to augment WebSocket frame sent and received events with their * direction, because only the event name, not the event itself, * tells us whether their data was sent or received */ webSocketEvents: WebSocketDirectionAndEvent[]; /** * * @param timelord A timelord is used to map monotonic timestamps wall time. * @param orderArrived The order in which the HAREntryBuilder was created, for debugging purposes * @param options Package options */ constructor(timelord: TimeLord, orderArrived: number, options: PopulatedOptions); /** * Does this entry builder have enough information to be used to calculate page timings? */ get isValidForPageTimeCalculations(): boolean; /** * Does this entry builder have enough information to generate a HAR entry * for inclusion in the HAR Archive? */ get isValidForInclusionInHarArchive(): boolean; /** * A HAR entry cannot exist if there is no requestWillBeSentEvent. * This getter is used by code that should only be called after * ensuring _requestWillBeSentEvent is not null. * * Both `isValidForInclusionInHarArchive` and `isValidForPageTimeCalculations` * ensure _requestWillBeSentEvent is not null; */ private get requestWillBeSentEvent(); /** * Associate this entry with a HarPageBuilder to represent the page that initiated * network event represented by the HarEntry * @param page */ assignToPage: (page: HarPageBuilder) => void; /** * Get the page that this entry is associated with. */ private get page(); /** * The frameId that initiated the network request represented by the HAR entry. */ get frameId(): FrameId | undefined; /** * The response to this network request, if it exists, which may come from a * responseReceivedEvent or a subsequent requestWillBeSent event's * redirectResponse field. */ private get _response(); /** * The response to this network request, if it exists, which may come from a * responseReceivedEvent or a subsequent requestWillBeSent event's * redirectResponse field. * * This getter throws an exception if there is no response. * * `isValidForInclusionInHarArchive` ensures that there is a response, so * code used to generate a HAR entry after checking for validity may use * this getter. */ private get response(); /** * The body of the response to a network request (as a string), if it exists. */ private get responseBody(); /** * The request's HTTP version, derived from the response's protocol field. */ private get httpVersion(); /** * Tests if the request's HTTP version is HTTP/1.x */ private get isHttp1x(); /** * The text of the responseHeaders, which is obtained from responseReceivedExtraInfoEvent.headersText * if available or response.headersText for legacy logs that do not have extra info. */ private get responseHeadersText(); /** * The size of the response headers, or -1 if it cannot be reliably calculated. * * Note this from the spec * > *headersSize - The size of received response-headers is computed only from headers that are really received from the server. * > Additional headers appended by the browser are not included in this number, but they appear in the list of header objects. */ private get responseHeadersSize(); /** * The network headers in object (as opposed to string) format where * header names are keys (property names) and values are property values. */ private get networkResponseHeadersObj(); /** * Response headers in HAR format. */ private get responseHarHeaders(); /** * get the value of a specific response header. * @param caseInsensitiveName Header name (case-insensitive) * @returns The value of the header or undefined if the header is not present. */ private getResponseHeader; /** * The encoded data length of the response, if known, or undefined. */ private get responseEncodedDataLength(); /** * The response body size if known, or -1 if it cannot be reliably calculated. * * Per spec * > bodySize [number] - Size of the received response body in bytes. * > Set to zero in case of responses coming from the cache (304). * > Set to -1 if the info is not available. * * Implicitly, this means the size of the body AFTER it has been decompressed, and so * it's not possible to calculate by looking at the number of raw bytes over the network. * * There is no definitive source for the size of the response body, or even a definitive * expectation of what the size is in some circumstances (e.g., an interrupted request * that fetched some of the body but will return none of it). * * The only reliable source seems to be the content encoding. */ private get responseBodySize(); /** * The response cookie header (the cookies that the server is asking the client to set) */ private get responseCookeHeader(); /** * The response cookies (the cookies that the server is asking the client to set) */ private get responseCookies(); /** * The value of the location header used to indicate where a request should be * redirected to. */ private get locationHeaderValue(); /** * The requestId */ private get requestId(); /** * The network request object attached to requestWillBeSentEvent */ private get request(); /** * The network request headers in object format (as opposed to string format), * with header names as keys and header values as property values. */ private get requestHeaders(); /** * The request headers in HAR Header format */ private get requestHarHeaders(); /** * The cookie header of the request, containing the cookies being sent out. * * Note: at time of writing, behavior differs from `chrome-har`, which does * not include cookies from the requestWillBeSentExtraInfoEvent. */ private get requestCookieHeader(); /** * The request cookies converted to HAR format. */ private get requestHarCookies(); /** * The size of the request headers, or -1 if it cannot be reliably calculated. */ private get requestHeadersSize(); /** * The size of the request body, or 0 if there is no body */ private get requestBodySize(); /** * The request's URL as a URL class, which needs to be reconstructed * to include the URL fragment (the section following the hash "#', * which is not sent to the server) if it exists. */ private get requestParsedUrl(); /** * The request's URL in string format. */ get requestUrl(): string | undefined; /** * The request's query as an array of HAR QueryString objects */ private get queryStringHar(); /** * The constructed HAR post data object representing the data * sent in the request body. */ private get postDataHar(); private get _isLinkPreloadObj(); /** * The request method (e.g. "GET", "POST", etc.) */ private get method(); /** * The content size of the response * * Per spec * > size [number] - Length of the returned content in bytes. Should be equal to response.bodySize if there is no compression and * bigger when the content has been compressed. */ private get contentSize(); /** * An object containing the content `compression` property if and only if * dhe data was compressed. */ private get compression_obj(); /** * The HAR response.content object */ private get responseContent(); private get _initialPriority(); private get _priority(); /** * Initiator fields for the HAR entry */ private get initiatorFields(); /** * The entry's _resourceType field. */ private get resourceType(); /** * Is this a network request over a protocol that can be represented in HAR format. */ private get isSupportedProtocol(); /** * Event time in [seconds since arbitrary point in time we will call TimeStamp] [https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-MonotonicTime] * * See also: * - https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp */ get timestamp(): MonotonicTimeInSeconds; /** Event time in [seconds since UNIX Epoch](https://chromedevtools.github.io/devtools-protocol/tot/Network/#type-TimeSinceEpoch) */ get wallTime(): SecondsFromUnixEpoch; /** * The start time of the request in seconds since the unix epoch, which with the assistance of the * TimeLord can be assured to also be monotonically increasing with the timestamps * of the events. * * Spec: * > startedDateTime [string] - Date and time stamp of the request start (ISO 8601 - YYYY-MM-DDThh:mm:ss.sTZD). * * We interpret request start to be the requestTime from the timing object, rather than the timestamp of the * requestWillBeSentEvent, as the requestWillBeSent event occurs during the request, which may be after * the requested started by many milliseconds. Failing the presence of a timing object in the response, * we fall back to the timestamp on the requestWillBeSent event. */ get requestStartTimeInSecondsFromUnixEpoch(): SecondsFromUnixEpoch; /** * The start of the request in seconds since the unix epoch, which with the assistance of the * TimeLord can be assured to also be monotonically increasing with the timestamps, so that * if a request's timestamp is greater than another's request, it's startedDateTime will * also be greater. */ get startedDateTime(): ISODateTimeString; /** * The time required for the request */ private get time(); /** * The HAR cache record for the request */ private get cache(); /** * The IP address of the server that responded to the request. */ private get serverIPAddress(); /** * The ID of the HTTP connection over which the request was sent. * (With keep-alive and other features, the same connection may handle * many requests.) */ private get connection(); /** * The Chrome DevTools Protocol's response timing object * used to calculate HAR timings. */ private get timing(); /** * The timestamp of when the request started */ get requestTimeInSeconds(): MonotonicTimeInSeconds; /** * A reference time in units of seconds */ private get _requestTime(); /** * True if this request was handled by an HTTP2 push */ private get wasHttp2Push(); private get _was_pushed_obj(); /** * The non-standard HAR _chunks field containing the number of bytes * and timestamp of each chunk. */ private get _chunks_obj(); get pagerefObj(): { pageref?: string; }; /** * An entry field containing all the web socket messages sent over a requestId generated via the "ws:" or "wss:" protocol. */ get _webSocketMessagesObj(): { readonly _webSocketMessages?: Har.WebSocketMessage[]; }; /** * The HAR timings object */ private get timings(); /** * The HAR entry.request object */ private get harRequest(); /** * The HAR entry.response object */ private get harResponse(); /** * The HAR entry object that is the final product of the HarEntryBuilder. * * If you want to know how any value is calculated, just work backwards from * here using vscode's "Go to Definition" feature. */ get entry(): Har.Entry | undefined; }