Skip to content

Commit

Permalink
fix: use internal request id header vs "X-Request-Id" (#529)
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito authored Mar 26, 2024
1 parent 2468bcc commit 28e533c
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
12 changes: 11 additions & 1 deletion src/Interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { Logger } from '@open-draft/logger'
import { Emitter, EventMap, Listener } from 'strict-event-emitter'
import { Emitter, Listener } from 'strict-event-emitter'

export type InterceptorEventMap = Record<string, any>
export type InterceptorSubscription = () => void

/**
* Request header name to detect when a single request
* is being handled by nested interceptors (XHR -> ClientRequest).
* Obscure by design to prevent collisions with user-defined headers.
* Ideally, come up with the Interceptor-level mechanism for this.
* @see https://github.com/mswjs/interceptors/issues/378
*/
export const INTERNAL_REQUEST_ID_HEADER_NAME =
'x-interceptors-internal-request-id'

export function getGlobalSymbol<V>(symbol: Symbol): V | undefined {
return (
// @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587
Expand Down
5 changes: 3 additions & 2 deletions src/interceptors/ClientRequest/NodeClientRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { uuidv4 } from '../../utils/uuid'
import { emitAsync } from '../../utils/emitAsync'
import { getRawFetchHeaders } from '../../utils/getRawFetchHeaders'
import { isPropertyAccessible } from '../../utils/isPropertyAccessible'
import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'

export type Protocol = 'http' | 'https'

Expand Down Expand Up @@ -189,8 +190,8 @@ export class NodeClientRequest extends ClientRequest {
// in another (parent) interceptor (like XMLHttpRequest -> ClientRequest).
// That means some interceptor up the chain has concluded that
// this request must be performed as-is.
if (this.getHeader('X-Request-Id') != null) {
this.removeHeader('X-Request-Id')
if (this.hasHeader(INTERNAL_REQUEST_ID_HEADER_NAME)) {
this.removeHeader(INTERNAL_REQUEST_ID_HEADER_NAME)
return this.passthrough(chunk, encoding, callback)
}

Expand Down
17 changes: 12 additions & 5 deletions src/interceptors/XMLHttpRequest/XMLHttpRequestController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { isDomParserSupportedType } from './utils/isDomParserSupportedType'
import { parseJson } from '../../utils/parseJson'
import { uuidv4 } from '../../utils/uuid'
import { createResponse } from './utils/createResponse'
import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../Interceptor'

const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
const IS_NODE = isNodeProcess()
Expand Down Expand Up @@ -48,7 +49,10 @@ export class XMLHttpRequestController {
private responseBuffer: Uint8Array
private events: Map<keyof XMLHttpRequestEventTargetEventMap, Array<Function>>

constructor(readonly initialRequest: XMLHttpRequest, public logger: Logger) {
constructor(
readonly initialRequest: XMLHttpRequest,
public logger: Logger
) {
this.events = new Map()
this.requestId = uuidv4()
this.requestHeaders = new Headers()
Expand Down Expand Up @@ -99,7 +103,7 @@ export class XMLHttpRequestController {
case 'addEventListener': {
const [eventName, listener] = args as [
keyof XMLHttpRequestEventTargetEventMap,
Function
Function,
]

this.registerEvent(eventName, listener)
Expand All @@ -119,7 +123,7 @@ export class XMLHttpRequestController {

case 'send': {
const [body] = args as [
body?: XMLHttpRequestBodyInit | Document | null
body?: XMLHttpRequestBodyInit | Document | null,
]

if (body != null) {
Expand Down Expand Up @@ -180,7 +184,10 @@ export class XMLHttpRequestController {
* handle the same request at the same time (e.g. emit the "response" event twice).
*/
if (IS_NODE) {
this.request.setRequestHeader('X-Request-Id', this.requestId!)
this.request.setRequestHeader(
INTERNAL_REQUEST_ID_HEADER_NAME,
this.requestId!
)
}

return invoke()
Expand Down Expand Up @@ -517,7 +524,7 @@ export class XMLHttpRequestController {
private trigger<
EventName extends keyof (XMLHttpRequestEventTargetEventMap & {
readystatechange: ProgressEvent<XMLHttpRequestEventTarget>
})
}),
>(eventName: EventName, options?: ProgressEventInit): void {
const callback = this.request[`on${eventName}`]
const event = createEvent(this.request, eventName, options)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { invariant } from 'outvariant'
import { HttpServer } from '@open-draft/test-server/http'
import { RequestHandler } from 'express-serve-static-core'
import { test, expect } from '../../../playwright.extend'
import { invariant } from 'outvariant'
import { INTERNAL_REQUEST_ID_HEADER_NAME } from '../../../../src/Interceptor'

const httpServer = new HttpServer((app) => {
const strictCorsMiddleware: RequestHandler = (req, res, next) => {
invariant(
!req.header('x-request-id'),
'Found unexpected "X-Request-Id" request header in the browser for "%s %s"',
!req.header(INTERNAL_REQUEST_ID_HEADER_NAME),
'Found unexpected internal "%s" request header in the browser for "%s %s"',
INTERNAL_REQUEST_ID_HEADER_NAME,
req.method,
req.url
)
Expand Down

0 comments on commit 28e533c

Please sign in to comment.