UNPKG

nock

Version:

HTTP server mocking and expectations library for Node.js

107 lines (91 loc) • 3.52 kB
import globalEmitter from './global_emitter.js' import * as common from './common.js' import { playbackInterceptor } from './playback_interceptor.js' import { interceptorsFor, isOn, isEnabledForNetConnect } from './intercept.js' async function handleRequest(request ) { const url = new URL(request.url) const interceptors = interceptorsFor(url) if (isOn() && interceptors) { const matches = interceptors.some((interceptor ) => interceptor.matchOrigin(request), ) const allowUnmocked = interceptors.some( (interceptor ) => interceptor.options.allowUnmocked, ) if (!matches && allowUnmocked) { globalEmitter.emit('no match', request) } else { const requestBodyBuffer = await request.clone().arrayBuffer() // When request body is a binary buffer we internally use in its hexadecimal representation. const requestBodyIsUtf8Representable = common.isUtf8Representable(requestBodyBuffer) const requestBodyString = Buffer.from(requestBodyBuffer).toString( requestBodyIsUtf8Representable ? 'utf8' : 'hex', ) const matchResults = [] const matchedInterceptor = interceptors.find((i ) => { const reasons = i.match(request, requestBodyString) if (reasons.length > 0) { matchResults.push({ interceptor: i, reasons }) return false } else { return true } }) if (matchedInterceptor) { matchedInterceptor.scope.logger( 'interceptor identified, starting mocking', ) matchedInterceptor.markConsumed() if (matchedInterceptor.isPassthrough) { return } const response = await playbackInterceptor({ decompressedRequest: request, requestBodyString, interceptor: matchedInterceptor, requestBodyIsUtf8Representable, }) return response } else { globalEmitter.emit( 'no match', request, matchResults.sort((a, b) => a.reasons.length - b.reasons.length), ) // Try to find a hostname match that allows unmocked. const allowUnmocked = interceptors.some( (i ) => i.matchHostName(url.hostname) && i.options.allowUnmocked, ) if (!allowUnmocked) { const body = JSON.stringify({ code: 'ERR_NOCK_NO_MATCH', message: `Nock: No match for request ${common.stringifyRequest(request, requestBodyString)}`, }) return new Response(body, { status: 501, headers: { 'Content-Type': 'application/json' }, }) } } } } else { globalEmitter.emit('no match', request) // Remove http(s):// for backward compatibility until we decide this Error. const normalizedUrl = common .normalizeOrigin(url) .replace(`${url.protocol}//`, '') if (isOn() && !isEnabledForNetConnect(normalizedUrl)) { throw new NetConnectNotAllowedError(normalizedUrl, url.pathname) } } } class NetConnectNotAllowedError extends Error { constructor(host , path ) { super(`Nock: Disallowed net connect for "${host}${path}"`) this.name = 'NetConnectNotAllowedError' this.code = 'ENETUNREACH' } } export default handleRequest