@interopio/gateway-server 0.17.2 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +4 -0
- package/dist/index.cjs.map +3 -3
- package/dist/index.js.map +3 -3
- package/dist/web/test.js.map +3 -3
- package/package.json +2 -2
package/dist/web/test.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/http/exchange.ts", "../../src/client/exchange.ts", "../../src/http/status.ts", "../../src/client/fetch.ts", "../../src/mock/client/exchange.ts", "../../src/mock/server/exchange.ts", "../../src/server/exchange.ts", "../../src/logger.ts", "../../src/server/handler.ts", "../../src/test/server/handler.ts", "../../src/server/ws-client-verify.ts", "../../src/server/util/matchers.ts", "../../src/app/route.ts", "../../src/common/compose.ts", "../../src/test/server/client.ts", "../../src/test/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n HeaderValues,\n HttpCookie,\n HttpHeaders,\n MutableHttpHeaders,\n ReadonlyHeaderValues,\n ResponseCookie\n} from '../../types/web/http';\nimport { type AddressInfo, isIP } from 'node:net';\nimport { Cookie } from 'tough-cookie';\n\nfunction parseHost(headers: HttpHeaders, defaultHost?: string): string | undefined {\n let host = headers.get('x-forwarded-host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n const port = headers.one('x-forwarded-port');\n if (port) {\n host = `${host}:${port}`;\n }\n }\n host ??= headers.one('host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n return (host as string).split(',', 1)[0].trim();\n }\n\n return defaultHost;\n}\n\nfunction isForwardedSsl(headers: HttpHeaders): boolean {\n const v = headers.one('x-forwarded-ssl');\n return (typeof v === 'string') && (v.toLowerCase() === 'on');\n}\n\nfunction parseProtocol(headers: HttpHeaders, defaultProtocol: string): string {\n let proto = headers.get('x-forwarded-proto');\n\n if (Array.isArray(proto)) {\n proto = proto[0];\n }\n if (proto !== undefined) {\n return (proto as string).split(',', 1)[0].trim();\n }\n else if (isForwardedSsl(headers)) {\n return 'https';\n }\n return defaultProtocol;\n}\n\nfunction parseRemoteAddress(url: URL, headers: HttpHeaders, remoteAddress?: AddressInfo) : AddressInfo | undefined {\n const port = remoteAddress ? remoteAddress.port : 'https:' === url.protocol ? 443 : 80;\n\n let host = headers.one('x-forwarded-for');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host !== undefined) {\n host = (host as string).split(',', 1)[0].trim();\n return { address: host, port: Number(port), family: isIP(host) === 6 ? 'IPv6' : 'IPv4' };\n }\n}\n\nexport abstract class AbstractHttpMessage<Headers extends HttpHeaders = HttpHeaders> {\n readonly #headers: Headers;\n protected constructor(headers: Headers) {\n this.#headers = headers;\n }\n get headers(): Headers {\n return this.#headers;\n }\n}\n\nexport abstract class AbstractHttpRequest<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n private static logIdCounter = 0;\n #id?: string\n\n get id(): string {\n if (this.#id === undefined) {\n this.#id = `${this.initId()}-${++AbstractHttpRequest.logIdCounter}`;\n\n }\n return this.#id;\n }\n\n protected initId(): string {\n return 'request';\n }\n\n get cookies(): HttpCookie[] {\n return parseCookies(this.headers);\n }\n\n protected parseHost(defaultHost?: string): string | undefined {\n return parseHost(this.headers, defaultHost);\n }\n\n protected parseProtocol(defaultProtocol: string): string {\n return parseProtocol(this.headers, defaultProtocol);\n }\n\n abstract get URL(): URL;\n\n protected parseRemoteAddress(remoteAddress?: AddressInfo) {\n return parseRemoteAddress(this.URL, this.headers, remoteAddress);\n }\n}\n\nexport abstract class AbstractHttpResponse<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n get cookies(): ResponseCookie[] {\n return parseResponseCookies(this.headers);\n }\n\n protected setCookieValue(responseCookie: ResponseCookie): string {\n const cookie = new Cookie({\n key: responseCookie.name,\n value: responseCookie.value,\n maxAge: responseCookie.maxAge,\n domain: responseCookie.domain,\n path: responseCookie.path,\n secure: responseCookie.secure,\n httpOnly: responseCookie.httpOnly,\n sameSite: responseCookie.sameSite\n });\n return cookie.toString();\n }\n\n}\n\nfunction parseHeader(value: string): string[] {\n const list: string[] = [];\n {\n let start = 0;\n let end = 0;\n\n for (let i = 0; i < value.length; i++) {\n switch (value.charCodeAt(i)) {\n case 0x20: // space\n if (start === end) {\n start = end = i + 1;\n }\n break;\n case 0x2c: // comma\n list.push(value.slice(start, end));\n start = end = i + 1;\n break;\n default:\n end = end + 1;\n break;\n }\n }\n list.push(value.slice(start, end));\n }\n\n return list;\n}\n\nfunction toList(values: number | string | (readonly string[]) | undefined): string[] {\n if (typeof values === 'string') {\n values = [values];\n }\n if (typeof values === 'number') {\n values = [String(values)];\n }\n const list: string[] = [];\n if (values) {\n for (const value of values) {\n if (value) {\n list.push(...parseHeader(value));\n }\n }\n }\n return list;\n}\n\nfunction parseCookies(headers: HttpHeaders): HttpCookie[] {\n return headers.list('cookie')\n .map(s => s.split(';').map((cs) => Cookie.parse(cs)))\n .flat(1)\n .filter((tc) => tc !== undefined)\n .map((tc) => {\n const result: HttpCookie = Object.freeze({name: tc.key, value: tc.value});\n return result;\n });\n}\n\ntype Mutable<T> = {-readonly [K in keyof T]: T[K]};\n\nfunction parseResponseCookies(headers: HttpHeaders): ResponseCookie[] {\n return headers.list('set-cookie').map((cookie) => {\n const parsed = Cookie.parse(cookie);\n if (parsed) {\n const result: Mutable<ResponseCookie> = {name: parsed.key, value: parsed.value, maxAge: Number(parsed.maxAge ?? -1)};\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.domain) result.domain = parsed.domain;\n if (parsed.path) result.path = parsed.path;\n if (parsed.secure) result.secure = true;\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.sameSite) result.sameSite = parsed.sameSite as 'strict' | 'lax' | 'none';\n return Object.freeze(result);\n }\n }).filter((cookie): cookie is ResponseCookie => cookie !== undefined);\n}\n\n\nexport abstract class AbstractHttpHeaders<Values extends HeaderValues | ReadonlyHeaderValues> {\n protected constructor() {}\n abstract get(name: string): Values\n\n toList(name: string): string[] {\n const values = this.get(name);\n return toList(values);\n }\n}\n\nexport class MapHttpHeaders extends Map<string, (readonly string[])> implements MutableHttpHeaders {\n\n get(name: string) {\n return super.get(name.toLowerCase());\n }\n\n one(name: string): string | undefined {\n return this.get(name)?.[0];\n }\n\n list(name: string) {\n const values = super.get(name.toLowerCase());\n return toList(values);\n }\n\n set(name: string, value: number | string | (readonly string[]) | undefined): this {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n value = [value];\n }\n if (value) {\n return super.set(name.toLowerCase(), value);\n }\n else {\n super.delete(name.toLowerCase());\n return this;\n }\n }\n\n add(name: string, value: string | (readonly string[])) {\n const prev = super.get(name.toLowerCase());\n if (typeof value === 'string') {\n value = [value];\n }\n if (prev) {\n value = prev.concat(value);\n }\n this.set(name, value);\n return this;\n }\n}\n", "import type {\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHttpHeaders\n} from '../../types/web/http';\n\nimport {AbstractHttpRequest, AbstractHttpResponse, MapHttpHeaders} from '../http/exchange.js';\n\nexport abstract class AbstractClientHttpRequest extends AbstractHttpRequest<MutableHttpHeaders> {\n\n protected constructor(method: HttpMethod, uri: URL) {\n super(new MapHttpHeaders());\n this.URL = uri;\n this.method = method;\n }\n\n readonly URL: URL;\n readonly method: HttpMethod;\n}\n\nexport abstract class AbstractClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> {\n protected constructor(statusCode: HttpStatusCode, headers: ReadonlyHttpHeaders) {\n super(headers);\n this.statusCode = statusCode;\n }\n readonly statusCode: HttpStatusCode;\n}\n", "import type {HttpStatusCode} from '../../types/web/http';\n\nclass DefaultHttpStatusCode implements HttpStatusCode {\n readonly #value: number;\n constructor(value: number) {\n this.#value = value;\n }\n get value(): number {\n return this.#value;\n }\n\n toString(): string {\n return this.#value.toString();\n }\n}\n\nexport class HttpStatus implements HttpStatusCode {\n static readonly CONTINUE = new HttpStatus(100, 'Continue');\n static readonly SWITCHING_PROTOCOLS = new HttpStatus(101, 'Switching Protocols');\n\n // 2xx Success\n\n static readonly OK = new HttpStatus(200, 'OK');\n static readonly CREATED = new HttpStatus(201, 'Created');\n static readonly ACCEPTED = new HttpStatus(202, 'Accepted');\n static readonly NON_AUTHORITATIVE_INFORMATION = new HttpStatus(203, 'Non-Authoritative Information');\n static readonly NO_CONTENT = new HttpStatus(204, 'No Content');\n static readonly RESET_CONTENT = new HttpStatus(205, 'Reset Content');\n static readonly PARTIAL_CONTENT = new HttpStatus(206, 'Partial Content');\n static readonly MULTI_STATUS = new HttpStatus(207, 'Multi-Status');\n\n static readonly IM_USED = new HttpStatus(226, 'IM Used');\n\n\n // 3xx Redirection\n static readonly MULTIPLE_CHOICES = new HttpStatus(300, 'Multiple Choices');\n static readonly MOVED_PERMANENTLY = new HttpStatus(301, 'Moved Permanently');\n\n // 4xx Client Error\n\n static readonly BAD_REQUEST = new HttpStatus(400, 'Bad Request');\n static readonly UNAUTHORIZED = new HttpStatus(401, 'Unauthorized');\n static readonly FORBIDDEN = new HttpStatus(403, 'Forbidden');\n static readonly NOT_FOUND = new HttpStatus(404, 'Not Found');\n static readonly METHOD_NOT_ALLOWED = new HttpStatus(405, 'Method Not Allowed');\n static readonly NOT_ACCEPTABLE = new HttpStatus(406, 'Not Acceptable');\n static readonly PROXY_AUTHENTICATION_REQUIRED = new HttpStatus(407, 'Proxy Authentication Required');\n static readonly REQUEST_TIMEOUT = new HttpStatus(408, 'Request Timeout');\n static readonly CONFLICT = new HttpStatus(409, 'Conflict');\n static readonly GONE = new HttpStatus(410, 'Gone');\n static readonly LENGTH_REQUIRED = new HttpStatus(411, 'Length Required');\n static readonly PRECONDITION_FAILED = new HttpStatus(412, 'Precondition Failed');\n static readonly PAYLOAD_TOO_LARGE = new HttpStatus(413, 'Payload Too Large');\n static readonly URI_TOO_LONG = new HttpStatus(414, 'URI Too Long');\n static readonly UNSUPPORTED_MEDIA_TYPE = new HttpStatus(415, 'Unsupported Media Type');\n\n static readonly EXPECTATION_FAILED = new HttpStatus(417, 'Expectation Failed');\n static readonly IM_A_TEAPOT = new HttpStatus(418, 'I\\'m a teapot');\n\n static readonly TOO_EARLY = new HttpStatus(425, 'Too Early');\n static readonly UPGRADE_REQUIRED = new HttpStatus(426, 'Upgrade Required');\n static readonly PRECONDITION_REQUIRED = new HttpStatus(428, 'Precondition Required');\n static readonly TOO_MANY_REQUESTS = new HttpStatus(429, 'Too Many Requests');\n static readonly REQUEST_HEADER_FIELDS_TOO_LARGE = new HttpStatus(431, 'Request Header Fields Too Large');\n static readonly UNAVAILABLE_FOR_LEGAL_REASONS = new HttpStatus(451, 'Unavailable For Legal Reasons');\n\n // 5xx Server Error\n static readonly INTERNAL_SERVER_ERROR = new HttpStatus(500, 'Internal Server Error');\n static readonly NOT_IMPLEMENTED = new HttpStatus(501, 'Not Implemented');\n static readonly BAD_GATEWAY = new HttpStatus(502, 'Bad Gateway');\n static readonly SERVICE_UNAVAILABLE = new HttpStatus(503, 'Service Unavailable');\n static readonly GATEWAY_TIMEOUT = new HttpStatus(504, 'Gateway Timeout');\n static readonly HTTP_VERSION_NOT_SUPPORTED = new HttpStatus(505, 'HTTP Version Not Supported');\n static readonly VARIANT_ALSO_NEGOTIATES = new HttpStatus(506, 'Variant Also Negotiates');\n static readonly INSUFFICIENT_STORAGE = new HttpStatus(507, 'Insufficient Storage');\n static readonly LOOP_DETECTED = new HttpStatus(508, 'Loop Detected');\n static readonly NOT_EXTENDED = new HttpStatus(510, 'Not Extended');\n static readonly NETWORK_AUTHENTICATION_REQUIRED = new HttpStatus(511, 'Network Authentication Required');\n\n static readonly #VALUES: HttpStatus[] = [];\n static {\n Object.keys(HttpStatus)\n .filter(key => key !== 'VALUES' && key !== 'resolve')\n .forEach(key => {\n const value = HttpStatus[key];\n if (value instanceof HttpStatus) {\n Object.defineProperty(value, 'name', {enumerable: true, value: key, writable: false});\n HttpStatus.#VALUES.push(value);\n }\n })\n\n }\n\n static resolve(code: number): HttpStatus | undefined {\n for (const status of HttpStatus.#VALUES) {\n if (status.value === code) {\n return status;\n }\n }\n }\n\n readonly #value: number;\n readonly #phrase: string;\n\n private constructor(value: number, phrase: string) {\n this.#value = value;\n this.#phrase = phrase;\n }\n\n get value(): number {\n return this.#value;\n }\n get phrase(): string {\n return this.#phrase;\n }\n\n toString() {\n return `${this.#value} ${this['name']}`;\n }\n}\n\n\nexport function httpStatusCode(value: number | HttpStatusCode): HttpStatusCode {\n if (typeof value === 'number') {\n if (value < 100 || value > 999) {\n throw new Error(`status code ${value} should be in range 100-999`);\n }\n const status = HttpStatus.resolve(value);\n if (status !== undefined) {\n return status;\n }\n return new DefaultHttpStatusCode(value);\n }\n return value;\n}\n", "import type {ClientHttpConnector} from './types.js';\nimport {AbstractClientHttpRequest, AbstractClientHttpResponse} from './exchange.js';\nimport {MapHttpHeaders} from \"../http/exchange.js\";\n\nimport type {\n HttpMethod,\n BodyChunk\n} from '../../types/web/http';\nimport type {\n ClientHttpRequest,\n ClientHttpResponse\n} from '../../types/web/client';\nimport {httpStatusCode} from \"../http/status.ts\";\n\nclass FetchClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #body?: BodyInit;\n constructor(method: HttpMethod, uri: URL) {\n super(method, uri);\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk): Promise<boolean> {\n this.#body = body instanceof ReadableStream ? body : await body;\n return await this.end();\n }\n\n end() {\n return Promise.resolve(true);\n }\n\n getNativeRequest<T>(): T {\n const method = this.method;\n const headers = new Headers();\n for (const key of this.headers.keys()) {\n if (key.toLowerCase() === 'content-length') {\n continue; // Content-Length is set automatically later\n }\n for (const value of this.headers.list(key)) {\n headers.append(key, value);\n }\n }\n if (!this.headers.has('accept')) {\n headers.append('accept', '*/*');\n }\n const body = this.#body;\n\n return new Request(this.URL, {method, headers, body}) as T;\n }\n}\nfunction toHttpHeaders(headers: Headers): MapHttpHeaders {\n const result = new MapHttpHeaders();\n for (const [key, value] of headers.entries()) {\n result.add(key, value);\n }\n return result;\n}\nclass FetchClientHttpResponse extends AbstractClientHttpResponse implements ClientHttpResponse {\n #response: Response;\n constructor(response: Response) {\n super(httpStatusCode(response.status), toHttpHeaders(response.headers));\n this.#response = response;\n }\n\n get statusMessage() {\n return this.#response.statusText;\n }\n\n get body() {\n return this.#response.body ?? undefined;\n }\n\n blob() {\n return this.#response.blob();\n }\n}\n\nexport class FetchClientHttpConnector implements ClientHttpConnector {\n readonly #fetch: typeof fetch;\n constructor(fetchFn: typeof fetch = globalThis.fetch) {\n this.#fetch = fetchFn;\n }\n\n async connect(method: HttpMethod, uri: URL, requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n const fetchClientHttpRequest = new FetchClientHttpRequest(method, uri);\n await requestCallback(fetchClientHttpRequest);\n const fetchRequest = fetchClientHttpRequest.getNativeRequest<Request>();\n const fetchResponse = await this.#fetch(fetchRequest);\n return new FetchClientHttpResponse(fetchResponse);\n }\n}\n", "import {AbstractClientHttpRequest} from '../../client/exchange.js';\nimport {\n BodyChunk,\n HttpMethod,\n HttpStatusCode,\n type MutableHttpHeaders, type ReadonlyHeaderValue,\n ReadonlyHttpHeaders\n} from '../../../types/web/http';\nimport {ClientHttpRequest, ClientHttpResponse} from '../../../types/web/client';\n\nimport {AbstractHttpResponse, MapHttpHeaders} from '../../http/exchange.js';\nimport {httpStatusCode} from '../../http/status.js';\nimport * as stream from 'node:stream/web';\n\nexport class MockClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error(\"Body not set\");\n };\n constructor(uri: URL, method: HttpMethod) {\n super(method, uri);\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n this.#body = () => {\n return stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n };\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n chunks.push(value);\n }\n } while (!done);\n return true;\n }\n }\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#writeHandler = handler;\n }\n\n getNativeRequest<T>(): T {\n return this as unknown as T;\n }\n\n getBody(): ReadableStream<BodyChunk> {\n return this.#body();\n }\n\n body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n const asyncIterator = (async function* () {\n if (body instanceof ReadableStream) {\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n yield value;\n }\n } while (!done);\n }\n else {\n const value = await body;\n if (value !== undefined) {\n yield value;\n }\n }\n\n })();\n return this.#writeHandler(stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>);\n }\n\n async end() {\n return await this.body(Promise.resolve());\n }\n\n}\n\nexport class MockClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> implements ClientHttpResponse {\n #statusCode: HttpStatusCode;\n #body: ReadableStream<BodyChunk> = stream.ReadableStream.from([]) as ReadableStream<BodyChunk>;\n constructor(status: number | HttpStatusCode) {\n super(new MapHttpHeaders());\n this.#statusCode = httpStatusCode(status);\n }\n\n get statusCode(): HttpStatusCode {\n return this.#statusCode;\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n\n setBody(body: string, charset?: BufferEncoding): this {\n this.#body = stream.ReadableStream.from([Buffer.from(body, charset)]) as ReadableStream<BodyChunk>;\n return this;\n }\n\n set body(body: ReadableStream<BodyChunk>) {\n this.#body = body;\n }\n\n get body() {\n return this.#body;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n}\n", "import {AbstractHttpRequest, MapHttpHeaders} from '../../http/exchange.js';\nimport type {\n BodyChunk,\n HttpMethod, HttpResponse,\n MutableHttpHeaders,\n ReadonlyHeaderValue,\n ReadonlyHttpHeaders\n} from '../../../types/web/http';\nimport {ServerHttpRequest} from '../../../types/web/server';\n\nimport stream from 'node:stream/web';\nimport {AbstractServerHttpResponse, DefaultWebExchange} from '../../server/exchange.js';\n\nimport type {Principal} from '../../../types/auth';\n\nexport class MockServerHttpRequest extends AbstractHttpRequest<ReadonlyHttpHeaders> implements ServerHttpRequest {\n readonly #url: URL;\n #body?: Blob;\n upgrade = false;\n\n constructor(url: URL | string, method?: HttpMethod) {\n super(new MapHttpHeaders());\n if (typeof url === 'string') {\n if (URL.canParse(url)) {\n url = new URL(url);\n } else if (URL.canParse(url, 'http://localhost')) {\n url = new URL(url, 'http://localhost');\n } else {\n throw new TypeError('URL cannot parse url');\n }\n }\n this.#url = url;\n this.method = method ?? 'GET';\n this.setHeader('Host', this.#url.hostname);\n this.path = this.#url.pathname ?? '/';\n }\n\n method: HttpMethod;\n path: string;\n\n get host() {\n return super.parseHost(this.#url.host);\n }\n\n get protocol() {\n return super.parseProtocol((this.#url.protocol).slice(0, -1));\n }\n\n get body() {\n if (this.#body !== undefined) {\n const blob = this.#body;\n const asyncIterator: AsyncGenerator<BodyChunk> = (async function* () {\n const bytes = await blob.bytes();\n yield bytes;\n })();\n return stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>;\n }\n }\n\n blob(): Promise<Blob> {\n const body = this.#body;\n return body ? Promise.resolve(body) : Promise.reject(new Error(`no body set`));\n }\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n async writeBody(body?: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk) {\n if (body === undefined) {\n this.#body = new Blob([]);\n return;\n }\n if (body instanceof ReadableStream) {\n const chunks: BodyChunk[] = [];\n const reader = body.getReader();\n let done = false;\n while (!done) {\n const {value, done: readDone} = await reader.read();\n if (readDone) {\n done = true;\n } else {\n chunks.push(value);\n }\n }\n this.#body = new Blob(chunks);\n }\n else {\n body = await body;\n if (typeof body === 'string') {\n this.#body = new Blob([body], {type: 'text/plain'});\n } else {\n this.#body = new Blob([body]);\n }\n }\n if (!this.headers.has('content-type')) {\n this.setHeader('Content-Type', this.#body.type || 'application/octet-stream');\n }\n\n }\n\n get URL() {\n return new URL(this.path + this.#url.search + this.#url.hash, `${this.protocol}://${this.host}`);\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n}\n\nexport class MockServerHttpResponse extends AbstractServerHttpResponse implements HttpResponse<MutableHttpHeaders> {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error('No content was written to the response body nor end was called on this response.');\n };\n\n constructor() {\n super(new MapHttpHeaders());\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n let bodyStream: ReadableStream<BodyChunk> | undefined;\n this.#body = () => {\n bodyStream ??= stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n return bodyStream;\n };\n\n const reader = body.getReader();\n let done = false;\n do {\n const {value, done: readDone} = await reader.read();\n if (readDone) {\n done = true;\n } else {\n chunks.push(value);\n }\n } while (!done);\n return true;\n }\n }\n\n get statusCode() {\n return super.statusCode!; // :(\n }\n\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#body = () => {\n throw new Error('Not available with custom write handler');\n }\n this.#writeHandler = handler;\n }\n\n\n getNativeResponse<T>(): T {\n throw new Error('This is a mock. No running server, no native response.');\n }\n\n protected applyStatusCode(): void {}\n protected applyHeaders(): void {}\n protected applyCookies(): void {\n for (const cookie of this.cookies) {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n }\n }\n\n bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n const it = (async function* () {\n const resolved = await body;\n if (resolved === undefined) {\n return;\n }\n yield resolved;\n })();\n return this.#writeHandler(stream.ReadableStream.from(it) as ReadableStream<BodyChunk>);\n }\n\n async end(): Promise<boolean> {\n return this.doCommit(async () => {\n return await new Promise((resolve, reject) => {\n this.#writeHandler(stream.ReadableStream.from([]) as ReadableStream);\n });\n });\n }\n\n getBody() {\n return this.#body();\n }\n}\n\n\nexport class MockWebExchange extends DefaultWebExchange<MockServerHttpRequest, MockServerHttpResponse> {\n readonly #principal?: Principal;\n constructor(request: MockServerHttpRequest, response?: MockServerHttpResponse, principal?: Principal) {\n super(request, response ?? new MockServerHttpResponse());\n this.#principal = principal;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(this.#principal as P);\n }\n}\n", "import type {Principal} from '../../types/auth';\nimport {\n BodyChunk,\n HeaderValue,\n HeaderValues,\n HttpCookie,\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHeaderValues,\n ReadonlyHttpHeaders,\n ResponseCookie\n} from '../../types/web/http'\n\nimport type {\n ServerHttpRequest,\n ServerHttpResponse,\n ServerWebExchange\n} from '../../types/web/server';\nimport { AbstractHttpHeaders, AbstractHttpRequest, AbstractHttpResponse } from '../http/exchange.ts';\nimport { httpStatusCode } from '../http/status.ts';\nimport net from 'node:net';\nimport http from 'node:http';\nimport http2 from 'node:http2';\n\nexport class ExtendedHttpIncomingMessage extends http.IncomingMessage {\n // circular reference to the exchange\n exchange?: ServerWebExchange;\n\n upgradeHead?: Buffer<ArrayBufferLike>\n\n\n get urlBang(): string {\n return this.url!;\n }\n\n get socketEncrypted(): boolean {\n // see tls.TLSSocket#encrypted\n return this.socket['encrypted'] === true;\n }\n}\n\nexport class ExtendedHttpServerResponse<Request extends ExtendedHttpIncomingMessage = ExtendedHttpIncomingMessage> extends http.ServerResponse<Request> {\n\n markHeadersSent(): void {\n this['_header'] = true; // prevent response from being sent\n }\n\n getRawHeaderNames(): string[] {\n return super['getRawHeaderNames']();\n }\n}\n\nabstract class AbstractServerHttpRequest extends AbstractHttpRequest<ReadonlyHttpHeaders> {\n abstract getNativeRequest<T>(): T;\n}\n\nexport abstract class AbstractServerHttpResponse extends AbstractHttpResponse<MutableHttpHeaders> {\n #cookies: ResponseCookie[] = [];\n #statusCode?: HttpStatusCode;\n #state: 'new' | 'committing' | 'commit-action-failed' | 'committed' = 'new';\n #commitActions: (() => Promise<void>)[] = [];\n\n setStatusCode(statusCode?: HttpStatusCode): boolean {\n if (this.#state === 'committed') {\n return false;\n }\n else {\n this.#statusCode = statusCode;\n return true;\n }\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.setStatusCode(statusCode === undefined ? undefined : httpStatusCode(statusCode));\n };\n\n get statusCode(): HttpStatusCode | undefined {\n return this.#statusCode;\n }\n\n addCookie(cookie: ResponseCookie): this {\n if (this.#state === 'committed') {\n throw new Error(`Cannot add cookie ${JSON.stringify(cookie)} because HTTP response has already been committed`);\n }\n this.#cookies.push(cookie);\n return this;\n }\n\n abstract getNativeResponse<T>(): T;\n\n beforeCommit(action: () => Promise<void>): void {\n this.#commitActions.push(action);\n }\n\n get commited(): boolean {\n const state = this.#state;\n return state !== 'new' && state !== 'commit-action-failed';\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n if (body instanceof ReadableStream) {\n throw new Error('ReadableStream body not supported yet');\n }\n const buffer = await body;\n try {\n // touch buffers if needed\n\n return await this.doCommit(async () => {\n\n return await this.bodyInternal(Promise.resolve(buffer));\n\n }).catch(error => {\n // release buffers\n throw error;\n });\n }\n catch (error) {\n // clear content headers\n throw error;\n }\n }\n\n abstract bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean>;\n\n async end(): Promise<boolean> {\n if (!this.commited) {\n return this.doCommit(async () => {\n return await this.bodyInternal(Promise.resolve());\n });\n }\n else {\n return Promise.resolve(false);\n }\n }\n\n protected doCommit(writeAction?: () => Promise<boolean>): Promise<boolean> {\n const state = this.#state;\n let allActions = Promise.resolve();\n if (state === 'new') {\n this.#state = 'committing';\n if (this.#commitActions.length > 0) {\n allActions = this.#commitActions\n .reduce(\n (acc, cur) => acc.then(() => cur()),\n Promise.resolve())\n .catch((error) => {\n const state = this.#state;\n if (state === 'committing') {\n this.#state = 'commit-action-failed';\n // clear content headers\n }\n });\n }\n }\n else if (state === 'commit-action-failed') {\n this.#state = 'committing';\n // skip commit actions\n } else {\n return Promise.resolve(false);\n }\n\n allActions = allActions.then(() => {\n this.applyStatusCode();\n this.applyHeaders();\n this.applyCookies();\n this.#state = 'committed';\n });\n\n\n return allActions.then(async () => {\n return writeAction !== undefined ? await writeAction() : true;\n });\n }\n\n protected applyStatusCode(): void {}\n protected applyHeaders(): void {}\n protected applyCookies(): void {}\n}\nexport class HttpServerRequest extends AbstractServerHttpRequest implements ServerHttpRequest {\n\n #url?: URL;\n #cookies?: HttpCookie[];\n readonly #req: ExtendedHttpIncomingMessage;\n\n constructor(req: ExtendedHttpIncomingMessage) {\n super(new IncomingMessageHeaders(req));\n this.#req = req;\n }\n\n getNativeRequest<T>(): T {\n return this.#req as T;\n }\n\n get upgrade() {\n return this.#req['upgrade'];\n }\n\n get http2(): boolean {\n return this.#req.httpVersionMajor >= 2;\n }\n\n get path() {\n return this.URL?.pathname;\n }\n\n get URL() {\n this.#url ??= new URL(this.#req.urlBang, `${this.protocol}://${this.host}`);\n return this.#url;\n }\n\n get query() {\n return this.URL?.search;\n }\n\n get method() {\n return this.#req.method as HttpMethod;\n }\n\n get host() {\n let dh: string | undefined = undefined;\n if (this.#req.httpVersionMajor >= 2) {\n dh = (this.#req.headers as http2.IncomingHttpHeaders)[':authority'];\n }\n dh ??= this.#req.socket.remoteAddress;\n return super.parseHost(dh);\n }\n\n get protocol() {\n let dp: string | undefined = undefined;\n if (this.#req.httpVersionMajor > 2) {\n dp = (this.#req.headers as http2.IncomingHttpHeaders)[':scheme'];\n }\n dp ??= this.#req.socketEncrypted ? 'https' : 'http';\n return super.parseProtocol(dp);\n }\n\n get socket() {\n return this.#req.socket;\n }\n\n get remoteAddress(): net.AddressInfo | undefined {\n const family = this.#req.socket.remoteFamily;\n const address = this.#req.socket.remoteAddress;\n const port = this.#req.socket.remotePort;\n const remoteAddress = (!family || !address || !port) ? undefined : { family, address, port };\n return super.parseRemoteAddress(remoteAddress) ?? remoteAddress;\n }\n\n get cookies(): HttpCookie[] {\n this.#cookies ??= super.cookies\n return this.#cookies;\n }\n\n get body(): ReadableStream<BodyChunk> {\n return http.IncomingMessage.toWeb(this.#req) as ReadableStream<BodyChunk>;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n\n\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n\n protected initId(): string {\n const remoteIp = this.#req.socket.remoteAddress;\n if (!remoteIp) {\n throw new Error('Socket has no remote address');\n }\n return `${remoteIp}:${this.#req.socket.remotePort}`;\n }\n}\n\nclass IncomingMessageHeaders extends AbstractHttpHeaders<ReadonlyHeaderValues> implements ReadonlyHttpHeaders {\n readonly #msg: ExtendedHttpIncomingMessage;\n\n constructor(msg: ExtendedHttpIncomingMessage) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.headers[name] !== undefined;\n }\n\n get(name: string): string | (readonly string[]) | undefined {\n return this.#msg.headers[name];\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n\n one(name: string): string | undefined {\n const value = this.#msg.headers[name];\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n keys() {\n return Object.keys(this.#msg.headers).values();\n }\n}\n\nclass OutgoingMessageHeaders extends AbstractHttpHeaders<HeaderValues> implements MutableHttpHeaders {\n readonly #msg: ExtendedHttpServerResponse;\n\n constructor(msg: ExtendedHttpServerResponse) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.hasHeader(name);\n }\n\n keys() {\n return this.#msg.getHeaderNames().values();\n }\n\n get(name: string): HeaderValues {\n return this.#msg.getHeader(name);\n }\n\n one(name: string): HeaderValue {\n const value = this.#msg.getHeader(name);\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n set(name: string, value: HeaderValues): this {\n if (!this.#msg.headersSent) {\n if (Array.isArray(value)) {\n value = value.map(v => typeof v === 'number' ? String(v) : v);\n } else if (typeof value === 'number') {\n value = String(value);\n }\n\n if (value) {\n this.#msg.setHeader(name, value);\n }\n else {\n this.#msg.removeHeader(name);\n }\n }\n return this;\n }\n\n add(name: string, value: string | (readonly string[])): this {\n if (!this.#msg.headersSent) {\n this.#msg.appendHeader(name, value);\n }\n return this;\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n}\n\nexport class HttpServerResponse extends AbstractServerHttpResponse implements ServerHttpResponse {\n readonly #res: ExtendedHttpServerResponse;\n\n constructor(res: ExtendedHttpServerResponse) {\n super(new OutgoingMessageHeaders(res));\n this.#res = res;\n }\n\n getNativeResponse<T>(): T {\n return this.#res as T;\n }\n\n get statusCode(): HttpStatusCode {\n const status = super.statusCode;\n return status ?? {value: this.#res.statusCode};\n }\n\n applyStatusCode() {\n const status = super.statusCode;\n if (status !== undefined) {\n this.#res.statusCode = status.value;\n }\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n return this;\n }\n\n async bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n if (!this.#res.headersSent) {\n if (body instanceof ReadableStream) {\n // http.IncomingMessage.fromWeb(body)\n throw new Error('ReadableStream body not supported in response');\n }\n else {\n const chunk = await body;\n return await new Promise<boolean>((resolve, reject) => {\n try {\n if (chunk === undefined) {\n this.#res.end(() => {\n resolve(true);\n });\n } else {\n if (!this.headers.has('content-length')) {\n // set content-length if not already set\n if (typeof chunk === 'string') {\n this.headers.set('content-length', Buffer.byteLength(chunk));\n }\n else if (chunk instanceof Blob) {\n this.headers.set('content-length', chunk.size);\n }\n else {\n this.headers.set('content-length', chunk.byteLength);\n }\n }\n this.#res.end(chunk, () => {\n resolve(true);\n });\n }\n } catch (e) {\n reject(e instanceof Error ? e : new Error(`end failed: ${e}`));\n }\n });\n }\n }\n else {\n return false; // already ended\n }\n }\n}\n\nexport class ServerHttpRequestDecorator implements ServerHttpRequest {\n readonly #delegate: ServerHttpRequest;\n\n constructor(request: ServerHttpRequest) {\n this.#delegate = request;\n }\n\n get delegate(): ServerHttpRequest {\n return this.#delegate;\n }\n\n get id(): string {\n return this.#delegate.id;\n }\n\n get method(): HttpMethod {\n return this.#delegate.method;\n }\n\n get path(): string {\n return this.#delegate.path;\n }\n\n get protocol() {\n return this.#delegate.protocol;\n }\n\n get host(): string | undefined {\n return this.#delegate.host;\n }\n\n get URL(): URL {\n return this.#delegate.URL;\n }\n\n get headers(): ReadonlyHttpHeaders {\n return this.#delegate.headers;\n }\n\n get cookies(): HttpCookie[] {\n return this.#delegate.cookies;\n }\n\n get remoteAddress() {\n return this.#delegate.remoteAddress;\n }\n\n get upgrade() {\n return this.#delegate.upgrade;\n }\n\n get body(): ReadableStream<BodyChunk> | undefined {\n return this.#delegate.body;\n }\n async blob(): Promise<Blob> {\n return await this.#delegate.blob();\n }\n async text(): Promise<string> {\n return await this.#delegate.text();\n }\n async formData(): Promise<URLSearchParams> {\n return await this.#delegate.formData();\n }\n async json(): Promise<unknown> {\n return await this.#delegate.json();\n }\n\n toString(): string {\n return `${ServerHttpRequestDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeRequest<T>(request: ServerHttpRequest): T {\n if (request instanceof AbstractServerHttpRequest) {\n return request.getNativeRequest<T>();\n }\n else if (request instanceof ServerHttpRequestDecorator) {\n return ServerHttpRequestDecorator.getNativeRequest<T>(request.delegate);\n }\n else {\n throw new Error(`Cannot get native request from ${request.constructor.name}`);\n }\n }\n}\nexport class ServerHttpResponseDecorator implements ServerHttpResponse {\n readonly #delegate: ServerHttpResponse;\n\n constructor(response: ServerHttpResponse) {\n this.#delegate = response;\n }\n\n get delegate(): ServerHttpResponse {\n return this.#delegate;\n }\n\n setStatusCode(statusCode: HttpStatusCode): boolean {\n return this.delegate.setStatusCode(statusCode);\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.delegate.setRawStatusCode(statusCode);\n }\n\n get statusCode(): HttpStatusCode {\n return this.delegate.statusCode;\n }\n\n get cookies(): ResponseCookie[] {\n return this.delegate.cookies;\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.delegate.addCookie(cookie);\n return this;\n }\n\n async end(): Promise<boolean> {\n return await this.delegate.end();\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n return await this.#delegate.body(body);\n }\n\n get headers(): MutableHttpHeaders {\n return this.#delegate.headers;\n }\n\n toString(): string {\n return `${ServerHttpResponseDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeResponse<T>(response: ServerHttpResponse): T {\n if (response instanceof AbstractServerHttpResponse) {\n return response.getNativeResponse<T>();\n }\n else if (response instanceof ServerHttpResponseDecorator) {\n return ServerHttpResponseDecorator.getNativeResponse<T>(response.delegate);\n }\n else {\n throw new Error(`Cannot get native response from ${response.constructor.name}`);\n }\n }\n}\n\nexport class ServerWebExchangeDecorator implements ServerWebExchange {\n readonly #delegate: ServerWebExchange;\n\n protected constructor(exchange: ServerWebExchange) {\n this.#delegate = exchange;\n }\n\n get delegate(): ServerWebExchange {\n return this.#delegate;\n }\n\n get request(): ServerHttpRequest {\n return this.#delegate.request;\n }\n\n get response(): ServerHttpResponse {\n return this.#delegate.response;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.#delegate.attribute(name);\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return this.#delegate.principal();\n }\n\n get logPrefix(): string {\n return this.#delegate.logPrefix;\n }\n\n toString() {\n return `${ServerWebExchangeDecorator.name} [delegate: ${this.delegate}]`;\n }\n}\n\nexport class DefaultWebExchange<Request extends ServerHttpRequest, Response extends ServerHttpResponse> {\n readonly request: Request;\n readonly response: Response;\n readonly #attributes: Record<string, unknown> = {};\n #logId?: unknown;\n #logPrefix: string = '';\n\n constructor(request: Request, response: Response) {\n this.#attributes[LOG_ID_ATTRIBUTE] = request.id;\n this.request = request;\n this.response = response;\n }\n\n get method(): HttpMethod {\n return this.request.method;\n }\n\n get path(): string | null | undefined {\n return this.request.path;\n }\n\n get attributes(): Record<string, unknown> {\n return this.#attributes;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.attributes[name] as T;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(undefined);\n }\n\n get logPrefix(): string {\n const value = this.attribute(LOG_ID_ATTRIBUTE);\n if (this.#logId !== value) {\n this.#logId = value;\n this.#logPrefix = value !== undefined ? `[${value}] ` : '';\n }\n return this.#logPrefix;\n }\n}\n\nexport const LOG_ID_ATTRIBUTE = 'io.interop.gateway.server.log_id';\n\n", "import * as GatewayLogging from '@interopio/gateway/logging/core';\n\nexport import Logger = GatewayLogging.Logger;\n\nexport default function getLogger(name: string): Logger {\n return GatewayLogging.getLogger(`gateway.server.${name}`);\n}\n\n// This function is used to ensure that RegExp objects are displayed correctly when logging.\nexport function regexAwareReplacer<T>(_key: string, value: T): string | T {\n return value instanceof RegExp ? value.toString() : value;\n}\n", "import type { HttpHandler, WebHandler } from './types';\nimport { DefaultWebExchange, ServerHttpResponseDecorator } from './exchange.ts';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Logger } from '@interopio/gateway/logging/api';\nimport type { HttpHeaders } from '../../types/web/http';\nimport type {\n ServerHttpRequest,\n ServerHttpResponse,\n ServerWebExchange\n} from '../../types/web/server';\nimport getLogger from '../logger.ts';\nimport { HttpStatus } from '../http/status.ts';\n\nexport class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {\n\n}\n\nclass HandlerAdapter {\n\n readonly #logger: Logger\n #enableLoggingRequestDetails: boolean = false;\n readonly #delegate: WebHandler;\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }>;\n\n constructor(logger: Logger, delegate: WebHandler) {\n this.#logger = logger;\n this.#delegate = delegate;\n }\n\n protected createExchange(request: ServerHttpRequest, response: ServerHttpResponse): ServerWebExchange {\n\n const exchange = new DefaultWebExchange(request, response);\n return exchange;\n }\n\n set storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>) {\n this.#storage = storage;\n }\n\n set enableLoggingRequestDetails(value: boolean) {\n this.#enableLoggingRequestDetails = value;\n }\n\n formatHeaders(headers: HttpHeaders): string {\n let result = '{';\n\n for (const key of headers.keys()) {\n if (!this.#enableLoggingRequestDetails) {\n result += 'masked, ';\n break;\n } else {\n const value = headers.get(key);\n result += `\"${key}\": \"${value}\", `;\n }\n }\n if (result.endsWith(', ')) {\n result = result.slice(0, -2);\n }\n result += '}';\n return result;\n\n }\n\n formatRequest(request: ServerHttpRequest): string {\n const query = request.URL.search;\n return `HTTP ${request.method} \"${request.path}${query}`;\n }\n\n logRequest(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n this.#logger.debug(`${exchange.logPrefix}${this.formatRequest(exchange.request)}${trace ? `, headers: ${this.formatHeaders(exchange.request.headers)}` : ''}\"`);\n\n }\n }\n\n logResponse(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n const status = exchange.response.statusCode;\n this.#logger.debug(`${exchange.logPrefix}Completed ${status ?? '200 OK'}${trace ? `, headers: ${this.formatHeaders(exchange.response.headers)}` : ''}\"`);\n }\n }\n\n handleUnresolvedError(exchange: ServerWebExchange, error: Error) {\n const {request, response, logPrefix} = exchange;\n\n if (response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR)) {\n this.#logger.error(`${logPrefix}500 Server Error for ${this.formatRequest(request)}`, error);\n return;\n }\n // todo if client disconnected, we should not log an error\n\n this.#logger.error(`${logPrefix}Error [${error.message} for ${this.formatRequest(request)}, but already ended (${response.statusCode})`, error);\n throw error;\n\n }\n\n async web(exchange: ServerWebExchange): Promise<void> {\n return await this.#delegate(exchange);\n }\n\n async http(request: ServerHttpRequest, response: ServerHttpResponse): Promise<void> {\n\n const exchange = this.createExchange(request, response);\n const callback = () => {\n this.logRequest(exchange);\n return this.web(exchange)\n .then(() => {\n this.logResponse(exchange);\n })\n .catch((error: Error) => {\n this.handleUnresolvedError(exchange, error)\n })\n .then(async () => {\n await exchange.response.end();\n });\n };\n\n await new Promise<void>((resolve, reject) => {\n if (this.#storage !== undefined) {\n this.#storage.run({exchange}, () => {\n callback().then(() => resolve()).catch((error) => reject(error));\n });\n } else {\n callback().then(() => resolve()).catch((error) => reject(error));\n }\n });\n }\n}\n\nexport class WebHttpHandlerBuilder {\n readonly #webHandler: WebHandler;\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }> = new AsyncLocalStorage();\n #handlerDecorator?: (handler: HttpHandler) => HttpHandler;\n\n storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>): this {\n this.#storage = storage;\n return this;\n }\n\n httpHandlerDecorator(decorator: (handler: HttpHandler) => HttpHandler): this {\n if (this.#handlerDecorator === undefined) {\n this.#handlerDecorator = decorator;\n } else {\n const previousDecorator = this.#handlerDecorator;\n this.#handlerDecorator = (handler: HttpHandler) => {\n handler = previousDecorator(handler);\n return decorator(handler);\n }\n }\n return this;\n }\n\n constructor(webHandler: WebHandler) {\n this.#webHandler = webHandler;\n }\n\n build(): HttpHandler {\n const logger = getLogger('http');\n\n const adapter = new HandlerAdapter(logger, this.#webHandler);\n if (this.#storage !== undefined) adapter.storage = this.#storage;\n adapter.enableLoggingRequestDetails = false;\n const adapted: HttpHandler = async (request, response) => adapter.http(request, response);\n\n\n return this.#handlerDecorator ? this.#handlerDecorator(adapted) : adapted;\n }\n}\n", "import type {ClientHttpConnector} from '../../client/types.js';\nimport {HttpHandler} from '../../server/types.js';\nimport {MockClientHttpRequest, MockClientHttpResponse} from '../../mock/client/exchange.js';\nimport {MockServerHttpRequest, MockServerHttpResponse} from '../../mock/server/exchange.js';\nimport {BodyChunk, HttpMethod} from '../../../types/web/http';\nimport type {ClientHttpRequest, ClientHttpResponse} from '../../../types/web/client';\n\nimport getLogger from '../../logger.js';\nimport {ServerHttpRequest, ServerHttpResponse} from '../../../types/web/server';\nimport {HttpHeadResponseDecorator} from '../../server/handler.ts';\nimport stream from \"node:stream/web\";\n\n\nclass FailureAfterResponseCompletedError extends Error {\n readonly completedResponse: ClientHttpResponse;\n\n constructor(response: ClientHttpResponse, options: { cause?: Error } = {}) {\n super(`error occurred after response was completed: ${response}`, options);\n this.completedResponse = response;\n }\n}\n\ntype Sink<T> = {\n resolve: (value: T | PromiseLike<T>) => void,\n reject: (reason?: unknown) => void,\n promise: Promise<T>\n}\n\nasync function sink<T>(): Promise<Sink<T>> {\n try {\n return await new Promise<Sink<T>>((result, _error) => {\n\n const promise = new Promise<T>((resolve, reject) => {\n Promise.resolve().then(() => {\n result({promise, resolve, reject});\n });\n });\n });\n }\n catch (error) {\n throw error;\n }\n}\n\nexport class HttpHandlerConnector implements ClientHttpConnector {\n static readonly #logger = getLogger('test.http.handler.connector');\n readonly #httpHandler: HttpHandler;\n\n constructor(httpHandler: HttpHandler) {\n this.#httpHandler = httpHandler;\n }\n\n async connect(method: HttpMethod, uri: URL,\n requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n\n const requestWriteSink = await sink<void>();\n const handlerSink = await sink<void>();\n const savedResponse: [ClientHttpResponse | undefined] = [undefined];\n\n const mockClientRequest = new MockClientHttpRequest(uri, method);\n const mockServerResponse = new MockServerHttpResponse();\n\n mockClientRequest.writeHandler = async (responseBody) => {\n this.log('Invoking HttpHandler for ', method, uri);\n const mockServerRequest = await this.adoptRequest(mockClientRequest, responseBody);\n const responseToUse = this.prepareResponse(mockServerResponse, mockServerRequest);\n\n try {\n await this.#httpHandler(mockServerRequest, responseToUse);\n handlerSink.resolve();\n } catch (e) {\n handlerSink.reject(e);\n }\n return true;\n\n }\n\n mockServerResponse.writeHandler = async (responseBody) => {\n this.log('Creating client response for ', method, uri);\n savedResponse[0] = this.adoptResponse(mockServerResponse, responseBody);\n return true;\n }\n this.log('Writing client request for ', method, uri);\n\n requestCallback(mockClientRequest)\n .then(() => {\n requestWriteSink.resolve();\n })\n .catch(error => {\n requestWriteSink.reject(error);\n });\n\n return Promise.all([requestWriteSink.promise, handlerSink.promise])\n .catch((error) => {\n const response = savedResponse[0];\n throw response !== undefined ? new FailureAfterResponseCompletedError(response, {cause: error}) : error;\n }).then(() => {\n const response = savedResponse[0];\n return response ?? this.adoptResponse(mockServerResponse, stream.ReadableStream.from([]) as ReadableStream<BodyChunk>);\n });\n\n }\n\n private log(message: string, method: HttpMethod, uri: URL): void {\n if (HttpHandlerConnector.#logger.enabledFor('debug')) {\n HttpHandlerConnector.#logger.debug(`${message} ${method} \"${uri.href}\"`);\n }\n }\n\n private async adoptRequest(request: MockClientHttpRequest, body: ReadableStream<BodyChunk>): Promise<ServerHttpRequest> {\n const method = request.method;\n const uri = request.URL;\n const headers = request.headers;\n const cookies = request.cookies;\n const result = new MockServerHttpRequest(uri, method)\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n await result.writeBody(body)\n return result;\n }\n\n private prepareResponse(response: ServerHttpResponse, request: ServerHttpRequest): ServerHttpResponse {\n return request.method === 'HEAD' ? new HttpHeadResponseDecorator(response) : response;\n\n }\n\n private adoptResponse(response: MockServerHttpResponse, body: ReadableStream<BodyChunk>): ClientHttpResponse {\n const status = response.statusCode;\n const headers = response.headers;\n const cookies = response.cookies;\n const result = new MockClientHttpResponse(status);\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n result.body = body;\n return result;\n }\n}\n\n", "import {IOGateway} from '@interopio/gateway';\nimport {OriginFilters} from '../../types/web/server';\nimport getLogger from '../logger.js';\n\nconst log = getLogger('gateway.ws.client-verify');\n\nexport type ProcessedOriginFilters\n = Required<Omit<OriginFilters, 'blacklist' | 'whitelist'>>\n //| Required<Omit<GatewayServer.OriginFilters, 'block' | 'allow'>>\n ;\n\nfunction acceptsMissing(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.missing) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nfunction tryMatch(originFilters: ProcessedOriginFilters, origin: string): boolean | undefined {\n const block = originFilters.block ?? originFilters['blacklist'];\n const allow = originFilters.allow ?? originFilters['whitelist'];\n if (block.length > 0 && IOGateway.Filtering.valuesMatch(block, origin)) {\n log.warn(`origin ${origin} matches block filter`);\n return false;\n } else if (allow.length > 0 && IOGateway.Filtering.valuesMatch(allow, origin)) {\n if (log.enabledFor('debug')) {\n log.debug(`origin ${origin} matches allow filter`);\n }\n return true;\n }\n}\n\nfunction acceptsNonMatched(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.non_matched) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nexport function acceptsOrigin(origin?: string, originFilters?: ProcessedOriginFilters): boolean {\n if (!originFilters) {\n return true;\n }\n if (!origin) {\n return acceptsMissing(originFilters);\n } else {\n const matchResult: boolean | undefined = tryMatch(originFilters, origin);\n if (matchResult) {\n return matchResult;\n } else {\n return acceptsNonMatched(originFilters);\n }\n }\n}\n\nexport function regexifyOriginFilters(originFilters?: OriginFilters): ProcessedOriginFilters | undefined {\n if (originFilters) {\n const block = (originFilters.block ?? originFilters.blacklist ?? []).map(IOGateway.Filtering.regexify);\n const allow = (originFilters.allow ?? originFilters.whitelist ?? []).map(IOGateway.Filtering.regexify);\n return {\n non_matched: originFilters.non_matched ?? 'allow',\n missing: originFilters.missing ?? 'allow',\n allow,\n block,\n }\n }\n}\n", "import type {ServerWebExchange} from '../../../types/web/server';\n\nexport type MatchResult = Readonly<{ match: boolean, variables: Readonly<Record<string, string>> }>;\n\nexport interface ServerWebExchangeMatcher {\n /**\n * Matches the given exchange against the matcher.\n * @param exchange The web exchange to match.\n * @returns A promise that resolves to true if the exchange matches, false otherwise.\n */\n (exchange: ServerWebExchange): Promise<MatchResult>;\n\n /**\n * Returns a string representation of the matcher.\n * @returns A string representation of the matcher.\n */\n toString(): string;\n}\n\nexport type ServerWebExchangeMatcherEntry<T> = Readonly<[ServerWebExchangeMatcher, T]>\n\nexport const or: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (result.match) {\n return match();\n }\n }\n return NO_MATCH;\n };\n}\n\nexport const and: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]) => {\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (!result.match) {\n return NO_MATCH;\n }\n }\n return match();\n };\n matcher.toString = () => `and(${matchers.map(m => m.toString()).join(', ')})`;\n return matcher;\n}\n\n\nexport const not: (matcher: ServerWebExchangeMatcher) => ServerWebExchangeMatcher = (matcher: ServerWebExchangeMatcher): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const result = await matcher(exchange);\n return result.match ? NO_MATCH : match();\n };\n}\n\nexport const anyExchange: ServerWebExchangeMatcher = async (_exchange: ServerWebExchange): Promise<MatchResult> => {\n return match();\n}\nanyExchange.toString = () => 'any-exchange';\n\nconst EMPTY_OBJECT = Object.freeze({});\nexport const NO_MATCH: MatchResult = Object.freeze({match: false, variables: EMPTY_OBJECT});\nexport const match = (variables: Record<string, string> = EMPTY_OBJECT): MatchResult => {\n return {match: true, variables};\n}\n\nexport const pattern: ((pattern: string | RegExp, opts?: {method?: string}) => ServerWebExchangeMatcher) = (pattern, opts) => {\n const method = opts?.method;\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n const path = request.path;\n if (method !== undefined && request.method !== method) {\n return NO_MATCH;\n }\n if (typeof pattern === 'string') {\n if (path === pattern) {\n return match();\n }\n return NO_MATCH;\n }\n else {\n const match = pattern.exec(path);\n if (match === null) {\n return NO_MATCH;\n }\n return {match: true, variables: {...match.groups}};\n }\n };\n matcher.toString = () => {\n return `pattern(${pattern.toString()}, method=${method ?? '<any>'})`;\n }\n return matcher\n\n}\nexport const mediaType : ((opts: {mediaTypes: string[], ignoredMediaTypes?: string[], useEquality?: boolean}) => ServerWebExchangeMatcher) = (opts): ServerWebExchangeMatcher => {\n\n const shouldIgnore = (requestedMediaType: string): boolean => {\n if (opts.ignoredMediaTypes !== undefined) {\n for (const ignoredMediaType of opts.ignoredMediaTypes) {\n if (requestedMediaType === ignoredMediaType || ignoredMediaType === '*/*') {\n return true;\n }\n }\n }\n return false;\n }\n\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n let requestMediaTypes: string[];\n try {\n requestMediaTypes = request.headers.list('accept');\n }\n catch (e) {\n return NO_MATCH;\n }\n for (const requestedMediaType of requestMediaTypes) {\n if (shouldIgnore(requestedMediaType)) {\n continue;\n }\n for (const mediaType of opts.mediaTypes) {\n if (requestedMediaType.startsWith(mediaType)) {\n return match();\n }\n }\n }\n\n return NO_MATCH;\n };\n}\n\nexport const upgradeMatcher: ServerWebExchangeMatcher = async ({request}: ServerWebExchange): Promise<MatchResult> => {\n const upgrade = request.upgrade && request.headers.one('upgrade')?.toLowerCase() === 'websocket';\n return upgrade ? match() : NO_MATCH;\n};\nupgradeMatcher.toString = () => 'websocket upgrade';\n", "import {regexifyOriginFilters} from '../server/ws-client-verify.js';\nimport type {SecurityContext} from '../server/security/security-context.js';\nimport {pattern, ServerWebExchangeMatcher} from '../server/util/matchers.js';\nimport type {CorsConfig} from '../server/cors.js';\nimport type {Middleware} from '../server/types.ts';\nimport type {AsyncLocalStorage} from 'node:async_hooks';\nimport type {SocketRoute} from '../server/socket.js';\nimport {GatewayServer} from '../../gateway-server';\nimport type {\n ServerConfigurer,\n ServerConfigurerHandlerSpec,\n ServerConfigurerSocketSpec,\n ServerExchangeOptions,\n ServerWebExchange\n} from '../../types/web/server';\nimport type {AuthorizationRule} from '../../types/auth';\nimport {IOGateway} from '@interopio/gateway';\nexport type PathPattern = string | RegExp;\nexport type RouteConfig = Readonly<{\n readonly storage: AsyncLocalStorage<{\n exchange: ServerWebExchange,\n securityContext?: Promise<SecurityContext>\n }>,\n readonly serverHeader?: string | false\n readonly corsConfig?: GatewayServer.ServerConfig['cors'],\n readonly authConfig?: GatewayServer.ServerConfig['auth'],\n readonly middleware: Middleware,\n readonly cors: Array<[PathPattern, CorsConfig | undefined]>,\n readonly authorize: Array<[ServerWebExchangeMatcher, AuthorizationRule]>\n readonly sockets: Map<string, SocketRoute>\n}>\n\nexport async function configure(app: GatewayServer.ServerCustomizer, config: GatewayServer.ServerConfig, routes: RouteConfig): Promise<void> {\n const applyCors = (request: ServerConfigurerHandlerSpec['request'], options?: ServerExchangeOptions) => {\n // // disable CORS for this route\n // if (options?.cors === false) {\n // const path = request.path as (PathPattern);\n // routes.cors.push([request.path, undefined]);\n // }\n if (options?.cors) {\n const cors: CorsConfig = options.cors === true ? {\n allowOrigins: options.origins?.allow?.map(IOGateway.Filtering.regexify),\n allowMethods: request.method === undefined ? ['*'] : [request.method],\n allowCredentials: options.authorize?.access !== 'permitted' ? true : undefined,\n } : options.cors;\n const path = request.path as (PathPattern);\n routes.cors.push([path, cors]);\n }\n }\n\n const configurer = new class implements ServerConfigurer {\n\n handle(...handlers: Array<ServerConfigurerHandlerSpec>) {\n handlers.forEach(({request, options, handler}) => {\n const matcher = pattern(IOGateway.Filtering.regexify(request.path) as string | RegExp, {method: request.method});\n if (options?.authorize) {\n routes.authorize.push([matcher, options.authorize]);\n }\n\n applyCors(request, options);\n const middleware = async (exchange: ServerWebExchange, next: () => Promise<void>): Promise<void> => {\n const {match, variables} = await matcher(exchange);\n if (match) {\n await handler(exchange, variables);\n } else {\n await next();\n }\n };\n routes.middleware.push(middleware);\n });\n }\n\n socket(...sockets: Array<ServerConfigurerSocketSpec>) {\n for (const {path, factory, options} of sockets) {\n const route = path ?? '/';\n\n // cors and authorize are currently handled for ws\n routes.sockets.set(route, {\n default: path === undefined,\n ping: options?.ping,\n factory: factory,\n maxConnections: options?.maxConnections,\n authorize: options?.authorize,\n originFilters: regexifyOriginFilters(options?.origins)\n });\n }\n }\n };\n await app(configurer, config);\n}\n", "type MiddlewareFunction<T> = ((ctx: T, next: (ctx?: T) => Promise<void>) => Promise<void>) | ((ctx: T) => Promise<void>);\n\n// https://github.com/koajs/compose/blob/master/index.js\n/**\n * @typeParam T - Type of context passed through the middleware\n * @param middleware middleware stack\n * @return {MiddlewareFunction}\n */\nexport function compose<T>(...middleware: MiddlewareFunction<T>[]): (ctx: T) => Promise<void> {\n if (!Array.isArray(middleware)) {\n throw new Error('middleware must be array!');\n }\n const fns = middleware.flat();\n for (const fn of fns) {\n if (typeof fn !== 'function') {\n throw new Error('middleware must be compose of functions!');\n }\n }\n return async function (ctx: T, next?: (ctx?: T) => Promise<void>) {\n const dispatch = async (i: number, dispatchedCtx: T): Promise<void> => {\n const fn = i === fns.length ? next : fns[i];\n if (fn === undefined) {\n return;\n }\n let nextCalled = false;\n let nextResolved = false;\n const nextFn = async (nextCtx?: T) => {\n if (nextCalled) {\n throw new Error('next() called multiple times');\n }\n nextCalled = true;\n try {\n return await dispatch(i + 1, nextCtx ?? dispatchedCtx);\n }\n finally {\n nextResolved = true;\n }\n };\n const result = await fn(dispatchedCtx, nextFn);\n if (nextCalled && !nextResolved) {\n throw new Error('middleware resolved before downstream.\\n\\t You are probably missing an await or return statement in your middleware function.');\n }\n return result;\n }\n\n return dispatch(0, ctx);\n }\n}\n", "import type {ClientHttpConnector} from '../../client/types.js';\nimport {FetchClientHttpConnector} from '../../client/fetch.js';\nimport type {\n HttpMethod\n} from '../../../types/web/http';\nimport type {\n TestClient,\n TestClientBuilder,\n MockServerSpec\n} from '../../../types/web/test';\nimport {GatewayServer} from '../../../gateway-server';\nimport {HttpHandlerConnector} from './handler.js';\nimport {WebHttpHandlerBuilder} from '../../server/handler.js';\nimport {configure, RouteConfig} from '../../app/route.js';\nimport {compose} from '../../common/compose.js';\nimport {AsyncLocalStorage} from 'node:async_hooks';\nimport {ServerWebExchange} from '../../../types/web/server';\nimport {SocketRoute} from '../../server/socket.js';\n\nexport function bindToApp(app: GatewayServer.ServerCustomizer): MockServerSpec {\n return new AppSpec(app);\n}\n\nexport function bindToServer(): TestClientBuilder {\n return new DefaultTestClientBuilder();\n}\n\nclass DefaultTestClient implements TestClient {\n readonly #connector: ClientHttpConnector;\n readonly #baseUrl?: string;\n readonly #builder: TestClientBuilder;\n constructor(connector: ClientHttpConnector,\n baseUrl: string | undefined,\n builder: TestClientBuilder) {\n this.#connector = connector;\n this.#baseUrl = baseUrl;\n this.#builder = builder;\n }\n\n fetch = async (input: string | URL, init?: RequestInit): Promise<Response> => {\n try {\n const method = init?.method as HttpMethod ?? 'GET';\n const uri = new URL(input, this.#baseUrl);\n const response = await this.#connector.connect(method, uri, async (request) => {\n // fetch Request to ClientHttpRequest\n const headers = new Headers(init?.headers);\n for (const [name, value] of headers.entries()) {\n request.headers.add(name, value);\n }\n let body = init?.body ?? Promise.resolve();\n if (body instanceof ReadableStream) {\n throw new Error(`Unsupported body type ${typeof init?.body} in fetch request`);\n }\n if (body instanceof FormData) {\n // Convert FormData to URLSearchParams\n const formDataEntries = Array.from(body.entries());\n body = new URLSearchParams();\n for (const [key, value] of formDataEntries) {\n body.append(key, value.toString());\n }\n }\n if (body instanceof URLSearchParams) {\n if (!request.headers.has('content-type')) {\n request.headers.set('content-type', 'application/x-www-form-urlencoded');\n }\n body = body.toString();\n }\n if (body instanceof Blob) {\n body = await body.bytes();\n }\n if (typeof body === 'string') {\n body = Buffer.from(body);\n }\n await request.body(body);\n\n\n });\n // ClientHttpResponse to fetch Response\n const headers = new Headers();\n for (const key of response.headers.keys()) {\n const values = response.headers.list(key);\n for (const value of values) {\n headers.append(key, value);\n }\n }\n const status = response.statusCode?.value;\n const body = await response.blob();\n return new Response(body, {status, headers});\n }\n catch (error) {\n return Response.error();\n }\n\n }\n}\n\nclass DefaultTestClientBuilder implements TestClientBuilder {\n readonly #httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>;\n #connector?: ClientHttpConnector;\n #baseUrl: string = 'http://localhost:8080';\n constructor(httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>, connector?: ClientHttpConnector) {\n if (!(httpHandlerBuilder === undefined || connector === undefined)) {\n throw new Error('You can only set either httpHandlerBuilder or connector, not both.');\n }\n this.#connector = connector;\n this.#httpHandlerBuilder = httpHandlerBuilder;\n }\n\n baseUrl(baseUrl: string): this {\n this.#baseUrl = baseUrl;\n return this;\n }\n\n clientConnector(connector: ClientHttpConnector): this {\n this.#connector = connector;\n return this;\n }\n\n async build(): Promise<TestClient> {\n let connector = this.#connector;\n if (connector === undefined) {\n if (this.#httpHandlerBuilder !== undefined) {\n connector = new HttpHandlerConnector((await this.#httpHandlerBuilder).build());\n }\n }\n connector ??= new FetchClientHttpConnector();\n\n return new DefaultTestClient(connector, this.#baseUrl, this);\n }\n}\n\nabstract class AbstractMockServerSpec implements MockServerSpec {\n configureClient(): TestClientBuilder {\n const builder = this.initHttpHandlerBuilder();\n return new DefaultTestClientBuilder(builder);\n }\n\n protected abstract initHttpHandlerBuilder(): Promise<WebHttpHandlerBuilder>;\n\n async build(): Promise<TestClient> {\n return await this.configureClient().build();\n }\n}\n\nclass AppSpec extends AbstractMockServerSpec {\n readonly #app: GatewayServer.ServerCustomizer;\n constructor(app: GatewayServer.ServerCustomizer) {\n super();\n this.#app = app;\n }\n\n protected async initHttpHandlerBuilder() {\n const routes: RouteConfig = {\n middleware: [],\n corsConfig: {\n allowOrigin: ['http://localhost:8086']\n },\n cors: [],\n authConfig: {type: \"none\"},\n authorize: [],\n storage: new AsyncLocalStorage<{ exchange: ServerWebExchange }>(),\n sockets: new Map<string, SocketRoute>()\n };\n\n await configure(this.#app, {}, routes);\n const handler = compose(...routes.middleware)\n return new WebHttpHandlerBuilder(handler);\n }\n}\n", "import { bindToApp, bindToServer } from './server/client.ts';\n\nexport const TestClient = {\n bindToApp: bindToApp,\n bindToServer: bindToServer\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["isIP", "Cookie", "parseHost", "headers", "defaultHost", "host", "port", "isForwardedSsl", "v", "parseProtocol", "defaultProtocol", "proto", "parseRemoteAddress", "url", "remoteAddress", "AbstractHttpMessage", "#headers", "AbstractHttpRequest", "_AbstractHttpRequest", "#id", "parseCookies", "AbstractHttpResponse", "parseResponseCookies", "responseCookie", "parseHeader", "value", "list", "start", "end", "i", "toList", "values", "s", "cs", "tc", "cookie", "parsed", "result", "MapHttpHeaders", "name", "values", "toList", "value", "prev", "AbstractClientHttpRequest", "AbstractHttpRequest", "method", "uri", "MapHttpHeaders", "AbstractClientHttpResponse", "AbstractHttpResponse", "statusCode", "headers", "DefaultHttpStatusCode", "#value", "value", "HttpStatus", "_HttpStatus", "#VALUES", "key", "code", "status", "#phrase", "phrase", "httpStatusCode", "FetchClientHttpRequest", "AbstractClientHttpRequest", "#body", "method", "uri", "body", "headers", "key", "value", "toHttpHeaders", "result", "MapHttpHeaders", "FetchClientHttpResponse", "AbstractClientHttpResponse", "#response", "response", "httpStatusCode", "FetchClientHttpConnector", "#fetch", "fetchFn", "requestCallback", "fetchClientHttpRequest", "fetchRequest", "fetchResponse", "stream", "MockClientHttpRequest", "AbstractClientHttpRequest", "#writeHandler", "#body", "uri", "method", "body", "chunks", "reader", "done", "value", "doneReading", "handler", "asyncIterator", "MockClientHttpResponse", "AbstractHttpResponse", "#statusCode", "status", "MapHttpHeaders", "httpStatusCode", "name", "charset", "chunk", "stream", "http", "ExtendedHttpIncomingMessage", "ExtendedHttpServerResponse", "AbstractServerHttpResponse", "AbstractHttpResponse", "#cookies", "#statusCode", "#state", "#commitActions", "statusCode", "httpStatusCode", "cookie", "action", "state", "body", "buffer", "error", "writeAction", "allActions", "acc", "cur", "ServerHttpResponseDecorator", "_ServerHttpResponseDecorator", "#delegate", "response", "statusCode", "cookie", "body", "AbstractServerHttpResponse", "DefaultWebExchange", "#attributes", "#logId", "#logPrefix", "request", "response", "LOG_ID_ATTRIBUTE", "name", "value", "MockServerHttpRequest", "AbstractHttpRequest", "#url", "#body", "url", "method", "MapHttpHeaders", "blob", "asyncIterator", "stream", "body", "text", "chunks", "reader", "done", "value", "readDone", "name", "MockServerHttpResponse", "AbstractServerHttpResponse", "#writeHandler", "bodyStream", "handler", "cookie", "it", "resolved", "resolve", "reject", "GatewayLogging", "getLogger", "name", "AsyncLocalStorage", "HttpHeadResponseDecorator", "ServerHttpResponseDecorator", "HandlerAdapter", "#logger", "#enableLoggingRequestDetails", "#delegate", "#storage", "logger", "delegate", "request", "response", "DefaultWebExchange", "storage", "value", "headers", "result", "key", "query", "exchange", "trace", "status", "error", "logPrefix", "HttpStatus", "callback", "resolve", "reject", "WebHttpHandlerBuilder", "#webHandler", "AsyncLocalStorage", "#handlerDecorator", "decorator", "previousDecorator", "handler", "webHandler", "getLogger", "adapter", "adapted", "stream", "FailureAfterResponseCompletedError", "response", "options", "sink", "result", "_error", "promise", "resolve", "reject", "error", "HttpHandlerConnector", "_HttpHandlerConnector", "#logger", "getLogger", "#httpHandler", "httpHandler", "method", "uri", "requestCallback", "requestWriteSink", "handlerSink", "savedResponse", "mockClientRequest", "MockClientHttpRequest", "mockServerResponse", "MockServerHttpResponse", "responseBody", "mockServerRequest", "responseToUse", "e", "message", "request", "body", "headers", "cookies", "MockServerHttpRequest", "name", "value", "v", "HttpHeadResponseDecorator", "status", "MockClientHttpResponse", "IOGateway", "log", "getLogger", "regexifyOriginFilters", "originFilters", "block", "IOGateway", "allow", "anyExchange", "_exchange", "match", "EMPTY_OBJECT", "NO_MATCH", "variables", "pattern", "opts", "method", "matcher", "exchange", "request", "path", "upgradeMatcher", "request", "match", "NO_MATCH", "IOGateway", "configure", "app", "config", "routes", "applyCors", "request", "options", "cors", "path", "configurer", "handlers", "handler", "matcher", "pattern", "middleware", "exchange", "next", "match", "variables", "sockets", "factory", "route", "regexifyOriginFilters", "compose", "middleware", "fns", "fn", "ctx", "next", "dispatch", "i", "dispatchedCtx", "nextCalled", "nextResolved", "result", "nextCtx", "AsyncLocalStorage", "bindToApp", "app", "AppSpec", "bindToServer", "DefaultTestClientBuilder", "DefaultTestClient", "#connector", "#baseUrl", "#builder", "connector", "baseUrl", "builder", "input", "init", "method", "uri", "response", "request", "headers", "name", "value", "body", "formDataEntries", "key", "values", "status", "#httpHandlerBuilder", "httpHandlerBuilder", "HttpHandlerConnector", "FetchClientHttpConnector", "AbstractMockServerSpec", "#app", "routes", "configure", "handler", "compose", "WebHttpHandlerBuilder", "TestClient", "bindToApp", "bindToServer"]
|
|
4
|
+
"sourcesContent": ["import type {\n HeaderValues,\n HttpCookie,\n HttpHeaders,\n MutableHttpHeaders,\n ReadonlyHeaderValues,\n ResponseCookie\n} from '../../types/web/http';\nimport { type AddressInfo, isIP } from 'node:net';\nimport { Cookie } from 'tough-cookie';\n\nfunction parseHost(headers: HttpHeaders, defaultHost?: string): string | undefined {\n let host = headers.get('x-forwarded-host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n const port = headers.one('x-forwarded-port');\n if (port) {\n host = `${host}:${port}`;\n }\n }\n host ??= headers.one('host');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host) {\n return (host as string).split(',', 1)[0].trim();\n }\n\n return defaultHost;\n}\n\nfunction isForwardedSsl(headers: HttpHeaders): boolean {\n const v = headers.one('x-forwarded-ssl');\n return (typeof v === 'string') && (v.toLowerCase() === 'on');\n}\n\nfunction parseProtocol(headers: HttpHeaders, defaultProtocol: string): string {\n let proto = headers.get('x-forwarded-proto');\n\n if (Array.isArray(proto)) {\n proto = proto[0];\n }\n if (proto !== undefined) {\n return (proto as string).split(',', 1)[0].trim();\n }\n else if (isForwardedSsl(headers)) {\n return 'https';\n }\n return defaultProtocol;\n}\n\nfunction parseRemoteAddress(url: URL, headers: HttpHeaders, remoteAddress?: AddressInfo) : AddressInfo | undefined {\n const port = remoteAddress ? remoteAddress.port : 'https:' === url.protocol ? 443 : 80;\n\n let host = headers.one('x-forwarded-for');\n if (Array.isArray(host)) {\n host = host[0];\n }\n if (host !== undefined) {\n host = (host as string).split(',', 1)[0].trim();\n return { address: host, port: Number(port), family: isIP(host) === 6 ? 'IPv6' : 'IPv4' };\n }\n}\n\nexport abstract class AbstractHttpMessage<Headers extends HttpHeaders = HttpHeaders> {\n readonly #headers: Headers;\n protected constructor(headers: Headers) {\n this.#headers = headers;\n }\n get headers(): Headers {\n return this.#headers;\n }\n}\n\nexport abstract class AbstractHttpRequest<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n private static logIdCounter = 0;\n #id?: string\n\n get id(): string {\n if (this.#id === undefined) {\n this.#id = `${this.initId()}-${++AbstractHttpRequest.logIdCounter}`;\n\n }\n return this.#id;\n }\n\n protected initId(): string {\n return 'request';\n }\n\n get cookies(): HttpCookie[] {\n return parseCookies(this.headers);\n }\n\n protected parseHost(defaultHost?: string): string | undefined {\n return parseHost(this.headers, defaultHost);\n }\n\n protected parseProtocol(defaultProtocol: string): string {\n return parseProtocol(this.headers, defaultProtocol);\n }\n\n abstract get URL(): URL;\n\n protected parseRemoteAddress(remoteAddress?: AddressInfo) {\n return parseRemoteAddress(this.URL, this.headers, remoteAddress);\n }\n}\n\nexport abstract class AbstractHttpResponse<Headers extends HttpHeaders = HttpHeaders> extends AbstractHttpMessage<Headers> {\n get cookies(): ResponseCookie[] {\n return parseResponseCookies(this.headers);\n }\n\n protected setCookieValue(responseCookie: ResponseCookie): string {\n const cookie = new Cookie({\n key: responseCookie.name,\n value: responseCookie.value,\n maxAge: responseCookie.maxAge,\n domain: responseCookie.domain,\n path: responseCookie.path,\n secure: responseCookie.secure,\n httpOnly: responseCookie.httpOnly,\n sameSite: responseCookie.sameSite\n });\n return cookie.toString();\n }\n\n}\n\nfunction parseHeader(value: string): string[] {\n const list: string[] = [];\n {\n let start = 0;\n let end = 0;\n\n for (let i = 0; i < value.length; i++) {\n switch (value.charCodeAt(i)) {\n case 0x20: // space\n if (start === end) {\n start = end = i + 1;\n }\n break;\n case 0x2c: // comma\n list.push(value.slice(start, end));\n start = end = i + 1;\n break;\n default:\n end = end + 1;\n break;\n }\n }\n list.push(value.slice(start, end));\n }\n\n return list;\n}\n\nfunction toList(values: number | string | (readonly string[]) | undefined): string[] {\n if (typeof values === 'string') {\n values = [values];\n }\n if (typeof values === 'number') {\n values = [String(values)];\n }\n const list: string[] = [];\n if (values) {\n for (const value of values) {\n if (value) {\n list.push(...parseHeader(value));\n }\n }\n }\n return list;\n}\n\nfunction parseCookies(headers: HttpHeaders): HttpCookie[] {\n return headers.list('cookie')\n .map(s => s.split(';').map((cs) => Cookie.parse(cs)))\n .flat(1)\n .filter((tc) => tc !== undefined)\n .map((tc) => {\n const result: HttpCookie = Object.freeze({name: tc.key, value: tc.value});\n return result;\n });\n}\n\ntype Mutable<T> = {-readonly [K in keyof T]: T[K]};\n\nfunction parseResponseCookies(headers: HttpHeaders): ResponseCookie[] {\n return headers.list('set-cookie').map((cookie) => {\n const parsed = Cookie.parse(cookie);\n if (parsed) {\n const result: Mutable<ResponseCookie> = {name: parsed.key, value: parsed.value, maxAge: Number(parsed.maxAge ?? -1)};\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.domain) result.domain = parsed.domain;\n if (parsed.path) result.path = parsed.path;\n if (parsed.secure) result.secure = true;\n if (parsed.httpOnly) result.httpOnly = true;\n if (parsed.sameSite) result.sameSite = parsed.sameSite as 'strict' | 'lax' | 'none';\n return Object.freeze(result);\n }\n }).filter((cookie): cookie is ResponseCookie => cookie !== undefined);\n}\n\n\nexport abstract class AbstractHttpHeaders<Values extends HeaderValues | ReadonlyHeaderValues> {\n protected constructor() {}\n abstract get(name: string): Values\n\n toList(name: string): string[] {\n const values = this.get(name);\n return toList(values);\n }\n}\n\nexport class MapHttpHeaders extends Map<string, (readonly string[])> implements MutableHttpHeaders {\n\n get(name: string) {\n return super.get(name.toLowerCase());\n }\n\n one(name: string): string | undefined {\n return this.get(name)?.[0];\n }\n\n list(name: string) {\n const values = super.get(name.toLowerCase());\n return toList(values);\n }\n\n set(name: string, value: number | string | (readonly string[]) | undefined): this {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n value = [value];\n }\n if (value) {\n return super.set(name.toLowerCase(), value);\n }\n else {\n super.delete(name.toLowerCase());\n return this;\n }\n }\n\n add(name: string, value: string | (readonly string[])) {\n const prev = super.get(name.toLowerCase());\n if (typeof value === 'string') {\n value = [value];\n }\n if (prev) {\n value = prev.concat(value);\n }\n this.set(name, value);\n return this;\n }\n}\n", "import type {\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHttpHeaders\n} from '../../types/web/http';\n\nimport {AbstractHttpRequest, AbstractHttpResponse, MapHttpHeaders} from '../http/exchange.js';\n\nexport abstract class AbstractClientHttpRequest extends AbstractHttpRequest<MutableHttpHeaders> {\n\n protected constructor(method: HttpMethod, uri: URL) {\n super(new MapHttpHeaders());\n this.URL = uri;\n this.method = method;\n }\n\n readonly URL: URL;\n readonly method: HttpMethod;\n}\n\nexport abstract class AbstractClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> {\n protected constructor(statusCode: HttpStatusCode, headers: ReadonlyHttpHeaders) {\n super(headers);\n this.statusCode = statusCode;\n }\n readonly statusCode: HttpStatusCode;\n}\n", "import type {HttpStatusCode} from '../../types/web/http';\n\nclass DefaultHttpStatusCode implements HttpStatusCode {\n readonly #value: number;\n constructor(value: number) {\n this.#value = value;\n }\n get value(): number {\n return this.#value;\n }\n\n toString(): string {\n return this.#value.toString();\n }\n}\n\nexport class HttpStatus implements HttpStatusCode {\n static readonly CONTINUE = new HttpStatus(100, 'Continue');\n static readonly SWITCHING_PROTOCOLS = new HttpStatus(101, 'Switching Protocols');\n\n // 2xx Success\n\n static readonly OK = new HttpStatus(200, 'OK');\n static readonly CREATED = new HttpStatus(201, 'Created');\n static readonly ACCEPTED = new HttpStatus(202, 'Accepted');\n static readonly NON_AUTHORITATIVE_INFORMATION = new HttpStatus(203, 'Non-Authoritative Information');\n static readonly NO_CONTENT = new HttpStatus(204, 'No Content');\n static readonly RESET_CONTENT = new HttpStatus(205, 'Reset Content');\n static readonly PARTIAL_CONTENT = new HttpStatus(206, 'Partial Content');\n static readonly MULTI_STATUS = new HttpStatus(207, 'Multi-Status');\n\n static readonly IM_USED = new HttpStatus(226, 'IM Used');\n\n\n // 3xx Redirection\n static readonly MULTIPLE_CHOICES = new HttpStatus(300, 'Multiple Choices');\n static readonly MOVED_PERMANENTLY = new HttpStatus(301, 'Moved Permanently');\n\n // 4xx Client Error\n\n static readonly BAD_REQUEST = new HttpStatus(400, 'Bad Request');\n static readonly UNAUTHORIZED = new HttpStatus(401, 'Unauthorized');\n static readonly FORBIDDEN = new HttpStatus(403, 'Forbidden');\n static readonly NOT_FOUND = new HttpStatus(404, 'Not Found');\n static readonly METHOD_NOT_ALLOWED = new HttpStatus(405, 'Method Not Allowed');\n static readonly NOT_ACCEPTABLE = new HttpStatus(406, 'Not Acceptable');\n static readonly PROXY_AUTHENTICATION_REQUIRED = new HttpStatus(407, 'Proxy Authentication Required');\n static readonly REQUEST_TIMEOUT = new HttpStatus(408, 'Request Timeout');\n static readonly CONFLICT = new HttpStatus(409, 'Conflict');\n static readonly GONE = new HttpStatus(410, 'Gone');\n static readonly LENGTH_REQUIRED = new HttpStatus(411, 'Length Required');\n static readonly PRECONDITION_FAILED = new HttpStatus(412, 'Precondition Failed');\n static readonly PAYLOAD_TOO_LARGE = new HttpStatus(413, 'Payload Too Large');\n static readonly URI_TOO_LONG = new HttpStatus(414, 'URI Too Long');\n static readonly UNSUPPORTED_MEDIA_TYPE = new HttpStatus(415, 'Unsupported Media Type');\n\n static readonly EXPECTATION_FAILED = new HttpStatus(417, 'Expectation Failed');\n static readonly IM_A_TEAPOT = new HttpStatus(418, 'I\\'m a teapot');\n\n static readonly TOO_EARLY = new HttpStatus(425, 'Too Early');\n static readonly UPGRADE_REQUIRED = new HttpStatus(426, 'Upgrade Required');\n static readonly PRECONDITION_REQUIRED = new HttpStatus(428, 'Precondition Required');\n static readonly TOO_MANY_REQUESTS = new HttpStatus(429, 'Too Many Requests');\n static readonly REQUEST_HEADER_FIELDS_TOO_LARGE = new HttpStatus(431, 'Request Header Fields Too Large');\n static readonly UNAVAILABLE_FOR_LEGAL_REASONS = new HttpStatus(451, 'Unavailable For Legal Reasons');\n\n // 5xx Server Error\n static readonly INTERNAL_SERVER_ERROR = new HttpStatus(500, 'Internal Server Error');\n static readonly NOT_IMPLEMENTED = new HttpStatus(501, 'Not Implemented');\n static readonly BAD_GATEWAY = new HttpStatus(502, 'Bad Gateway');\n static readonly SERVICE_UNAVAILABLE = new HttpStatus(503, 'Service Unavailable');\n static readonly GATEWAY_TIMEOUT = new HttpStatus(504, 'Gateway Timeout');\n static readonly HTTP_VERSION_NOT_SUPPORTED = new HttpStatus(505, 'HTTP Version Not Supported');\n static readonly VARIANT_ALSO_NEGOTIATES = new HttpStatus(506, 'Variant Also Negotiates');\n static readonly INSUFFICIENT_STORAGE = new HttpStatus(507, 'Insufficient Storage');\n static readonly LOOP_DETECTED = new HttpStatus(508, 'Loop Detected');\n static readonly NOT_EXTENDED = new HttpStatus(510, 'Not Extended');\n static readonly NETWORK_AUTHENTICATION_REQUIRED = new HttpStatus(511, 'Network Authentication Required');\n\n static readonly #VALUES: HttpStatus[] = [];\n static {\n Object.keys(HttpStatus)\n .filter(key => key !== 'VALUES' && key !== 'resolve')\n .forEach(key => {\n const value = HttpStatus[key];\n if (value instanceof HttpStatus) {\n Object.defineProperty(value, 'name', {enumerable: true, value: key, writable: false});\n HttpStatus.#VALUES.push(value);\n }\n })\n\n }\n\n static resolve(code: number): HttpStatus | undefined {\n for (const status of HttpStatus.#VALUES) {\n if (status.value === code) {\n return status;\n }\n }\n }\n\n readonly #value: number;\n readonly #phrase: string;\n\n private constructor(value: number, phrase: string) {\n this.#value = value;\n this.#phrase = phrase;\n }\n\n get value(): number {\n return this.#value;\n }\n get phrase(): string {\n return this.#phrase;\n }\n\n toString() {\n return `${this.#value} ${this['name']}`;\n }\n}\n\n\nexport function httpStatusCode(value: number | HttpStatusCode): HttpStatusCode {\n if (typeof value === 'number') {\n if (value < 100 || value > 999) {\n throw new Error(`status code ${value} should be in range 100-999`);\n }\n const status = HttpStatus.resolve(value);\n if (status !== undefined) {\n return status;\n }\n return new DefaultHttpStatusCode(value);\n }\n return value;\n}\n", "import type {ClientHttpConnector} from './types.js';\nimport {AbstractClientHttpRequest, AbstractClientHttpResponse} from './exchange.js';\nimport {MapHttpHeaders} from \"../http/exchange.js\";\n\nimport type {\n HttpMethod,\n BodyChunk\n} from '../../types/web/http';\nimport type {\n ClientHttpRequest,\n ClientHttpResponse\n} from '../../types/web/client';\nimport {httpStatusCode} from \"../http/status.ts\";\n\nclass FetchClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #body?: BodyInit;\n constructor(method: HttpMethod, uri: URL) {\n super(method, uri);\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk): Promise<boolean> {\n this.#body = body instanceof ReadableStream ? body : await body;\n return await this.end();\n }\n\n end() {\n return Promise.resolve(true);\n }\n\n getNativeRequest<T>(): T {\n const method = this.method;\n const headers = new Headers();\n for (const key of this.headers.keys()) {\n if (key.toLowerCase() === 'content-length') {\n continue; // Content-Length is set automatically later\n }\n for (const value of this.headers.list(key)) {\n headers.append(key, value);\n }\n }\n if (!this.headers.has('accept')) {\n headers.append('accept', '*/*');\n }\n const body = this.#body;\n\n return new Request(this.URL, {method, headers, body}) as T;\n }\n}\nfunction toHttpHeaders(headers: Headers): MapHttpHeaders {\n const result = new MapHttpHeaders();\n for (const [key, value] of headers.entries()) {\n result.add(key, value);\n }\n return result;\n}\nclass FetchClientHttpResponse extends AbstractClientHttpResponse implements ClientHttpResponse {\n #response: Response;\n constructor(response: Response) {\n super(httpStatusCode(response.status), toHttpHeaders(response.headers));\n this.#response = response;\n }\n\n get statusMessage() {\n return this.#response.statusText;\n }\n\n get body() {\n return this.#response.body ?? undefined;\n }\n\n blob() {\n return this.#response.blob();\n }\n}\n\nexport class FetchClientHttpConnector implements ClientHttpConnector {\n readonly #fetch: typeof fetch;\n constructor(fetchFn: typeof fetch = globalThis.fetch) {\n this.#fetch = fetchFn;\n }\n\n async connect(method: HttpMethod, uri: URL, requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n const fetchClientHttpRequest = new FetchClientHttpRequest(method, uri);\n await requestCallback(fetchClientHttpRequest);\n const fetchRequest = fetchClientHttpRequest.getNativeRequest<Request>();\n const fetchResponse = await this.#fetch(fetchRequest);\n return new FetchClientHttpResponse(fetchResponse);\n }\n}\n", "import {AbstractClientHttpRequest} from '../../client/exchange.js';\nimport {\n BodyChunk,\n HttpMethod,\n HttpStatusCode,\n type MutableHttpHeaders, type ReadonlyHeaderValue,\n ReadonlyHttpHeaders\n} from '../../../types/web/http';\nimport {ClientHttpRequest, ClientHttpResponse} from '../../../types/web/client';\n\nimport {AbstractHttpResponse, MapHttpHeaders} from '../../http/exchange.js';\nimport {httpStatusCode} from '../../http/status.js';\nimport * as stream from 'node:stream/web';\n\nexport class MockClientHttpRequest extends AbstractClientHttpRequest implements ClientHttpRequest {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error(\"Body not set\");\n };\n constructor(uri: URL, method: HttpMethod) {\n super(method, uri);\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n this.#body = () => {\n return stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n };\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n chunks.push(value);\n }\n } while (!done);\n return true;\n }\n }\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#writeHandler = handler;\n }\n\n getNativeRequest<T>(): T {\n return this as unknown as T;\n }\n\n getBody(): ReadableStream<BodyChunk> {\n return this.#body();\n }\n\n body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n const asyncIterator = (async function* () {\n if (body instanceof ReadableStream) {\n const reader = body.getReader();\n let done: boolean;\n do {\n const {value, done: doneReading} = await reader.read();\n done = doneReading;\n if (value !== undefined) {\n yield value;\n }\n } while (!done);\n }\n else {\n const value = await body;\n if (value !== undefined) {\n yield value;\n }\n }\n\n })();\n return this.#writeHandler(stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>);\n }\n\n async end() {\n return await this.body(Promise.resolve());\n }\n\n}\n\nexport class MockClientHttpResponse extends AbstractHttpResponse<ReadonlyHttpHeaders> implements ClientHttpResponse {\n #statusCode: HttpStatusCode;\n #body: ReadableStream<BodyChunk> = stream.ReadableStream.from([]) as ReadableStream<BodyChunk>;\n constructor(status: number | HttpStatusCode) {\n super(new MapHttpHeaders());\n this.#statusCode = httpStatusCode(status);\n }\n\n get statusCode(): HttpStatusCode {\n return this.#statusCode;\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n\n setBody(body: string, charset?: BufferEncoding): this {\n this.#body = stream.ReadableStream.from([Buffer.from(body, charset)]) as ReadableStream<BodyChunk>;\n return this;\n }\n\n set body(body: ReadableStream<BodyChunk>) {\n this.#body = body;\n }\n\n get body() {\n return this.#body;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n}\n", "import {AbstractHttpRequest, MapHttpHeaders} from '../../http/exchange.js';\nimport type {\n BodyChunk,\n HttpMethod, HttpResponse,\n MutableHttpHeaders,\n ReadonlyHeaderValue,\n ReadonlyHttpHeaders\n} from '../../../types/web/http';\nimport {ServerHttpRequest} from '../../../types/web/server';\n\nimport stream from 'node:stream/web';\nimport {AbstractServerHttpResponse, DefaultWebExchange} from '../../server/exchange.js';\n\nimport type {Principal} from '../../../types/auth';\n\nexport class MockServerHttpRequest extends AbstractHttpRequest<ReadonlyHttpHeaders> implements ServerHttpRequest {\n readonly #url: URL;\n #body?: Blob;\n upgrade = false;\n\n constructor(url: URL | string, method?: HttpMethod) {\n super(new MapHttpHeaders());\n if (typeof url === 'string') {\n if (URL.canParse(url)) {\n url = new URL(url);\n } else if (URL.canParse(url, 'http://localhost')) {\n url = new URL(url, 'http://localhost');\n } else {\n throw new TypeError('URL cannot parse url');\n }\n }\n this.#url = url;\n this.method = method ?? 'GET';\n this.setHeader('Host', this.#url.hostname);\n this.path = this.#url.pathname ?? '/';\n }\n\n method: HttpMethod;\n path: string;\n\n get host() {\n return super.parseHost(this.#url.host);\n }\n\n get protocol() {\n return super.parseProtocol((this.#url.protocol).slice(0, -1));\n }\n\n get body() {\n if (this.#body !== undefined) {\n const blob = this.#body;\n const asyncIterator: AsyncGenerator<BodyChunk> = (async function* () {\n const bytes = await blob.bytes();\n yield bytes;\n })();\n return stream.ReadableStream.from(asyncIterator) as ReadableStream<BodyChunk>;\n }\n }\n\n blob(): Promise<Blob> {\n const body = this.#body;\n return body ? Promise.resolve(body) : Promise.reject(new Error(`no body set`));\n }\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n async writeBody(body?: ReadableStream<BodyChunk> | Promise<BodyChunk> | BodyChunk) {\n if (body === undefined) {\n this.#body = new Blob([]);\n return;\n }\n if (body instanceof ReadableStream) {\n const chunks: BodyChunk[] = [];\n const reader = body.getReader();\n let done = false;\n while (!done) {\n const {value, done: readDone} = await reader.read();\n if (readDone) {\n done = true;\n } else {\n chunks.push(value);\n }\n }\n this.#body = new Blob(chunks);\n }\n else {\n body = await body;\n if (typeof body === 'string') {\n this.#body = new Blob([body], {type: 'text/plain'});\n } else {\n this.#body = new Blob([body]);\n }\n }\n if (!this.headers.has('content-type')) {\n this.setHeader('Content-Type', this.#body.type || 'application/octet-stream');\n }\n\n }\n\n get URL() {\n return new URL(this.path + this.#url.search + this.#url.hash, `${this.protocol}://${this.host}`);\n }\n\n addHeader(name: string, value: string | (readonly string[])): this {\n (this.headers as MutableHttpHeaders).add(name, value);\n return this;\n }\n\n setHeader(name: string, value: ReadonlyHeaderValue): this {\n (this.headers as MutableHttpHeaders).set(name, value);\n return this;\n }\n}\n\nexport class MockServerHttpResponse extends AbstractServerHttpResponse implements HttpResponse<MutableHttpHeaders> {\n #writeHandler: (body: ReadableStream<BodyChunk>) => Promise<boolean>;\n #body: () => ReadableStream<BodyChunk> = () => {\n throw new Error('No content was written to the response body nor end was called on this response.');\n };\n\n constructor() {\n super(new MapHttpHeaders());\n this.#writeHandler = async (body) => {\n const chunks: BodyChunk[] = [];\n let bodyStream: ReadableStream<BodyChunk> | undefined;\n this.#body = () => {\n bodyStream ??= stream.ReadableStream.from(chunks) as ReadableStream<BodyChunk>;\n return bodyStream;\n };\n\n const reader = body.getReader();\n let done = false;\n do {\n const {value, done: readDone} = await reader.read();\n if (readDone) {\n done = true;\n } else {\n chunks.push(value);\n }\n } while (!done);\n return true;\n }\n }\n\n get statusCode() {\n return super.statusCode!; // :(\n }\n\n set writeHandler(handler: (body: ReadableStream<BodyChunk>) => Promise<boolean>) {\n this.#body = () => {\n throw new Error('Not available with custom write handler');\n }\n this.#writeHandler = handler;\n }\n\n\n getNativeResponse<T>(): T {\n throw new Error('This is a mock. No running server, no native response.');\n }\n\n protected applyStatusCode(): void {}\n protected applyHeaders(): void {}\n protected applyCookies(): void {\n for (const cookie of this.cookies) {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n }\n }\n\n bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n const it = (async function* () {\n const resolved = await body;\n if (resolved === undefined) {\n return;\n }\n yield resolved;\n })();\n return this.#writeHandler(stream.ReadableStream.from(it) as ReadableStream<BodyChunk>);\n }\n\n async end(): Promise<boolean> {\n return this.doCommit(async () => {\n return await new Promise((resolve, reject) => {\n this.#writeHandler(stream.ReadableStream.from([]) as ReadableStream);\n });\n });\n }\n\n getBody() {\n return this.#body();\n }\n}\n\n\nexport class MockWebExchange extends DefaultWebExchange<MockServerHttpRequest, MockServerHttpResponse> {\n readonly #principal?: Principal;\n constructor(request: MockServerHttpRequest, response?: MockServerHttpResponse, principal?: Principal) {\n super(request, response ?? new MockServerHttpResponse());\n this.#principal = principal;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(this.#principal as P);\n }\n}\n", "import type { Principal } from '../../types/auth';\nimport type {\n BodyChunk,\n HeaderValue,\n HeaderValues,\n HttpCookie,\n HttpMethod,\n HttpStatusCode,\n MutableHttpHeaders,\n ReadonlyHeaderValues,\n ReadonlyHttpHeaders,\n ResponseCookie\n} from '../../types/web/http'\n\nimport type {\n ServerHttpRequest,\n ServerHttpResponse,\n ServerWebExchange\n} from '../../types/web/server';\nimport { AbstractHttpHeaders, AbstractHttpRequest, AbstractHttpResponse } from '../http/exchange.ts';\nimport { httpStatusCode } from '../http/status.ts';\nimport net from 'node:net';\nimport http from 'node:http';\nimport http2 from 'node:http2';\n\nexport class ExtendedHttpIncomingMessage extends http.IncomingMessage {\n // circular reference to the exchange\n exchange?: ServerWebExchange;\n\n upgradeHead?: Buffer<ArrayBufferLike>\n\n\n get urlBang(): string {\n return this.url!;\n }\n\n get socketEncrypted(): boolean {\n // see tls.TLSSocket#encrypted\n return this.socket['encrypted'] === true;\n }\n}\n\nexport class ExtendedHttpServerResponse<Request extends ExtendedHttpIncomingMessage = ExtendedHttpIncomingMessage> extends http.ServerResponse<Request> {\n\n markHeadersSent(): void {\n this['_header'] = true; // prevent response from being sent\n }\n\n getRawHeaderNames(): string[] {\n return super['getRawHeaderNames']();\n }\n}\n\nabstract class AbstractServerHttpRequest extends AbstractHttpRequest<ReadonlyHttpHeaders> {\n abstract getNativeRequest<T>(): T;\n}\n\nexport abstract class AbstractServerHttpResponse extends AbstractHttpResponse<MutableHttpHeaders> {\n #cookies: ResponseCookie[] = [];\n #statusCode?: HttpStatusCode;\n #state: 'new' | 'committing' | 'commit-action-failed' | 'committed' = 'new';\n #commitActions: (() => Promise<void>)[] = [];\n\n setStatusCode(statusCode?: HttpStatusCode): boolean {\n if (this.#state === 'committed') {\n return false;\n }\n else {\n this.#statusCode = statusCode;\n return true;\n }\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.setStatusCode(statusCode === undefined ? undefined : httpStatusCode(statusCode));\n };\n\n get statusCode(): HttpStatusCode | undefined {\n return this.#statusCode;\n }\n\n addCookie(cookie: ResponseCookie): this {\n if (this.#state === 'committed') {\n throw new Error(`Cannot add cookie ${JSON.stringify(cookie)} because HTTP response has already been committed`);\n }\n this.#cookies.push(cookie);\n return this;\n }\n\n abstract getNativeResponse<T>(): T;\n\n beforeCommit(action: () => Promise<void>): void {\n this.#commitActions.push(action);\n }\n\n get commited(): boolean {\n const state = this.#state;\n return state !== 'new' && state !== 'commit-action-failed';\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n if (body instanceof ReadableStream) {\n throw new Error('ReadableStream body not supported yet');\n }\n const buffer = await body;\n try {\n // touch buffers if needed\n\n return await this.doCommit(async () => {\n\n return await this.bodyInternal(Promise.resolve(buffer));\n\n }).catch(error => {\n // release buffers\n throw error;\n });\n }\n catch (error) {\n // clear content headers\n throw error;\n }\n }\n\n abstract bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean>;\n\n async end(): Promise<boolean> {\n if (!this.commited) {\n return this.doCommit(async () => {\n return await this.bodyInternal(Promise.resolve());\n });\n }\n else {\n return Promise.resolve(false);\n }\n }\n\n protected doCommit(writeAction?: () => Promise<boolean>): Promise<boolean> {\n const state = this.#state;\n let allActions = Promise.resolve();\n if (state === 'new') {\n this.#state = 'committing';\n if (this.#commitActions.length > 0) {\n allActions = this.#commitActions\n .reduce(\n (acc, cur) => acc.then(() => cur()),\n Promise.resolve())\n .catch((_error) => {\n const state = this.#state;\n if (state === 'committing') {\n this.#state = 'commit-action-failed';\n // clear content headers\n }\n });\n }\n }\n else if (state === 'commit-action-failed') {\n this.#state = 'committing';\n // skip commit actions\n } else {\n return Promise.resolve(false);\n }\n\n allActions = allActions.then(() => {\n this.applyStatusCode();\n this.applyHeaders();\n this.applyCookies();\n this.#state = 'committed';\n });\n\n\n return allActions.then(async () => {\n return writeAction !== undefined ? await writeAction() : true;\n });\n }\n\n protected applyStatusCode(): void {}\n protected applyHeaders(): void {}\n protected applyCookies(): void {}\n}\nexport class HttpServerRequest extends AbstractServerHttpRequest implements ServerHttpRequest {\n\n #url?: URL;\n #cookies?: HttpCookie[];\n readonly #req: ExtendedHttpIncomingMessage;\n\n constructor(req: ExtendedHttpIncomingMessage) {\n super(new IncomingMessageHeaders(req));\n this.#req = req;\n }\n\n getNativeRequest<T>(): T {\n return this.#req as T;\n }\n\n get upgrade() {\n return this.#req['upgrade'];\n }\n\n get http2(): boolean {\n return this.#req.httpVersionMajor >= 2;\n }\n\n get path() {\n return this.URL?.pathname;\n }\n\n get URL() {\n this.#url ??= new URL(this.#req.urlBang, `${this.protocol}://${this.host}`);\n return this.#url;\n }\n\n get query() {\n return this.URL?.search;\n }\n\n get method() {\n return this.#req.method as HttpMethod;\n }\n\n get host() {\n let dh: string | undefined = undefined;\n if (this.#req.httpVersionMajor >= 2) {\n dh = (this.#req.headers as http2.IncomingHttpHeaders)[':authority'];\n }\n dh ??= this.#req.socket.remoteAddress;\n return super.parseHost(dh);\n }\n\n get protocol() {\n let dp: string | undefined = undefined;\n if (this.#req.httpVersionMajor > 2) {\n dp = (this.#req.headers as http2.IncomingHttpHeaders)[':scheme'];\n }\n dp ??= this.#req.socketEncrypted ? 'https' : 'http';\n return super.parseProtocol(dp);\n }\n\n get socket() {\n return this.#req.socket;\n }\n\n get remoteAddress(): net.AddressInfo | undefined {\n const family = this.#req.socket.remoteFamily;\n const address = this.#req.socket.remoteAddress;\n const port = this.#req.socket.remotePort;\n const remoteAddress = (!family || !address || !port) ? undefined : { family, address, port };\n return super.parseRemoteAddress(remoteAddress) ?? remoteAddress;\n }\n\n get cookies(): HttpCookie[] {\n this.#cookies ??= super.cookies\n return this.#cookies;\n }\n\n get body(): ReadableStream<BodyChunk> {\n return http.IncomingMessage.toWeb(this.#req) as ReadableStream<BodyChunk>;\n }\n\n async blob() {\n const chunks: BodyChunk[] = [];\n if (this.body !== undefined) {\n for await (const chunk of this.body) {\n chunks.push(chunk);\n }\n }\n return new Blob(chunks, {type: this.headers.one('content-type') as string || 'application/octet-stream'});\n }\n\n\n async text() {\n const blob = await this.blob();\n return await blob.text();\n }\n\n async formData() {\n const blob = await this.blob();\n const text = await blob.text();\n return new URLSearchParams(text);\n }\n\n async json() {\n const blob = await this.blob();\n if (blob.size === 0) {\n return undefined;\n }\n const text = await blob.text();\n return JSON.parse(text);\n }\n\n\n protected initId(): string {\n const remoteIp = this.#req.socket.remoteAddress;\n if (!remoteIp) {\n throw new Error('Socket has no remote address');\n }\n return `${remoteIp}:${this.#req.socket.remotePort}`;\n }\n}\n\nclass IncomingMessageHeaders extends AbstractHttpHeaders<ReadonlyHeaderValues> implements ReadonlyHttpHeaders {\n readonly #msg: ExtendedHttpIncomingMessage;\n\n constructor(msg: ExtendedHttpIncomingMessage) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.headers[name] !== undefined;\n }\n\n get(name: string): string | (readonly string[]) | undefined {\n return this.#msg.headers[name];\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n\n one(name: string): string | undefined {\n const value = this.#msg.headers[name];\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n keys() {\n return Object.keys(this.#msg.headers).values();\n }\n}\n\nclass OutgoingMessageHeaders extends AbstractHttpHeaders<HeaderValues> implements MutableHttpHeaders {\n readonly #msg: ExtendedHttpServerResponse;\n\n constructor(msg: ExtendedHttpServerResponse) {\n super();\n this.#msg = msg;\n }\n\n has(name: string): boolean {\n return this.#msg.hasHeader(name);\n }\n\n keys() {\n return this.#msg.getHeaderNames().values();\n }\n\n get(name: string): HeaderValues {\n return this.#msg.getHeader(name);\n }\n\n one(name: string): HeaderValue {\n const value = this.#msg.getHeader(name);\n if (Array.isArray(value)) {\n return value[0];\n }\n return value;\n }\n\n set(name: string, value: HeaderValues): this {\n if (!this.#msg.headersSent) {\n if (Array.isArray(value)) {\n value = value.map(v => typeof v === 'number' ? String(v) : v);\n } else if (typeof value === 'number') {\n value = String(value);\n }\n\n if (value) {\n this.#msg.setHeader(name, value);\n }\n else {\n this.#msg.removeHeader(name);\n }\n }\n return this;\n }\n\n add(name: string, value: string | (readonly string[])): this {\n if (!this.#msg.headersSent) {\n this.#msg.appendHeader(name, value);\n }\n return this;\n }\n\n list(name: string): string[] {\n return super.toList(name);\n }\n}\n\nexport class HttpServerResponse extends AbstractServerHttpResponse implements ServerHttpResponse {\n readonly #res: ExtendedHttpServerResponse;\n\n constructor(res: ExtendedHttpServerResponse) {\n super(new OutgoingMessageHeaders(res));\n this.#res = res;\n }\n\n getNativeResponse<T>(): T {\n return this.#res as T;\n }\n\n get statusCode(): HttpStatusCode {\n const status = super.statusCode;\n return status ?? {value: this.#res.statusCode};\n }\n\n applyStatusCode() {\n const status = super.statusCode;\n if (status !== undefined) {\n this.#res.statusCode = status.value;\n }\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.headers.add('Set-Cookie', super.setCookieValue(cookie));\n return this;\n }\n\n async bodyInternal(body: Promise<BodyChunk | void>): Promise<boolean> {\n if (!this.#res.headersSent) {\n if (body instanceof ReadableStream) {\n // http.IncomingMessage.fromWeb(body)\n throw new Error('ReadableStream body not supported in response');\n }\n else {\n const chunk = await body;\n return await new Promise<boolean>((resolve, reject) => {\n try {\n if (chunk === undefined) {\n this.#res.end(() => {\n resolve(true);\n });\n } else {\n if (!this.headers.has('content-length')) {\n // set content-length if not already set\n if (typeof chunk === 'string') {\n this.headers.set('content-length', Buffer.byteLength(chunk));\n }\n else if (chunk instanceof Blob) {\n this.headers.set('content-length', chunk.size);\n }\n else {\n this.headers.set('content-length', chunk.byteLength);\n }\n }\n this.#res.end(chunk, () => {\n resolve(true);\n });\n }\n } catch (e) {\n reject(e instanceof Error ? e : new Error(`end failed: ${e}`));\n }\n });\n }\n }\n else {\n return false; // already ended\n }\n }\n}\n\nexport class ServerHttpRequestDecorator implements ServerHttpRequest {\n readonly #delegate: ServerHttpRequest;\n\n constructor(request: ServerHttpRequest) {\n this.#delegate = request;\n }\n\n get delegate(): ServerHttpRequest {\n return this.#delegate;\n }\n\n get id(): string {\n return this.#delegate.id;\n }\n\n get method(): HttpMethod {\n return this.#delegate.method;\n }\n\n get path(): string {\n return this.#delegate.path;\n }\n\n get protocol() {\n return this.#delegate.protocol;\n }\n\n get host(): string | undefined {\n return this.#delegate.host;\n }\n\n get URL(): URL {\n return this.#delegate.URL;\n }\n\n get headers(): ReadonlyHttpHeaders {\n return this.#delegate.headers;\n }\n\n get cookies(): HttpCookie[] {\n return this.#delegate.cookies;\n }\n\n get remoteAddress() {\n return this.#delegate.remoteAddress;\n }\n\n get upgrade() {\n return this.#delegate.upgrade;\n }\n\n get body(): ReadableStream<BodyChunk> | undefined {\n return this.#delegate.body;\n }\n async blob(): Promise<Blob> {\n return await this.#delegate.blob();\n }\n async text(): Promise<string> {\n return await this.#delegate.text();\n }\n async formData(): Promise<URLSearchParams> {\n return await this.#delegate.formData();\n }\n async json(): Promise<unknown> {\n return await this.#delegate.json();\n }\n\n toString(): string {\n return `${ServerHttpRequestDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeRequest<T>(request: ServerHttpRequest): T {\n if (request instanceof AbstractServerHttpRequest) {\n return request.getNativeRequest<T>();\n }\n else if (request instanceof ServerHttpRequestDecorator) {\n return ServerHttpRequestDecorator.getNativeRequest<T>(request.delegate);\n }\n else {\n throw new Error(`Cannot get native request from ${request.constructor.name}`);\n }\n }\n}\nexport class ServerHttpResponseDecorator implements ServerHttpResponse {\n readonly #delegate: ServerHttpResponse;\n\n constructor(response: ServerHttpResponse) {\n this.#delegate = response;\n }\n\n get delegate(): ServerHttpResponse {\n return this.#delegate;\n }\n\n setStatusCode(statusCode: HttpStatusCode): boolean {\n return this.delegate.setStatusCode(statusCode);\n }\n\n setRawStatusCode(statusCode?: number): boolean {\n return this.delegate.setRawStatusCode(statusCode);\n }\n\n get statusCode(): HttpStatusCode {\n return this.delegate.statusCode;\n }\n\n get cookies(): ResponseCookie[] {\n return this.delegate.cookies;\n }\n\n addCookie(cookie: ResponseCookie): this {\n this.delegate.addCookie(cookie);\n return this;\n }\n\n async end(): Promise<boolean> {\n return await this.delegate.end();\n }\n\n async body(body: ReadableStream<BodyChunk> | Promise<BodyChunk | void> | BodyChunk): Promise<boolean> {\n return await this.#delegate.body(body);\n }\n\n get headers(): MutableHttpHeaders {\n return this.#delegate.headers;\n }\n\n toString(): string {\n return `${ServerHttpResponseDecorator.name} [delegate: ${this.delegate.toString()}]`;\n }\n\n public static getNativeResponse<T>(response: ServerHttpResponse): T {\n if (response instanceof AbstractServerHttpResponse) {\n return response.getNativeResponse<T>();\n }\n else if (response instanceof ServerHttpResponseDecorator) {\n return ServerHttpResponseDecorator.getNativeResponse<T>(response.delegate);\n }\n else {\n throw new Error(`Cannot get native response from ${response.constructor.name}`);\n }\n }\n}\n\nexport class ServerWebExchangeDecorator implements ServerWebExchange {\n readonly #delegate: ServerWebExchange;\n\n protected constructor(exchange: ServerWebExchange) {\n this.#delegate = exchange;\n }\n\n get delegate(): ServerWebExchange {\n return this.#delegate;\n }\n\n get request(): ServerHttpRequest {\n return this.#delegate.request;\n }\n\n get response(): ServerHttpResponse {\n return this.#delegate.response;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.#delegate.attribute(name);\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return this.#delegate.principal();\n }\n\n get logPrefix(): string {\n return this.#delegate.logPrefix;\n }\n\n toString() {\n return `${ServerWebExchangeDecorator.name} [delegate: ${this.delegate}]`;\n }\n}\n\nexport class DefaultWebExchange<Request extends ServerHttpRequest, Response extends ServerHttpResponse> {\n readonly request: Request;\n readonly response: Response;\n readonly #attributes: Record<string, unknown> = {};\n #logId?: unknown;\n #logPrefix: string = '';\n\n constructor(request: Request, response: Response) {\n this.#attributes[LOG_ID_ATTRIBUTE] = request.id;\n this.request = request;\n this.response = response;\n }\n\n get method(): HttpMethod {\n return this.request.method;\n }\n\n get path(): string | null | undefined {\n return this.request.path;\n }\n\n get attributes(): Record<string, unknown> {\n return this.#attributes;\n }\n\n attribute<T>(name: string): T | undefined {\n return this.attributes[name] as T;\n }\n\n principal<P extends Principal>(): Promise<P | undefined> {\n return Promise.resolve(undefined);\n }\n\n get logPrefix(): string {\n const value = this.attribute(LOG_ID_ATTRIBUTE);\n if (this.#logId !== value) {\n this.#logId = value;\n this.#logPrefix = value !== undefined ? `[${value}] ` : '';\n }\n return this.#logPrefix;\n }\n}\n\nexport const LOG_ID_ATTRIBUTE = 'io.interop.gateway.server.log_id';\n\n", "import * as GatewayLogging from '@interopio/gateway/logging/core';\n\nexport import Logger = GatewayLogging.Logger;\n\nexport default function getLogger(name: string): Logger {\n return GatewayLogging.getLogger(`gateway.server.${name}`);\n}\n\n// This function is used to ensure that RegExp objects are displayed correctly when logging.\nexport function regexAwareReplacer<T>(_key: string, value: T): string | T {\n return value instanceof RegExp ? value.toString() : value;\n}\n", "import type { HttpHandler, WebHandler } from './types';\nimport { DefaultWebExchange, ServerHttpResponseDecorator } from './exchange.ts';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Logger } from '@interopio/gateway/logging/api';\nimport type { HttpHeaders } from '../../types/web/http';\nimport type {\n ServerHttpRequest,\n ServerHttpResponse,\n ServerWebExchange\n} from '../../types/web/server';\nimport getLogger from '../logger.ts';\nimport { HttpStatus } from '../http/status.ts';\n\nexport class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {\n\n}\n\nclass HandlerAdapter {\n\n readonly #logger: Logger\n #enableLoggingRequestDetails: boolean = false;\n readonly #delegate: WebHandler;\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }>;\n\n constructor(logger: Logger, delegate: WebHandler) {\n this.#logger = logger;\n this.#delegate = delegate;\n }\n\n protected createExchange(request: ServerHttpRequest, response: ServerHttpResponse): ServerWebExchange {\n\n const exchange = new DefaultWebExchange(request, response);\n return exchange;\n }\n\n set storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>) {\n this.#storage = storage;\n }\n\n set enableLoggingRequestDetails(value: boolean) {\n this.#enableLoggingRequestDetails = value;\n }\n\n formatHeaders(headers: HttpHeaders): string {\n let result = '{';\n\n for (const key of headers.keys()) {\n if (!this.#enableLoggingRequestDetails) {\n result += 'masked, ';\n break;\n } else {\n const value = headers.get(key);\n result += `\"${key}\": \"${value}\", `;\n }\n }\n if (result.endsWith(', ')) {\n result = result.slice(0, -2);\n }\n result += '}';\n return result;\n\n }\n\n formatRequest(request: ServerHttpRequest): string {\n const query = request.URL.search;\n return `HTTP ${request.method} \"${request.path}${query}`;\n }\n\n logRequest(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n this.#logger.debug(`${exchange.logPrefix}${this.formatRequest(exchange.request)}${trace ? `, headers: ${this.formatHeaders(exchange.request.headers)}` : ''}\"`);\n\n }\n }\n\n logResponse(exchange: ServerWebExchange) {\n if (this.#logger.enabledFor('debug')) {\n const trace = this.#logger.enabledFor('trace');\n const status = exchange.response.statusCode;\n this.#logger.debug(`${exchange.logPrefix}Completed ${status ?? '200 OK'}${trace ? `, headers: ${this.formatHeaders(exchange.response.headers)}` : ''}\"`);\n }\n }\n\n handleUnresolvedError(exchange: ServerWebExchange, error: Error) {\n const {request, response, logPrefix} = exchange;\n\n if (response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR)) {\n this.#logger.error(`${logPrefix}500 Server Error for ${this.formatRequest(request)}`, error);\n return;\n }\n // todo if client disconnected, we should not log an error\n\n this.#logger.error(`${logPrefix}Error [${error.message} for ${this.formatRequest(request)}, but already ended (${response.statusCode})`, error);\n throw error;\n\n }\n\n async web(exchange: ServerWebExchange): Promise<void> {\n return await this.#delegate(exchange);\n }\n\n async http(request: ServerHttpRequest, response: ServerHttpResponse): Promise<void> {\n\n const exchange = this.createExchange(request, response);\n const callback = () => {\n this.logRequest(exchange);\n return this.web(exchange)\n .then(() => {\n this.logResponse(exchange);\n })\n .catch((error: Error) => {\n this.handleUnresolvedError(exchange, error)\n })\n .then(async () => {\n await exchange.response.end();\n });\n };\n\n await new Promise<void>((resolve, reject) => {\n if (this.#storage !== undefined) {\n this.#storage.run({exchange}, () => {\n callback().then(() => resolve()).catch((error) => reject(error));\n });\n } else {\n callback().then(() => resolve()).catch((error) => reject(error));\n }\n });\n }\n}\n\nexport class WebHttpHandlerBuilder {\n readonly #webHandler: WebHandler;\n #storage?: AsyncLocalStorage<{ exchange: ServerWebExchange }> = new AsyncLocalStorage();\n #handlerDecorator?: (handler: HttpHandler) => HttpHandler;\n\n storage(storage: AsyncLocalStorage<{ exchange: ServerWebExchange }>): this {\n this.#storage = storage;\n return this;\n }\n\n httpHandlerDecorator(decorator: (handler: HttpHandler) => HttpHandler): this {\n if (this.#handlerDecorator === undefined) {\n this.#handlerDecorator = decorator;\n } else {\n const previousDecorator = this.#handlerDecorator;\n this.#handlerDecorator = (handler: HttpHandler) => {\n handler = previousDecorator(handler);\n return decorator(handler);\n }\n }\n return this;\n }\n\n constructor(webHandler: WebHandler) {\n this.#webHandler = webHandler;\n }\n\n build(): HttpHandler {\n const logger = getLogger('http');\n\n const adapter = new HandlerAdapter(logger, this.#webHandler);\n if (this.#storage !== undefined) adapter.storage = this.#storage;\n adapter.enableLoggingRequestDetails = false;\n const adapted: HttpHandler = async (request, response) => adapter.http(request, response);\n\n\n return this.#handlerDecorator ? this.#handlerDecorator(adapted) : adapted;\n }\n}\n", "import type {ClientHttpConnector} from '../../client/types.js';\nimport {HttpHandler} from '../../server/types.js';\nimport {MockClientHttpRequest, MockClientHttpResponse} from '../../mock/client/exchange.js';\nimport {MockServerHttpRequest, MockServerHttpResponse} from '../../mock/server/exchange.js';\nimport {BodyChunk, HttpMethod} from '../../../types/web/http';\nimport type {ClientHttpRequest, ClientHttpResponse} from '../../../types/web/client';\n\nimport getLogger from '../../logger.js';\nimport {ServerHttpRequest, ServerHttpResponse} from '../../../types/web/server';\nimport {HttpHeadResponseDecorator} from '../../server/handler.ts';\nimport stream from \"node:stream/web\";\n\n\nclass FailureAfterResponseCompletedError extends Error {\n readonly completedResponse: ClientHttpResponse;\n\n constructor(response: ClientHttpResponse, options: { cause?: Error } = {}) {\n super(`error occurred after response was completed: ${response}`, options);\n this.completedResponse = response;\n }\n}\n\ntype Sink<T> = {\n resolve: (value: T | PromiseLike<T>) => void,\n reject: (reason?: unknown) => void,\n promise: Promise<T>\n}\n\nasync function sink<T>(): Promise<Sink<T>> {\n try {\n return await new Promise<Sink<T>>((result, _error) => {\n\n const promise = new Promise<T>((resolve, reject) => {\n Promise.resolve().then(() => {\n result({promise, resolve, reject});\n });\n });\n });\n }\n catch (error) {\n throw error;\n }\n}\n\nexport class HttpHandlerConnector implements ClientHttpConnector {\n static readonly #logger = getLogger('test.http.handler.connector');\n readonly #httpHandler: HttpHandler;\n\n constructor(httpHandler: HttpHandler) {\n this.#httpHandler = httpHandler;\n }\n\n async connect(method: HttpMethod, uri: URL,\n requestCallback: (request: ClientHttpRequest) => Promise<void>): Promise<ClientHttpResponse> {\n\n const requestWriteSink = await sink<void>();\n const handlerSink = await sink<void>();\n const savedResponse: [ClientHttpResponse | undefined] = [undefined];\n\n const mockClientRequest = new MockClientHttpRequest(uri, method);\n const mockServerResponse = new MockServerHttpResponse();\n\n mockClientRequest.writeHandler = async (responseBody) => {\n this.log('Invoking HttpHandler for ', method, uri);\n const mockServerRequest = await this.adoptRequest(mockClientRequest, responseBody);\n const responseToUse = this.prepareResponse(mockServerResponse, mockServerRequest);\n\n try {\n await this.#httpHandler(mockServerRequest, responseToUse);\n handlerSink.resolve();\n } catch (e) {\n handlerSink.reject(e);\n }\n return true;\n\n }\n\n mockServerResponse.writeHandler = async (responseBody) => {\n this.log('Creating client response for ', method, uri);\n savedResponse[0] = this.adoptResponse(mockServerResponse, responseBody);\n return true;\n }\n this.log('Writing client request for ', method, uri);\n\n requestCallback(mockClientRequest)\n .then(() => {\n requestWriteSink.resolve();\n })\n .catch(error => {\n requestWriteSink.reject(error);\n });\n\n return Promise.all([requestWriteSink.promise, handlerSink.promise])\n .catch((error) => {\n const response = savedResponse[0];\n throw response !== undefined ? new FailureAfterResponseCompletedError(response, {cause: error}) : error;\n }).then(() => {\n const response = savedResponse[0];\n return response ?? this.adoptResponse(mockServerResponse, stream.ReadableStream.from([]) as ReadableStream<BodyChunk>);\n });\n\n }\n\n private log(message: string, method: HttpMethod, uri: URL): void {\n if (HttpHandlerConnector.#logger.enabledFor('debug')) {\n HttpHandlerConnector.#logger.debug(`${message} ${method} \"${uri.href}\"`);\n }\n }\n\n private async adoptRequest(request: MockClientHttpRequest, body: ReadableStream<BodyChunk>): Promise<ServerHttpRequest> {\n const method = request.method;\n const uri = request.URL;\n const headers = request.headers;\n const cookies = request.cookies;\n const result = new MockServerHttpRequest(uri, method)\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n await result.writeBody(body)\n return result;\n }\n\n private prepareResponse(response: ServerHttpResponse, request: ServerHttpRequest): ServerHttpResponse {\n return request.method === 'HEAD' ? new HttpHeadResponseDecorator(response) : response;\n\n }\n\n private adoptResponse(response: MockServerHttpResponse, body: ReadableStream<BodyChunk>): ClientHttpResponse {\n const status = response.statusCode;\n const headers = response.headers;\n const cookies = response.cookies;\n const result = new MockClientHttpResponse(status);\n for (const name of headers.keys()) {\n let value = headers.get(name);\n if (value !== undefined) {\n if (typeof value === 'number') {\n value = String(value);\n }\n if (typeof value === 'string') {\n result.setHeader(name, value);\n } else {\n for (const v of value) {\n result.addHeader(name, v);\n }\n }\n }\n }\n result.body = body;\n return result;\n }\n}\n\n", "import {IOGateway} from '@interopio/gateway';\nimport {OriginFilters} from '../../types/web/server';\nimport getLogger from '../logger.js';\n\nconst log = getLogger('gateway.ws.client-verify');\n\nexport type ProcessedOriginFilters\n = Required<Omit<OriginFilters, 'blacklist' | 'whitelist'>>\n //| Required<Omit<GatewayServer.OriginFilters, 'block' | 'allow'>>\n ;\n\nfunction acceptsMissing(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.missing) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nfunction tryMatch(originFilters: ProcessedOriginFilters, origin: string): boolean | undefined {\n const block = originFilters.block ?? originFilters['blacklist'];\n const allow = originFilters.allow ?? originFilters['whitelist'];\n if (block.length > 0 && IOGateway.Filtering.valuesMatch(block, origin)) {\n log.warn(`origin ${origin} matches block filter`);\n return false;\n } else if (allow.length > 0 && IOGateway.Filtering.valuesMatch(allow, origin)) {\n if (log.enabledFor('debug')) {\n log.debug(`origin ${origin} matches allow filter`);\n }\n return true;\n }\n}\n\nfunction acceptsNonMatched(originFilters: ProcessedOriginFilters): boolean {\n switch (originFilters.non_matched) {\n case 'allow': // fall-through\n case 'whitelist':\n return true;\n case 'block': // fall-through\n case 'blacklist':\n return false;\n default:\n return false;\n }\n}\n\nexport function acceptsOrigin(origin?: string, originFilters?: ProcessedOriginFilters): boolean {\n if (!originFilters) {\n return true;\n }\n if (!origin) {\n return acceptsMissing(originFilters);\n } else {\n const matchResult: boolean | undefined = tryMatch(originFilters, origin);\n if (matchResult) {\n return matchResult;\n } else {\n return acceptsNonMatched(originFilters);\n }\n }\n}\n\nexport function regexifyOriginFilters(originFilters?: OriginFilters): ProcessedOriginFilters | undefined {\n if (originFilters) {\n const block = (originFilters.block ?? originFilters.blacklist ?? []).map(IOGateway.Filtering.regexify);\n const allow = (originFilters.allow ?? originFilters.whitelist ?? []).map(IOGateway.Filtering.regexify);\n return {\n non_matched: originFilters.non_matched ?? 'allow',\n missing: originFilters.missing ?? 'allow',\n allow,\n block,\n }\n }\n}\n", "import type {ServerWebExchange} from '../../../types/web/server';\n\nexport type MatchResult = Readonly<{ match: boolean, variables: Readonly<Record<string, string>> }>;\n\nexport interface ServerWebExchangeMatcher {\n /**\n * Matches the given exchange against the matcher.\n * @param exchange The web exchange to match.\n * @returns A promise that resolves to true if the exchange matches, false otherwise.\n */\n (exchange: ServerWebExchange): Promise<MatchResult>;\n\n /**\n * Returns a string representation of the matcher.\n * @returns A string representation of the matcher.\n */\n toString(): string;\n}\n\nexport type ServerWebExchangeMatcherEntry<T> = Readonly<[ServerWebExchangeMatcher, T]>\n\nexport const or: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (result.match) {\n return match();\n }\n }\n return NO_MATCH;\n };\n}\n\nexport const and: (matchers: ServerWebExchangeMatcher[]) => ServerWebExchangeMatcher = (matchers: ServerWebExchangeMatcher[]) => {\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n for (const matcher of matchers) {\n const result = await matcher(exchange);\n if (!result.match) {\n return NO_MATCH;\n }\n }\n return match();\n };\n matcher.toString = () => `and(${matchers.map(m => m.toString()).join(', ')})`;\n return matcher;\n}\n\n\nexport const not: (matcher: ServerWebExchangeMatcher) => ServerWebExchangeMatcher = (matcher: ServerWebExchangeMatcher): ServerWebExchangeMatcher => {\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const result = await matcher(exchange);\n return result.match ? NO_MATCH : match();\n };\n}\n\nexport const anyExchange: ServerWebExchangeMatcher = async (_exchange: ServerWebExchange): Promise<MatchResult> => {\n return match();\n}\nanyExchange.toString = () => 'any-exchange';\n\nconst EMPTY_OBJECT = Object.freeze({});\nexport const NO_MATCH: MatchResult = Object.freeze({match: false, variables: EMPTY_OBJECT});\nexport const match = (variables: Record<string, string> = EMPTY_OBJECT): MatchResult => {\n return {match: true, variables};\n}\n\nexport const pattern: ((pattern: string | RegExp, opts?: {method?: string}) => ServerWebExchangeMatcher) = (pattern, opts) => {\n const method = opts?.method;\n const matcher = async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n const path = request.path;\n if (method !== undefined && request.method !== method) {\n return NO_MATCH;\n }\n if (typeof pattern === 'string') {\n if (path === pattern) {\n return match();\n }\n return NO_MATCH;\n }\n else {\n const match = pattern.exec(path);\n if (match === null) {\n return NO_MATCH;\n }\n return {match: true, variables: {...match.groups}};\n }\n };\n matcher.toString = () => {\n return `pattern(${pattern.toString()}, method=${method ?? '<any>'})`;\n }\n return matcher\n\n}\nexport const mediaType : ((opts: {mediaTypes: string[], ignoredMediaTypes?: string[], useEquality?: boolean}) => ServerWebExchangeMatcher) = (opts): ServerWebExchangeMatcher => {\n\n const shouldIgnore = (requestedMediaType: string): boolean => {\n if (opts.ignoredMediaTypes !== undefined) {\n for (const ignoredMediaType of opts.ignoredMediaTypes) {\n if (requestedMediaType === ignoredMediaType || ignoredMediaType === '*/*') {\n return true;\n }\n }\n }\n return false;\n }\n\n return async (exchange: ServerWebExchange): Promise<MatchResult> => {\n const request = exchange.request;\n let requestMediaTypes: string[];\n try {\n requestMediaTypes = request.headers.list('accept');\n }\n catch (e) {\n return NO_MATCH;\n }\n for (const requestedMediaType of requestMediaTypes) {\n if (shouldIgnore(requestedMediaType)) {\n continue;\n }\n for (const mediaType of opts.mediaTypes) {\n if (requestedMediaType.startsWith(mediaType)) {\n return match();\n }\n }\n }\n\n return NO_MATCH;\n };\n}\n\nexport const upgradeMatcher: ServerWebExchangeMatcher = async ({request}: ServerWebExchange): Promise<MatchResult> => {\n const upgrade = request.upgrade && request.headers.one('upgrade')?.toLowerCase() === 'websocket';\n return upgrade ? match() : NO_MATCH;\n};\nupgradeMatcher.toString = () => 'websocket upgrade';\n", "import {regexifyOriginFilters} from '../server/ws-client-verify.js';\nimport type {SecurityContext} from '../server/security/security-context.js';\nimport {pattern, ServerWebExchangeMatcher} from '../server/util/matchers.js';\nimport type {CorsConfig} from '../server/cors.js';\nimport type {Middleware} from '../server/types.ts';\nimport type {AsyncLocalStorage} from 'node:async_hooks';\nimport type {SocketRoute} from '../server/socket.js';\nimport {GatewayServer} from '../../gateway-server';\nimport type {\n ServerConfigurer,\n ServerConfigurerHandlerSpec,\n ServerConfigurerSocketSpec,\n ServerExchangeOptions,\n ServerWebExchange\n} from '../../types/web/server';\nimport type {AuthorizationRule} from '../../types/auth';\nimport {IOGateway} from '@interopio/gateway';\nexport type PathPattern = string | RegExp;\nexport type RouteConfig = Readonly<{\n readonly storage: AsyncLocalStorage<{\n exchange: ServerWebExchange,\n securityContext?: Promise<SecurityContext>\n }>,\n readonly serverHeader?: string | false\n readonly corsConfig?: GatewayServer.ServerConfig['cors'],\n readonly authConfig?: GatewayServer.ServerConfig['auth'],\n readonly middleware: Middleware,\n readonly cors: Array<[PathPattern, CorsConfig | undefined]>,\n readonly authorize: Array<[ServerWebExchangeMatcher, AuthorizationRule]>\n readonly sockets: Map<string, SocketRoute>\n}>\n\nexport async function configure(app: GatewayServer.ServerCustomizer, config: GatewayServer.ServerConfig, routes: RouteConfig): Promise<void> {\n const applyCors = (request: ServerConfigurerHandlerSpec['request'], options?: ServerExchangeOptions) => {\n // // disable CORS for this route\n // if (options?.cors === false) {\n // const path = request.path as (PathPattern);\n // routes.cors.push([request.path, undefined]);\n // }\n if (options?.cors) {\n const cors: CorsConfig = options.cors === true ? {\n allowOrigins: options.origins?.allow?.map(IOGateway.Filtering.regexify),\n allowMethods: request.method === undefined ? ['*'] : [request.method],\n allowCredentials: options.authorize?.access !== 'permitted' ? true : undefined,\n } : options.cors;\n const path = request.path as (PathPattern);\n routes.cors.push([path, cors]);\n }\n }\n\n const configurer = new class implements ServerConfigurer {\n\n handle(...handlers: Array<ServerConfigurerHandlerSpec>) {\n handlers.forEach(({request, options, handler}) => {\n const matcher = pattern(IOGateway.Filtering.regexify(request.path) as string | RegExp, {method: request.method});\n if (options?.authorize) {\n routes.authorize.push([matcher, options.authorize]);\n }\n\n applyCors(request, options);\n const middleware = async (exchange: ServerWebExchange, next: () => Promise<void>): Promise<void> => {\n const {match, variables} = await matcher(exchange);\n if (match) {\n await handler(exchange, variables);\n } else {\n await next();\n }\n };\n routes.middleware.push(middleware);\n });\n }\n\n socket(...sockets: Array<ServerConfigurerSocketSpec>) {\n for (const {path, factory, options} of sockets) {\n const route = path ?? '/';\n\n // cors and authorize are currently handled for ws\n routes.sockets.set(route, {\n default: path === undefined,\n ping: options?.ping,\n factory: factory,\n maxConnections: options?.maxConnections,\n authorize: options?.authorize,\n originFilters: regexifyOriginFilters(options?.origins)\n });\n }\n }\n };\n await app(configurer, config);\n}\n", "type MiddlewareFunction<T> = ((ctx: T, next: (ctx?: T) => Promise<void>) => Promise<void>) | ((ctx: T) => Promise<void>);\n\n// https://github.com/koajs/compose/blob/master/index.js\n/**\n * @typeParam T - Type of context passed through the middleware\n * @param middleware middleware stack\n * @return {MiddlewareFunction}\n */\nexport function compose<T>(...middleware: MiddlewareFunction<T>[]): (ctx: T) => Promise<void> {\n if (!Array.isArray(middleware)) {\n throw new Error('middleware must be array!');\n }\n const fns = middleware.flat();\n for (const fn of fns) {\n if (typeof fn !== 'function') {\n throw new Error('middleware must be compose of functions!');\n }\n }\n return async function (ctx: T, next?: (ctx?: T) => Promise<void>) {\n const dispatch = async (i: number, dispatchedCtx: T): Promise<void> => {\n const fn = i === fns.length ? next : fns[i];\n if (fn === undefined) {\n return;\n }\n let nextCalled = false;\n let nextResolved = false;\n const nextFn = async (nextCtx?: T) => {\n if (nextCalled) {\n throw new Error('next() called multiple times');\n }\n nextCalled = true;\n try {\n return await dispatch(i + 1, nextCtx ?? dispatchedCtx);\n }\n finally {\n nextResolved = true;\n }\n };\n const result = await fn(dispatchedCtx, nextFn);\n if (nextCalled && !nextResolved) {\n throw new Error('middleware resolved before downstream.\\n\\t You are probably missing an await or return statement in your middleware function.');\n }\n return result;\n }\n\n return dispatch(0, ctx);\n }\n}\n", "import type {ClientHttpConnector} from '../../client/types.js';\nimport {FetchClientHttpConnector} from '../../client/fetch.js';\nimport type {\n HttpMethod\n} from '../../../types/web/http';\nimport type {\n TestClient,\n TestClientBuilder,\n MockServerSpec\n} from '../../../types/web/test';\nimport {GatewayServer} from '../../../gateway-server';\nimport {HttpHandlerConnector} from './handler.js';\nimport {WebHttpHandlerBuilder} from '../../server/handler.js';\nimport {configure, RouteConfig} from '../../app/route.js';\nimport {compose} from '../../common/compose.js';\nimport {AsyncLocalStorage} from 'node:async_hooks';\nimport {ServerWebExchange} from '../../../types/web/server';\nimport {SocketRoute} from '../../server/socket.js';\n\nexport function bindToApp(app: GatewayServer.ServerCustomizer): MockServerSpec {\n return new AppSpec(app);\n}\n\nexport function bindToServer(): TestClientBuilder {\n return new DefaultTestClientBuilder();\n}\n\nclass DefaultTestClient implements TestClient {\n readonly #connector: ClientHttpConnector;\n readonly #baseUrl?: string;\n readonly #builder: TestClientBuilder;\n constructor(connector: ClientHttpConnector,\n baseUrl: string | undefined,\n builder: TestClientBuilder) {\n this.#connector = connector;\n this.#baseUrl = baseUrl;\n this.#builder = builder;\n }\n\n fetch = async (input: string | URL, init?: RequestInit): Promise<Response> => {\n try {\n const method = init?.method as HttpMethod ?? 'GET';\n const uri = new URL(input, this.#baseUrl);\n const response = await this.#connector.connect(method, uri, async (request) => {\n // fetch Request to ClientHttpRequest\n const headers = new Headers(init?.headers);\n for (const [name, value] of headers.entries()) {\n request.headers.add(name, value);\n }\n let body = init?.body ?? Promise.resolve();\n if (body instanceof ReadableStream) {\n throw new Error(`Unsupported body type ${typeof init?.body} in fetch request`);\n }\n if (body instanceof FormData) {\n // Convert FormData to URLSearchParams\n const formDataEntries = Array.from(body.entries());\n body = new URLSearchParams();\n for (const [key, value] of formDataEntries) {\n body.append(key, value.toString());\n }\n }\n if (body instanceof URLSearchParams) {\n if (!request.headers.has('content-type')) {\n request.headers.set('content-type', 'application/x-www-form-urlencoded');\n }\n body = body.toString();\n }\n if (body instanceof Blob) {\n body = await body.bytes();\n }\n if (typeof body === 'string') {\n body = Buffer.from(body);\n }\n await request.body(body);\n\n\n });\n // ClientHttpResponse to fetch Response\n const headers = new Headers();\n for (const key of response.headers.keys()) {\n const values = response.headers.list(key);\n for (const value of values) {\n headers.append(key, value);\n }\n }\n const status = response.statusCode?.value;\n const body = await response.blob();\n return new Response(body, {status, headers});\n }\n catch (error) {\n return Response.error();\n }\n\n }\n}\n\nclass DefaultTestClientBuilder implements TestClientBuilder {\n readonly #httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>;\n #connector?: ClientHttpConnector;\n #baseUrl: string = 'http://localhost:8080';\n constructor(httpHandlerBuilder?: Promise<WebHttpHandlerBuilder>, connector?: ClientHttpConnector) {\n if (!(httpHandlerBuilder === undefined || connector === undefined)) {\n throw new Error('You can only set either httpHandlerBuilder or connector, not both.');\n }\n this.#connector = connector;\n this.#httpHandlerBuilder = httpHandlerBuilder;\n }\n\n baseUrl(baseUrl: string): this {\n this.#baseUrl = baseUrl;\n return this;\n }\n\n clientConnector(connector: ClientHttpConnector): this {\n this.#connector = connector;\n return this;\n }\n\n async build(): Promise<TestClient> {\n let connector = this.#connector;\n if (connector === undefined) {\n if (this.#httpHandlerBuilder !== undefined) {\n connector = new HttpHandlerConnector((await this.#httpHandlerBuilder).build());\n }\n }\n connector ??= new FetchClientHttpConnector();\n\n return new DefaultTestClient(connector, this.#baseUrl, this);\n }\n}\n\nabstract class AbstractMockServerSpec implements MockServerSpec {\n configureClient(): TestClientBuilder {\n const builder = this.initHttpHandlerBuilder();\n return new DefaultTestClientBuilder(builder);\n }\n\n protected abstract initHttpHandlerBuilder(): Promise<WebHttpHandlerBuilder>;\n\n async build(): Promise<TestClient> {\n return await this.configureClient().build();\n }\n}\n\nclass AppSpec extends AbstractMockServerSpec {\n readonly #app: GatewayServer.ServerCustomizer;\n constructor(app: GatewayServer.ServerCustomizer) {\n super();\n this.#app = app;\n }\n\n protected async initHttpHandlerBuilder() {\n const routes: RouteConfig = {\n middleware: [],\n corsConfig: {\n allowOrigin: ['http://localhost:8086']\n },\n cors: [],\n authConfig: {type: \"none\"},\n authorize: [],\n storage: new AsyncLocalStorage<{ exchange: ServerWebExchange }>(),\n sockets: new Map<string, SocketRoute>()\n };\n\n await configure(this.#app, {}, routes);\n const handler = compose(...routes.middleware)\n return new WebHttpHandlerBuilder(handler);\n }\n}\n", "import { bindToApp, bindToServer } from './server/client.ts';\n\nexport const TestClient = {\n bindToApp: bindToApp,\n bindToServer: bindToServer\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["isIP", "Cookie", "parseHost", "headers", "defaultHost", "host", "port", "isForwardedSsl", "v", "parseProtocol", "defaultProtocol", "proto", "parseRemoteAddress", "url", "remoteAddress", "AbstractHttpMessage", "#headers", "AbstractHttpRequest", "_AbstractHttpRequest", "#id", "parseCookies", "AbstractHttpResponse", "parseResponseCookies", "responseCookie", "parseHeader", "value", "list", "start", "end", "i", "toList", "values", "s", "cs", "tc", "cookie", "parsed", "result", "MapHttpHeaders", "name", "values", "toList", "value", "prev", "AbstractClientHttpRequest", "AbstractHttpRequest", "method", "uri", "MapHttpHeaders", "AbstractClientHttpResponse", "AbstractHttpResponse", "statusCode", "headers", "DefaultHttpStatusCode", "#value", "value", "HttpStatus", "_HttpStatus", "#VALUES", "key", "code", "status", "#phrase", "phrase", "httpStatusCode", "FetchClientHttpRequest", "AbstractClientHttpRequest", "#body", "method", "uri", "body", "headers", "key", "value", "toHttpHeaders", "result", "MapHttpHeaders", "FetchClientHttpResponse", "AbstractClientHttpResponse", "#response", "response", "httpStatusCode", "FetchClientHttpConnector", "#fetch", "fetchFn", "requestCallback", "fetchClientHttpRequest", "fetchRequest", "fetchResponse", "stream", "MockClientHttpRequest", "AbstractClientHttpRequest", "#writeHandler", "#body", "uri", "method", "body", "chunks", "reader", "done", "value", "doneReading", "handler", "asyncIterator", "MockClientHttpResponse", "AbstractHttpResponse", "#statusCode", "status", "MapHttpHeaders", "httpStatusCode", "name", "charset", "chunk", "stream", "http", "ExtendedHttpIncomingMessage", "ExtendedHttpServerResponse", "AbstractServerHttpResponse", "AbstractHttpResponse", "#cookies", "#statusCode", "#state", "#commitActions", "statusCode", "httpStatusCode", "cookie", "action", "state", "body", "buffer", "error", "writeAction", "allActions", "acc", "cur", "_error", "ServerHttpResponseDecorator", "_ServerHttpResponseDecorator", "#delegate", "response", "statusCode", "cookie", "body", "AbstractServerHttpResponse", "DefaultWebExchange", "#attributes", "#logId", "#logPrefix", "request", "response", "LOG_ID_ATTRIBUTE", "name", "value", "MockServerHttpRequest", "AbstractHttpRequest", "#url", "#body", "url", "method", "MapHttpHeaders", "blob", "asyncIterator", "stream", "body", "text", "chunks", "reader", "done", "value", "readDone", "name", "MockServerHttpResponse", "AbstractServerHttpResponse", "#writeHandler", "bodyStream", "handler", "cookie", "it", "resolved", "resolve", "reject", "GatewayLogging", "getLogger", "name", "AsyncLocalStorage", "HttpHeadResponseDecorator", "ServerHttpResponseDecorator", "HandlerAdapter", "#logger", "#enableLoggingRequestDetails", "#delegate", "#storage", "logger", "delegate", "request", "response", "DefaultWebExchange", "storage", "value", "headers", "result", "key", "query", "exchange", "trace", "status", "error", "logPrefix", "HttpStatus", "callback", "resolve", "reject", "WebHttpHandlerBuilder", "#webHandler", "AsyncLocalStorage", "#handlerDecorator", "decorator", "previousDecorator", "handler", "webHandler", "getLogger", "adapter", "adapted", "stream", "FailureAfterResponseCompletedError", "response", "options", "sink", "result", "_error", "promise", "resolve", "reject", "error", "HttpHandlerConnector", "_HttpHandlerConnector", "#logger", "getLogger", "#httpHandler", "httpHandler", "method", "uri", "requestCallback", "requestWriteSink", "handlerSink", "savedResponse", "mockClientRequest", "MockClientHttpRequest", "mockServerResponse", "MockServerHttpResponse", "responseBody", "mockServerRequest", "responseToUse", "e", "message", "request", "body", "headers", "cookies", "MockServerHttpRequest", "name", "value", "v", "HttpHeadResponseDecorator", "status", "MockClientHttpResponse", "IOGateway", "log", "getLogger", "regexifyOriginFilters", "originFilters", "block", "IOGateway", "allow", "anyExchange", "_exchange", "match", "EMPTY_OBJECT", "NO_MATCH", "variables", "pattern", "opts", "method", "matcher", "exchange", "request", "path", "upgradeMatcher", "request", "match", "NO_MATCH", "IOGateway", "configure", "app", "config", "routes", "applyCors", "request", "options", "cors", "path", "configurer", "handlers", "handler", "matcher", "pattern", "middleware", "exchange", "next", "match", "variables", "sockets", "factory", "route", "regexifyOriginFilters", "compose", "middleware", "fns", "fn", "ctx", "next", "dispatch", "i", "dispatchedCtx", "nextCalled", "nextResolved", "result", "nextCtx", "AsyncLocalStorage", "bindToApp", "app", "AppSpec", "bindToServer", "DefaultTestClientBuilder", "DefaultTestClient", "#connector", "#baseUrl", "#builder", "connector", "baseUrl", "builder", "input", "init", "method", "uri", "response", "request", "headers", "name", "value", "body", "formDataEntries", "key", "values", "status", "#httpHandlerBuilder", "httpHandlerBuilder", "HttpHandlerConnector", "FetchClientHttpConnector", "AbstractMockServerSpec", "#app", "routes", "configure", "handler", "compose", "WebHttpHandlerBuilder", "TestClient", "bindToApp", "bindToServer"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interopio/gateway-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"gateway",
|
|
6
6
|
"server",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"node": ">=20.10 || >= 22.12 || >= 24"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@interopio/gateway": "^0.
|
|
78
|
+
"@interopio/gateway": "^0.21.0",
|
|
79
79
|
"ws": "^8.18.3",
|
|
80
80
|
"tough-cookie": "^6.0.0",
|
|
81
81
|
"http-cookie-agent": "^7.0.3"
|