@3sixty/api-core-server 0.20.0-next.0 → 0.20.0-next.1
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/LICENSE +201 -0
- package/README.md +20 -2
- package/dist/es/baseServer.js +666 -0
- package/dist/es/baseServer.js.map +1 -0
- package/dist/es/index.js +8 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IBaseServerConstructorOptions.js +2 -0
- package/dist/es/models/IBaseServerConstructorOptions.js.map +1 -0
- package/dist/es/models/IRestProcessorChains.js +2 -0
- package/dist/es/models/IRestProcessorChains.js.map +1 -0
- package/dist/es/models/IServerCorsOptions.js +2 -0
- package/dist/es/models/IServerCorsOptions.js.map +1 -0
- package/dist/es/models/ISocketProcessorChains.js +2 -0
- package/dist/es/models/ISocketProcessorChains.js.map +1 -0
- package/dist/types/baseServer.d.ts +232 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/models/IBaseServerConstructorOptions.d.ts +19 -0
- package/dist/types/models/IRestProcessorChains.d.ts +18 -0
- package/dist/types/models/IServerCorsOptions.d.ts +26 -0
- package/dist/types/models/ISocketProcessorChains.d.ts +26 -0
- package/docs/changelog.md +16 -0
- package/docs/examples.md +78 -0
- package/docs/reference/classes/BaseServer.md +730 -0
- package/docs/reference/index.md +12 -0
- package/docs/reference/interfaces/IBaseServerConstructorOptions.md +33 -0
- package/docs/reference/interfaces/IRestProcessorChains.md +171 -0
- package/docs/reference/interfaces/IServerCorsOptions.md +43 -0
- package/docs/reference/interfaces/ISocketProcessorChains.md +245 -0
- package/locales/.validate-ignore +3 -0
- package/locales/en.json +33 -0
- package/package.json +54 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"baseServer.js","sources":["../../src/baseServer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// Copyright 2026 3Sixty Trade Ltd.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\ttype IncomingMessage,\n\trequest as httpRequest,\n\tvalidateHeaderName,\n\tvalidateHeaderValue\n} from \"node:http\";\nimport { request as httpsRequest } from \"node:https\";\nimport {\n\ttype HealthApplicationCallback,\n\tHealthCategory,\n\tHealthStatus,\n\tHttpBodyLimit,\n\tHttpContextIdKeys,\n\tHttpErrorHelper,\n\ttype IHealth,\n\ttype IHealthProviderComponent,\n\ttype IHttpRequestPathParams,\n\ttype IHttpRequestQuery,\n\ttype IHttpResponse,\n\ttype IHttpServerRequest,\n\ttype IMimeTypeProcessor,\n\ttype IRestRoute,\n\ttype IRestRouteProcessor,\n\ttype ISocketRoute,\n\ttype ISocketRouteProcessor,\n\ttype ISocketServerRequest,\n\ttype IWebServer,\n\ttype IWebServerOptions\n} from \"@3sixty/api-models\";\nimport { JsonLdMimeTypeProcessor } from \"@3sixty/api-processors\";\nimport { ContextIdStore, type IContextIds } from \"@3sixty/context\";\nimport { BaseError, ComponentFactory, GeneralError, Is, RandomHelper, Url } from \"@3sixty/core\";\nimport type { ILoggingComponent } from \"@3sixty/logging-models\";\n\nimport {\n\tHeaderHelper,\n\tHeaderTypes,\n\tHttpMethod,\n\tHttpStatusCode,\n\ttype IHttpHeaders,\n\tMimeTypes\n} from \"@3sixty/web\";\nimport type { IBaseServerConstructorOptions } from \"./models/IBaseServerConstructorOptions.js\";\nimport type { IRestProcessorChains } from \"./models/IRestProcessorChains.js\";\nimport type { IServerCorsOptions } from \"./models/IServerCorsOptions.js\";\nimport type { ISocketProcessorChains } from \"./models/ISocketProcessorChains.js\";\n\n/**\n * Base class for web servers, containing the transport agnostic route processing.\n * Derived classes supply the transport specific behaviour through the abstract server methods.\n */\nexport abstract class BaseServer<T> implements IWebServer<T>, IHealthProviderComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = \"BaseServer\";\n\n\t/**\n\t * Default port for running the server.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_PORT: number = 3000;\n\n\t/**\n\t * Default host for running the server.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_HOST: string = \"localhost\";\n\n\t/**\n\t * Default named body size limits for routes.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_BODY_LIMITS: { [name: string]: number } = {\n\t\t[HttpBodyLimit.Default]: 1048576,\n\t\t[HttpBodyLimit.Large]: 26214400\n\t};\n\n\t/**\n\t * The logging component type.\n\t */\n\tprotected readonly _loggingComponentType?: string;\n\n\t/**\n\t * The logging component.\n\t */\n\tprotected readonly _logging?: ILoggingComponent;\n\n\t/**\n\t * The options for the server.\n\t */\n\tprotected _options?: IWebServerOptions;\n\n\t/**\n\t * Whether the server has been started.\n\t */\n\tprotected _started: boolean;\n\n\t/**\n\t * The mime type processors.\n\t */\n\tprotected readonly _mimeTypeProcessors: IMimeTypeProcessor[];\n\n\t/**\n\t * Include the stack with errors.\n\t */\n\tprotected readonly _includeErrorStack: boolean;\n\n\t/**\n\t * The public origin of the server, used for constructing the request URL and for CORS.\n\t */\n\tprotected _publicOrigin?: string;\n\n\t/**\n\t * The local origin of the server, used for constructing the request URL and for CORS.\n\t */\n\tprotected _localOrigin?: string;\n\n\t/**\n\t * The REST processor chains resolved when the server is built.\n\t */\n\tprotected _restChains: IRestProcessorChains;\n\n\t/**\n\t * The socket processor chains resolved when the server is built.\n\t */\n\tprotected _socketChains: ISocketProcessorChains;\n\n\t/**\n\t * Create a new instance of BaseServer.\n\t * @param options The options for the server.\n\t */\n\tconstructor(options?: IBaseServerConstructorOptions) {\n\t\tthis._loggingComponentType = options?.loggingComponentType;\n\t\tthis._logging = ComponentFactory.getIfExists(options?.loggingComponentType);\n\t\tthis._started = false;\n\t\tthis._restChains = { pre: [], process: [], post: [] };\n\t\tthis._socketChains = { connected: [], disconnected: [], pre: [], process: [], post: [] };\n\t\tthis._mimeTypeProcessors = options?.mimeTypeProcessors ?? [];\n\t\tthis._includeErrorStack = options?.includeErrorStack ?? false;\n\n\t\tconst hasJsonLd = this._mimeTypeProcessors.some(processor =>\n\t\t\tprocessor.getTypes().includes(MimeTypes.JsonLd)\n\t\t);\n\t\tif (!hasJsonLd) {\n\t\t\tthis._mimeTypeProcessors.push(new JsonLdMimeTypeProcessor());\n\t\t}\n\t}\n\n\t/**\n\t * Start the server.\n\t * @returns A promise that resolves when the server is listening for connections.\n\t */\n\tpublic async start(): Promise<void> {\n\t\tconst host = this._options?.host ?? BaseServer._DEFAULT_HOST;\n\t\tconst port = this._options?.port ?? BaseServer._DEFAULT_PORT;\n\n\t\tawait this._logging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tts: Date.now(),\n\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\tmessage: \"starting\",\n\t\t\tdata: {\n\t\t\t\thost,\n\t\t\t\tport\n\t\t\t}\n\t\t});\n\n\t\tif (!this._started) {\n\t\t\ttry {\n\t\t\t\tawait this.serverListen(host, port);\n\t\t\t\tconst addresses = this.serverAddresses();\n\n\t\t\t\tconst protocol = this.serverIsSecure() ? \"https://\" : \"http://\";\n\t\t\t\tconst normalizeAnyHost = (address: string): string => {\n\t\t\t\t\tif (address === \"0.0.0.0\") {\n\t\t\t\t\t\treturn \"127.0.0.1\";\n\t\t\t\t\t}\n\t\t\t\t\tif (address === \"::\") {\n\t\t\t\t\t\treturn \"::1\";\n\t\t\t\t\t}\n\n\t\t\t\t\treturn address;\n\t\t\t\t};\n\n\t\t\t\tconst formatAddress = (\n\t\t\t\t\taddress: string,\n\t\t\t\t\tfamily?: string,\n\t\t\t\t\tforceProtocol?: string\n\t\t\t\t): string => {\n\t\t\t\t\tconst displayAddress = normalizeAnyHost(address);\n\t\t\t\t\tconst isIPv6 =\n\t\t\t\t\t\tfamily === \"IPv6\" || (Is.stringValue(displayAddress) && displayAddress.includes(\":\"));\n\n\t\t\t\t\treturn `${forceProtocol ?? protocol}${isIPv6 ? \"[\" : \"\"}${displayAddress}${isIPv6 ? \"]\" : \"\"}`;\n\t\t\t\t};\n\n\t\t\t\tconst startupAddresses = addresses.map(a => {\n\t\t\t\t\tconst formatted = formatAddress(a.address, a.family, protocol);\n\n\t\t\t\t\treturn `${formatted}:${a.port}`;\n\t\t\t\t});\n\n\t\t\t\tfor (const origin of [this._localOrigin, this._publicOrigin]) {\n\t\t\t\t\tif (Is.stringValue(origin)) {\n\t\t\t\t\t\tconst originUrl = Url.tryParseExact(origin);\n\t\t\t\t\t\tif (!Is.empty(originUrl)) {\n\t\t\t\t\t\t\tconst originParts = originUrl.parts();\n\t\t\t\t\t\t\tconst formatted = formatAddress(\n\t\t\t\t\t\t\t\toriginParts.host,\n\t\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\t`${originParts.schema}://`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tstartupAddresses.push(\n\t\t\t\t\t\t\t\t`${formatted}${Is.integer(originParts.port) ? `:${originParts.port}` : \"\"}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstartupAddresses.push(origin);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst distinctStartupAddresses = [...new Set(startupAddresses)];\n\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"started\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\taddresses: distinctStartupAddresses.join(\", \")\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tthis._started = true;\n\t\t\t} catch (err) {\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"startFailed\",\n\t\t\t\t\terror: BaseError.fromError(err)\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Stop the server.\n\t * @returns A promise that resolves when the server has shut down all connections.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tif (this._started) {\n\t\t\tthis._started = false;\n\n\t\t\tawait this.serverClose();\n\n\t\t\tawait this._logging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tts: Date.now(),\n\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\tmessage: \"stopped\"\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component, can return multiple entries for elements within the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\tlet healthCheck: IHealth | undefined;\n\t\tif (this.serverIsListening()) {\n\t\t\thealthCheck = {\n\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\tcategory: HealthCategory.Connectivity,\n\t\t\t\tdescription: \"healthConnectivityDescription\",\n\t\t\t\tmessage: \"reachable\"\n\t\t\t};\n\t\t} else {\n\t\t\thealthCheck = {\n\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\tcategory: HealthCategory.Connectivity,\n\t\t\t\tdescription: \"healthConnectivityDescription\",\n\t\t\t\tmessage: \"unreachable\"\n\t\t\t};\n\t\t}\n\n\t\treturn [healthCheck];\n\t}\n\n\t/**\n\t * Verify the root endpoint is reachable and returns a body by making a real HTTP request.\n\t * Skipped when GET / is not registered on this server instance.\n\t * @param callback The callback to invoke when a deferred health result is ready.\n\t * @returns The application health status of the component.\n\t */\n\tpublic async healthApplication(\n\t\tcallback: HealthApplicationCallback\n\t): Promise<IHealth[] | undefined> {\n\t\tif (!this.serverHasRootRoute()) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (!Is.stringValue(this._localOrigin)) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tcategory: HealthCategory.Application,\n\t\t\t\t\tdescription: \"healthApplicationDescription\",\n\t\t\t\t\tmessage: \"serverNotBuilt\"\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await this.requestLocalRoot(`${this._localOrigin}/`);\n\n\t\t\tif (response.ok && Is.stringValue(response.body)) {\n\t\t\t\treturn [\n\t\t\t\t\t{\n\t\t\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\t\tcategory: HealthCategory.Application,\n\t\t\t\t\t\tdescription: \"healthApplicationDescription\",\n\t\t\t\t\t\tmessage: \"rootEndpointReachable\"\n\t\t\t\t\t}\n\t\t\t\t];\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tcategory: HealthCategory.Application,\n\t\t\t\t\tdescription: \"healthApplicationDescription\",\n\t\t\t\t\tmessage: \"rootEndpointError\"\n\t\t\t\t}\n\t\t\t];\n\t\t} catch (error) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tcategory: HealthCategory.Application,\n\t\t\t\t\tdescription: \"healthApplicationDescription\",\n\t\t\t\t\terror: BaseError.fromError(error)\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * Request the root endpoint of this server over the loopback address.\n\t * @param url The url of the root endpoint.\n\t * @returns Whether the response was successful and its body.\n\t */\n\tprotected async requestLocalRoot(url: string): Promise<{ ok: boolean; body: string }> {\n\t\tconst isSecure = url.startsWith(\"https:\");\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst callback = (response: IncomingMessage): void => {\n\t\t\t\tconst chunks: Buffer[] = [];\n\t\t\t\tresponse.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n\t\t\t\tresponse.on(\"error\", reject);\n\t\t\t\tresponse.on(\"end\", () => {\n\t\t\t\t\tconst statusCode = response.statusCode ?? 0;\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tok: statusCode >= HttpStatusCode.ok && statusCode < HttpStatusCode.multipleChoices,\n\t\t\t\t\t\tbody: Buffer.concat(chunks).toString(\"utf8\")\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t};\n\t\t\t// The certificate is issued for the public host name rather than the loopback\n\t\t\t// address, and this only checks the server can reach its own listener, so it\n\t\t\t// is not verified\n\t\t\tconst request = isSecure\n\t\t\t\t? httpsRequest(url, { rejectUnauthorized: false }, callback)\n\t\t\t\t: httpRequest(url, callback);\n\t\t\trequest.on(\"error\", reject);\n\t\t\trequest.end();\n\t\t});\n\t}\n\n\t/**\n\t * Perform the transport agnostic part of building the server, validating the routes and\n\t * processors, resolving the origins and resolving the processor chains.\n\t * @param restRouteProcessors The processors for incoming requests over REST.\n\t * @param restRoutes The REST routes.\n\t * @param socketRouteProcessors The processors for incoming requests over Sockets.\n\t * @param socketRoutes The socket routes.\n\t * @param options Options for building the server.\n\t * @returns A promise that resolves when the shared build steps are complete.\n\t */\n\tprotected async prepareBuild(\n\t\trestRouteProcessors?: IRestRouteProcessor[],\n\t\trestRoutes?: IRestRoute[],\n\t\tsocketRouteProcessors?: ISocketRouteProcessor[],\n\t\tsocketRoutes?: ISocketRoute[],\n\t\toptions?: IWebServerOptions\n\t): Promise<void> {\n\t\tif (Is.arrayValue(restRoutes) && !Is.arrayValue(restRouteProcessors)) {\n\t\t\tthrow new GeneralError(BaseServer.CLASS_NAME, \"noRestProcessors\");\n\t\t}\n\t\tif (Is.arrayValue(socketRoutes) && !Is.arrayValue(socketRouteProcessors)) {\n\t\t\tthrow new GeneralError(BaseServer.CLASS_NAME, \"noSocketProcessors\");\n\t\t}\n\t\tawait this._logging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tts: Date.now(),\n\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\tmessage: \"building\"\n\t\t});\n\n\t\tlet localHost = options?.host ?? \"127.0.0.1\";\n\t\tif (localHost === \"0.0.0.0\") {\n\t\t\tlocalHost = \"127.0.0.1\";\n\t\t}\n\n\t\tthis._localOrigin = `${this.serverIsSecure() ? \"https\" : \"http\"}://${localHost}:${options?.port ?? 3000}`;\n\n\t\tif (Is.stringValue(options?.publicOrigin)) {\n\t\t\tconst publicUrl = Url.tryParseExact(options.publicOrigin);\n\t\t\tif (!Is.empty(publicUrl)) {\n\t\t\t\tconst urlParts = publicUrl.parts();\n\t\t\t\tthis._publicOrigin = `${urlParts.schema}://${urlParts.host}${Is.integer(urlParts.port) ? `:${urlParts.port}` : \"\"}`;\n\t\t\t} else {\n\t\t\t\tthrow new GeneralError(BaseServer.CLASS_NAME, \"invalidPublicOrigin\", {\n\t\t\t\t\tpublicOrigin: options.publicOrigin\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis._options = options;\n\n\t\tthis.buildProcessorChains(restRouteProcessors, socketRouteProcessors);\n\t}\n\n\t/**\n\t * Resolve the route processors in to per phase chains, so that the lookups and bindings\n\t * are performed once when the server is built instead of on every request.\n\t * @param restRouteProcessors The processors for the incoming REST requests.\n\t * @param socketRouteProcessors The processors for the incoming socket requests.\n\t */\n\tprotected buildProcessorChains(\n\t\trestRouteProcessors?: IRestRouteProcessor[],\n\t\tsocketRouteProcessors?: ISocketRouteProcessor[]\n\t): void {\n\t\tconst restChains: IRestProcessorChains = { pre: [], process: [], post: [] };\n\n\t\tfor (const routeProcessor of restRouteProcessors ?? []) {\n\t\t\tconst pre = routeProcessor.pre?.bind(routeProcessor);\n\t\t\tif (Is.function(pre)) {\n\t\t\t\trestChains.pre.push(pre);\n\t\t\t}\n\t\t\tconst process = routeProcessor.process?.bind(routeProcessor);\n\t\t\tif (Is.function(process)) {\n\t\t\t\trestChains.process.push(process);\n\t\t\t}\n\t\t\tconst post = routeProcessor.post?.bind(routeProcessor);\n\t\t\tif (Is.function(post)) {\n\t\t\t\trestChains.post.push(post);\n\t\t\t}\n\t\t}\n\n\t\tconst socketChains: ISocketProcessorChains = {\n\t\t\tconnected: [],\n\t\t\tdisconnected: [],\n\t\t\tpre: [],\n\t\t\tprocess: [],\n\t\t\tpost: []\n\t\t};\n\n\t\tfor (const routeProcessor of socketRouteProcessors ?? []) {\n\t\t\tconst connected = routeProcessor.connected?.bind(routeProcessor);\n\t\t\tif (Is.function(connected)) {\n\t\t\t\tsocketChains.connected.push(connected);\n\t\t\t}\n\t\t\tconst disconnected = routeProcessor.disconnected?.bind(routeProcessor);\n\t\t\tif (Is.function(disconnected)) {\n\t\t\t\tsocketChains.disconnected.push(disconnected);\n\t\t\t}\n\t\t\tconst pre = routeProcessor.pre?.bind(routeProcessor);\n\t\t\tif (Is.function(pre)) {\n\t\t\t\tsocketChains.pre.push(pre);\n\t\t\t}\n\t\t\tconst process = routeProcessor.process?.bind(routeProcessor);\n\t\t\tif (Is.function(process)) {\n\t\t\t\tsocketChains.process.push(process);\n\t\t\t}\n\t\t\tconst post = routeProcessor.post?.bind(routeProcessor);\n\t\t\tif (Is.function(post)) {\n\t\t\t\tsocketChains.post.push(post);\n\t\t\t}\n\t\t}\n\n\t\tthis._restChains = restChains;\n\t\tthis._socketChains = socketChains;\n\t}\n\n\t/**\n\t * Merge the configured body limits over the built-in ones and validate them.\n\t * @returns The named body limits in bytes.\n\t * @throws GeneralError If a limit is not a positive integer.\n\t */\n\tprotected resolveBodyLimits(): { [name: string]: number } {\n\t\tconst bodyLimits = {\n\t\t\t...BaseServer._DEFAULT_BODY_LIMITS,\n\t\t\t...this._options?.bodyLimits\n\t\t};\n\t\tfor (const name of Object.keys(bodyLimits)) {\n\t\t\tconst bodyLimit = bodyLimits[name];\n\t\t\tif (!Is.integer(bodyLimit) || bodyLimit <= 0) {\n\t\t\t\tthrow new GeneralError(BaseServer.CLASS_NAME, \"invalidBodyLimit\", {\n\t\t\t\t\tbodyLimit: name,\n\t\t\t\t\tvalue: bodyLimit\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn bodyLimits;\n\t}\n\n\t/**\n\t * Resolve the CORS options from the web server options, merging in the defaults.\n\t * @param options The web server options.\n\t * @returns The resolved CORS options.\n\t */\n\tprotected resolveCorsOptions(options?: IWebServerOptions): IServerCorsOptions {\n\t\tlet origins: string[] = [\"*\"];\n\n\t\tif (Is.arrayValue(options?.corsOrigins)) {\n\t\t\torigins = options?.corsOrigins;\n\t\t} else if (Is.stringValue(options?.corsOrigins)) {\n\t\t\torigins = [options?.corsOrigins];\n\t\t}\n\n\t\tconst hasWildcardOrigin = origins.includes(\"*\");\n\n\t\tconst methods = options?.methods ?? [\n\t\t\tHttpMethod.GET,\n\t\t\tHttpMethod.PUT,\n\t\t\tHttpMethod.POST,\n\t\t\tHttpMethod.PATCH,\n\t\t\tHttpMethod.DELETE,\n\t\t\tHttpMethod.OPTIONS\n\t\t];\n\t\tconst allowedHeaders: string[] = [\n\t\t\tHeaderTypes.AccessControlAllowOrigin,\n\t\t\tHeaderTypes.ContentEncoding,\n\t\t\tHeaderTypes.AcceptEncoding,\n\t\t\tHeaderTypes.ContentType,\n\t\t\tHeaderTypes.Authorization,\n\t\t\tHeaderTypes.Accept\n\t\t];\n\t\tconst exposedHeaders: string[] = [HeaderTypes.ContentDisposition, HeaderTypes.Location];\n\n\t\tif (Is.arrayValue(options?.allowedHeaders)) {\n\t\t\tallowedHeaders.push(...options.allowedHeaders);\n\t\t}\n\t\tif (Is.arrayValue(options?.exposedHeaders)) {\n\t\t\texposedHeaders.push(...options.exposedHeaders);\n\t\t}\n\n\t\treturn { origins, hasWildcardOrigin, methods, allowedHeaders, exposedHeaders };\n\t}\n\n\t/**\n\t * Build the server request from the transport values, the path params and query must already\n\t * have been decoded by the transport, as decoding them again corrupts values containing %.\n\t * @param method The request method.\n\t * @param url The full request url, including the origin.\n\t * @param body The request body.\n\t * @param query The request query params.\n\t * @param pathParams The request path params.\n\t * @param headers The request headers.\n\t * @returns The server request.\n\t */\n\tprotected buildServerRequest(\n\t\tmethod: HttpMethod,\n\t\turl: string,\n\t\tbody: unknown,\n\t\tquery?: IHttpRequestQuery,\n\t\tpathParams?: IHttpRequestPathParams,\n\t\theaders?: IHttpHeaders\n\t): IHttpServerRequest {\n\t\treturn {\n\t\t\tmethod,\n\t\t\turl,\n\t\t\tbody,\n\t\t\tquery,\n\t\t\tpathParams,\n\t\t\theaders\n\t\t};\n\t}\n\n\t/**\n\t * Validate the processed response before it is sent, so that every transport fails an invalid\n\t * response in the same way rather than with its own transport specific error.\n\t * @param httpResponse The processed response.\n\t * @throws GeneralError If the status code or a header is invalid.\n\t */\n\tprotected validateResponse(httpResponse: IHttpResponse): void {\n\t\tconst statusCode = httpResponse.statusCode;\n\t\tif (\n\t\t\t!Is.empty(statusCode) &&\n\t\t\t(!Is.integer(statusCode) || statusCode < 100 || statusCode > 599)\n\t\t) {\n\t\t\tthrow new GeneralError(BaseServer.CLASS_NAME, \"invalidStatusCode\", { statusCode });\n\t\t}\n\t\tif (!Is.empty(httpResponse.headers)) {\n\t\t\tfor (const header of Object.keys(httpResponse.headers)) {\n\t\t\t\tconst value = httpResponse.headers[header];\n\t\t\t\ttry {\n\t\t\t\t\tvalidateHeaderName(header);\n\t\t\t\t\tfor (const item of Is.array(value) ? value : [value]) {\n\t\t\t\t\t\tif (!Is.empty(item)) {\n\t\t\t\t\t\t\tvalidateHeaderValue(header, item);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (err) {\n\t\t\t\t\tthrow new GeneralError(BaseServer.CLASS_NAME, \"invalidHeader\", { header }, err);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build the context ids for an incoming request.\n\t * @param requestOrigin The origin the request was received on.\n\t * @param headers The request headers.\n\t * @returns The context ids.\n\t */\n\tprotected buildContextIds(requestOrigin: string, headers?: IHttpHeaders): IContextIds {\n\t\treturn {\n\t\t\t[HttpContextIdKeys.IpAddress]: HeaderHelper.extractClientIps(headers).join(\"|\"),\n\t\t\t[HttpContextIdKeys.UserAgent]: HeaderHelper.extractUserAgent(headers),\n\t\t\t[HttpContextIdKeys.CorrelationId]: HeaderHelper.extractCorrelationId(headers),\n\t\t\t[HttpContextIdKeys.RemoteRequest]: RandomHelper.generateUuidV7(\"compact\"),\n\t\t\t[HttpContextIdKeys.LocalOrigin]: this._localOrigin,\n\t\t\t// This can be overridden by a processor if needed, for example a tenant processor\n\t\t\t[HttpContextIdKeys.PublicOrigin]: this._publicOrigin ?? requestOrigin ?? this._localOrigin\n\t\t};\n\t}\n\n\t/**\n\t * Run the REST processors for the route.\n\t * @param restRoute The route to process.\n\t * @param httpServerRequest The incoming request.\n\t * @param httpResponse The outgoing response.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t */\n\tprotected async runProcessorsRest(\n\t\trestRoute: IRestRoute | undefined,\n\t\thttpServerRequest: IHttpServerRequest,\n\t\thttpResponse: IHttpResponse,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: {\n\t\t\t[id: string]: unknown;\n\t\t}\n\t): Promise<void> {\n\t\tlet hasPreError = false;\n\n\t\ttry {\n\t\t\t// Run inside ContextIdStore.run so pre-processors can do tenant-scoped storage lookups.\n\t\t\tawait ContextIdStore.run(contextIds, async () => {\n\t\t\t\tfor (const pre of this._restChains.pre) {\n\t\t\t\t\tawait pre(httpServerRequest, httpResponse, restRoute, contextIds, processorState, {\n\t\t\t\t\t\tloggingComponentType: this._loggingComponentType\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tconst { error, httpStatusCode } = HttpErrorHelper.processError(err, this._includeErrorStack);\n\t\t\tHttpErrorHelper.buildResponse(httpResponse, error, httpStatusCode, this._includeErrorStack);\n\t\t\thasPreError = true;\n\t\t}\n\n\t\t// A pre-processor may set an error response without throwing; treat that as halt.\n\t\tif (\n\t\t\t!hasPreError &&\n\t\t\tIs.integer(httpResponse.statusCode) &&\n\t\t\thttpResponse.statusCode >= HttpStatusCode.badRequest\n\t\t) {\n\t\t\thasPreError = true;\n\t\t}\n\n\t\t// Don't run the main processing if there was an error in the pre processing\n\t\t// As this is likely to perform tasks such as authentication which may have failed\n\t\tif (!hasPreError) {\n\t\t\ttry {\n\t\t\t\t// Run the processors within an async context\n\t\t\t\t// so that any services can access the context ids\n\t\t\t\tawait ContextIdStore.run(contextIds, async () => {\n\t\t\t\t\tfor (const process of this._restChains.process) {\n\t\t\t\t\t\tawait process(httpServerRequest, httpResponse, restRoute, processorState, {\n\t\t\t\t\t\t\tloggingComponentType: this._loggingComponentType\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tconst { error, httpStatusCode } = HttpErrorHelper.processError(\n\t\t\t\t\terr,\n\t\t\t\t\tthis._includeErrorStack\n\t\t\t\t);\n\t\t\t\tHttpErrorHelper.buildResponse(httpResponse, error, httpStatusCode, this._includeErrorStack);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\t// Always run the post processors, even if there was an error earlier\n\t\t\t// as they may perform cleanup tasks, or logging etc\n\t\t\tawait ContextIdStore.run(contextIds, async () => {\n\t\t\t\tfor (const post of this._restChains.post) {\n\t\t\t\t\tawait post(httpServerRequest, httpResponse, restRoute, contextIds, processorState, {\n\t\t\t\t\t\tloggingComponentType: this._loggingComponentType\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (err) {\n\t\t\t// Just log post processor errors\n\t\t\tawait this._logging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tts: Date.now(),\n\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\tmessage: \"postProcessorError\",\n\t\t\t\terror: BaseError.fromError(err),\n\t\t\t\tdata: {\n\t\t\t\t\troute: restRoute?.path ?? \"\"\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Run the socket processors for the route.\n\t * @param socketRoute The route to process.\n\t * @param socketServerRequest The incoming request.\n\t * @param httpResponse The outgoing response.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t * @param requestTopic The topic of the request.\n\t * @param responseEmitter The emitter to send the response on.\n\t */\n\tprotected async runProcessorsSocket(\n\t\tsocketRoute: ISocketRoute,\n\t\tsocketServerRequest: ISocketServerRequest,\n\t\thttpResponse: IHttpResponse,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: {\n\t\t\t[id: string]: unknown;\n\t\t},\n\t\trequestTopic: string,\n\t\tresponseEmitter: (topic: string, response: IHttpResponse) => Promise<void>\n\t): Promise<void> {\n\t\t// Custom emit method which will also call the post processors\n\t\tconst postProcessEmit = async (\n\t\t\ttopic: string,\n\t\t\tresponse: IHttpResponse,\n\t\t\tresponseProcessorState: {\n\t\t\t\t[id: string]: unknown;\n\t\t\t}\n\t\t): Promise<void> => {\n\t\t\tawait responseEmitter(topic, response);\n\n\t\t\ttry {\n\t\t\t\t// The post processors are called after the response has been emitted\n\t\t\t\tfor (const post of this._socketChains.post) {\n\t\t\t\t\tawait post(\n\t\t\t\t\t\tsocketServerRequest,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\tcontextIds,\n\t\t\t\t\t\tresponseProcessorState,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tloggingComponentType: this._loggingComponentType\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\tawait this._logging?.log({\n\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tsource: BaseServer.CLASS_NAME,\n\t\t\t\t\tmessage: \"postProcessorError\",\n\t\t\t\t\terror: BaseError.fromError(err),\n\t\t\t\t\tdata: {\n\t\t\t\t\t\troute: socketRoute.path\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\tfor (const pre of this._socketChains.pre) {\n\t\t\t\tawait pre(socketServerRequest, httpResponse, socketRoute, contextIds, processorState, {\n\t\t\t\t\tloggingComponentType: this._loggingComponentType\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// We always call all the processors regardless of any response set by a previous processor.\n\t\t\t// But if a pre processor sets a status code, we will emit the response manually, as the pre\n\t\t\t// and post processors do not receive the emit method, they just populate the response object.\n\t\t\tif (!Is.empty(httpResponse.statusCode)) {\n\t\t\t\tawait postProcessEmit(requestTopic, httpResponse, processorState);\n\t\t\t}\n\n\t\t\tawait ContextIdStore.run(contextIds, async () => {\n\t\t\t\tfor (const process of this._socketChains.process) {\n\t\t\t\t\tawait process(\n\t\t\t\t\t\tsocketServerRequest,\n\t\t\t\t\t\thttpResponse,\n\t\t\t\t\t\tsocketRoute,\n\t\t\t\t\t\tprocessorState,\n\t\t\t\t\t\tasync (topic: string, processResponse: IHttpResponse) => {\n\t\t\t\t\t\t\tawait postProcessEmit(topic, processResponse, processorState);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tthis._loggingComponentType\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// If the processors set the status to any kind of error then we should emit this manually\n\t\t\tif (\n\t\t\t\tIs.integer(httpResponse.statusCode) &&\n\t\t\t\thttpResponse.statusCode >= HttpStatusCode.badRequest\n\t\t\t) {\n\t\t\t\tawait postProcessEmit(requestTopic, httpResponse, processorState);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\t// Emit any unhandled errors manually\n\t\t\tconst { error, httpStatusCode } = HttpErrorHelper.processError(err, this._includeErrorStack);\n\t\t\tHttpErrorHelper.buildResponse(httpResponse, error, httpStatusCode, this._includeErrorStack);\n\t\t\tawait postProcessEmit(requestTopic, httpResponse, processorState);\n\t\t}\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic abstract className(): string;\n\n\t/**\n\t * Get the web server instance.\n\t * @returns The web server instance.\n\t */\n\tpublic abstract getInstance(): T;\n\n\t/**\n\t * Build the server.\n\t * @param restRouteProcessors The processors for incoming requests over REST.\n\t * @param restRoutes The REST routes.\n\t * @param socketRouteProcessors The processors for incoming requests over Sockets.\n\t * @param socketRoutes The socket routes.\n\t * @param options Options for building the server.\n\t * @returns A promise that resolves when the server is fully built and ready to start.\n\t */\n\tpublic abstract build(\n\t\trestRouteProcessors?: IRestRouteProcessor[],\n\t\trestRoutes?: IRestRoute[],\n\t\tsocketRouteProcessors?: ISocketRouteProcessor[],\n\t\tsocketRoutes?: ISocketRoute[],\n\t\toptions?: IWebServerOptions\n\t): Promise<void>;\n\n\t/**\n\t * Start listening for connections on the transport.\n\t * @param host The host to bind to.\n\t * @param port The port to bind to.\n\t * @returns A promise that resolves when the transport is listening.\n\t */\n\tprotected abstract serverListen(host: string, port: number): Promise<void>;\n\n\t/**\n\t * Close the transport and all of its connections.\n\t * @returns A promise that resolves when the transport has closed.\n\t */\n\tprotected abstract serverClose(): Promise<void>;\n\n\t/**\n\t * Get the addresses the transport is bound to.\n\t * @returns The bound addresses.\n\t */\n\tprotected abstract serverAddresses(): { address: string; family?: string; port: number }[];\n\n\t/**\n\t * Whether the transport is serving over TLS.\n\t * @returns True if the transport is secure.\n\t */\n\tprotected abstract serverIsSecure(): boolean;\n\n\t/**\n\t * Whether the transport is currently listening for connections.\n\t * @returns True if the transport is listening.\n\t */\n\tprotected abstract serverIsListening(): boolean;\n\n\t/**\n\t * Whether a GET route is registered for the root path.\n\t * @returns True if the root route is registered.\n\t */\n\tprotected abstract serverHasRootRoute(): boolean;\n}\n"]}
|
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Copyright 2026 3Sixty Trade Ltd.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
+
export * from "./baseServer.js";
|
|
4
|
+
export * from "./models/IBaseServerConstructorOptions.js";
|
|
5
|
+
export * from "./models/IRestProcessorChains.js";
|
|
6
|
+
export * from "./models/IServerCorsOptions.js";
|
|
7
|
+
export * from "./models/ISocketProcessorChains.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,uCAAuC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,2CAA2C,CAAC;AAC1D,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC","sourcesContent":["// Copyright 2026 3Sixty Trade Ltd.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./baseServer.js\";\nexport * from \"./models/IBaseServerConstructorOptions.js\";\nexport * from \"./models/IRestProcessorChains.js\";\nexport * from \"./models/IServerCorsOptions.js\";\nexport * from \"./models/ISocketProcessorChains.js\";\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IBaseServerConstructorOptions.js","sources":["../../../src/models/IBaseServerConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// Copyright 2026 3Sixty Trade Ltd.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IMimeTypeProcessor } from \"@3sixty/api-models\";\n\n/**\n * Options for constructing a base server.\n */\nexport interface IBaseServerConstructorOptions {\n\t/**\n\t * The type of the logging component to use, defaults to no logging.\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * The mime type processors to use for the request bodies.\n\t */\n\tmimeTypeProcessors?: IMimeTypeProcessor[];\n\n\t/**\n\t * Include the stack with errors.\n\t * @default false\n\t */\n\tincludeErrorStack?: boolean;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IRestProcessorChains.js","sources":["../../../src/models/IRestProcessorChains.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// Copyright 2026 3Sixty Trade Ltd.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRestRouteProcessor } from \"@3sixty/api-models\";\n\n/**\n * The REST processor phase chains, bound to their processors when the server is built.\n */\nexport interface IRestProcessorChains {\n\t/**\n\t * The pre processing phase.\n\t */\n\tpre: NonNullable<IRestRouteProcessor[\"pre\"]>[];\n\n\t/**\n\t * The main processing phase.\n\t */\n\tprocess: NonNullable<IRestRouteProcessor[\"process\"]>[];\n\n\t/**\n\t * The post processing phase.\n\t */\n\tpost: NonNullable<IRestRouteProcessor[\"post\"]>[];\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IServerCorsOptions.js","sources":["../../../src/models/IServerCorsOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// Copyright 2026 3Sixty Trade Ltd.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { HttpMethod } from \"@3sixty/web\";\n\n/**\n * The resolved CORS options for a server.\n */\nexport interface IServerCorsOptions {\n\t/**\n\t * The allowed origins.\n\t */\n\torigins: string[];\n\n\t/**\n\t * Whether the allowed origins include the wildcard, in which case any origin is allowed.\n\t */\n\thasWildcardOrigin: boolean;\n\n\t/**\n\t * The allowed methods.\n\t */\n\tmethods: HttpMethod[];\n\n\t/**\n\t * The allowed headers.\n\t */\n\tallowedHeaders: string[];\n\n\t/**\n\t * The exposed headers.\n\t */\n\texposedHeaders: string[];\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ISocketProcessorChains.js","sources":["../../../src/models/ISocketProcessorChains.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// Copyright 2026 3Sixty Trade Ltd.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ISocketRouteProcessor } from \"@3sixty/api-models\";\n\n/**\n * The socket processor phase chains, bound to their processors when the server is built.\n */\nexport interface ISocketProcessorChains {\n\t/**\n\t * The socket connected phase.\n\t */\n\tconnected: NonNullable<ISocketRouteProcessor[\"connected\"]>[];\n\n\t/**\n\t * The socket disconnected phase.\n\t */\n\tdisconnected: NonNullable<ISocketRouteProcessor[\"disconnected\"]>[];\n\n\t/**\n\t * The pre processing phase.\n\t */\n\tpre: NonNullable<ISocketRouteProcessor[\"pre\"]>[];\n\n\t/**\n\t * The main processing phase.\n\t */\n\tprocess: NonNullable<ISocketRouteProcessor[\"process\"]>[];\n\n\t/**\n\t * The post processing phase.\n\t */\n\tpost: NonNullable<ISocketRouteProcessor[\"post\"]>[];\n}\n"]}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { type HealthApplicationCallback, type IHealth, type IHealthProviderComponent, type IHttpRequestPathParams, type IHttpRequestQuery, type IHttpResponse, type IHttpServerRequest, type IMimeTypeProcessor, type IRestRoute, type IRestRouteProcessor, type ISocketRoute, type ISocketRouteProcessor, type ISocketServerRequest, type IWebServer, type IWebServerOptions } from "@3sixty/api-models";
|
|
2
|
+
import { type IContextIds } from "@3sixty/context";
|
|
3
|
+
import type { ILoggingComponent } from "@3sixty/logging-models";
|
|
4
|
+
import { HttpMethod, type IHttpHeaders } from "@3sixty/web";
|
|
5
|
+
import type { IBaseServerConstructorOptions } from "./models/IBaseServerConstructorOptions.js";
|
|
6
|
+
import type { IRestProcessorChains } from "./models/IRestProcessorChains.js";
|
|
7
|
+
import type { IServerCorsOptions } from "./models/IServerCorsOptions.js";
|
|
8
|
+
import type { ISocketProcessorChains } from "./models/ISocketProcessorChains.js";
|
|
9
|
+
/**
|
|
10
|
+
* Base class for web servers, containing the transport agnostic route processing.
|
|
11
|
+
* Derived classes supply the transport specific behaviour through the abstract server methods.
|
|
12
|
+
*/
|
|
13
|
+
export declare abstract class BaseServer<T> implements IWebServer<T>, IHealthProviderComponent {
|
|
14
|
+
/**
|
|
15
|
+
* Runtime name for the class.
|
|
16
|
+
*/
|
|
17
|
+
static readonly CLASS_NAME: string;
|
|
18
|
+
/**
|
|
19
|
+
* The logging component type.
|
|
20
|
+
*/
|
|
21
|
+
protected readonly _loggingComponentType?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The logging component.
|
|
24
|
+
*/
|
|
25
|
+
protected readonly _logging?: ILoggingComponent;
|
|
26
|
+
/**
|
|
27
|
+
* The options for the server.
|
|
28
|
+
*/
|
|
29
|
+
protected _options?: IWebServerOptions;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the server has been started.
|
|
32
|
+
*/
|
|
33
|
+
protected _started: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* The mime type processors.
|
|
36
|
+
*/
|
|
37
|
+
protected readonly _mimeTypeProcessors: IMimeTypeProcessor[];
|
|
38
|
+
/**
|
|
39
|
+
* Include the stack with errors.
|
|
40
|
+
*/
|
|
41
|
+
protected readonly _includeErrorStack: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The public origin of the server, used for constructing the request URL and for CORS.
|
|
44
|
+
*/
|
|
45
|
+
protected _publicOrigin?: string;
|
|
46
|
+
/**
|
|
47
|
+
* The local origin of the server, used for constructing the request URL and for CORS.
|
|
48
|
+
*/
|
|
49
|
+
protected _localOrigin?: string;
|
|
50
|
+
/**
|
|
51
|
+
* The REST processor chains resolved when the server is built.
|
|
52
|
+
*/
|
|
53
|
+
protected _restChains: IRestProcessorChains;
|
|
54
|
+
/**
|
|
55
|
+
* The socket processor chains resolved when the server is built.
|
|
56
|
+
*/
|
|
57
|
+
protected _socketChains: ISocketProcessorChains;
|
|
58
|
+
/**
|
|
59
|
+
* Create a new instance of BaseServer.
|
|
60
|
+
* @param options The options for the server.
|
|
61
|
+
*/
|
|
62
|
+
constructor(options?: IBaseServerConstructorOptions);
|
|
63
|
+
/**
|
|
64
|
+
* Start the server.
|
|
65
|
+
* @returns A promise that resolves when the server is listening for connections.
|
|
66
|
+
*/
|
|
67
|
+
start(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Stop the server.
|
|
70
|
+
* @returns A promise that resolves when the server has shut down all connections.
|
|
71
|
+
*/
|
|
72
|
+
stop(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the health status of the component.
|
|
75
|
+
* @returns The health status of the component, can return multiple entries for elements within the component.
|
|
76
|
+
*/
|
|
77
|
+
health(): Promise<IHealth[]>;
|
|
78
|
+
/**
|
|
79
|
+
* Verify the root endpoint is reachable and returns a body by making a real HTTP request.
|
|
80
|
+
* Skipped when GET / is not registered on this server instance.
|
|
81
|
+
* @param callback The callback to invoke when a deferred health result is ready.
|
|
82
|
+
* @returns The application health status of the component.
|
|
83
|
+
*/
|
|
84
|
+
healthApplication(callback: HealthApplicationCallback): Promise<IHealth[] | undefined>;
|
|
85
|
+
/**
|
|
86
|
+
* Request the root endpoint of this server over the loopback address.
|
|
87
|
+
* @param url The url of the root endpoint.
|
|
88
|
+
* @returns Whether the response was successful and its body.
|
|
89
|
+
*/
|
|
90
|
+
protected requestLocalRoot(url: string): Promise<{
|
|
91
|
+
ok: boolean;
|
|
92
|
+
body: string;
|
|
93
|
+
}>;
|
|
94
|
+
/**
|
|
95
|
+
* Perform the transport agnostic part of building the server, validating the routes and
|
|
96
|
+
* processors, resolving the origins and resolving the processor chains.
|
|
97
|
+
* @param restRouteProcessors The processors for incoming requests over REST.
|
|
98
|
+
* @param restRoutes The REST routes.
|
|
99
|
+
* @param socketRouteProcessors The processors for incoming requests over Sockets.
|
|
100
|
+
* @param socketRoutes The socket routes.
|
|
101
|
+
* @param options Options for building the server.
|
|
102
|
+
* @returns A promise that resolves when the shared build steps are complete.
|
|
103
|
+
*/
|
|
104
|
+
protected prepareBuild(restRouteProcessors?: IRestRouteProcessor[], restRoutes?: IRestRoute[], socketRouteProcessors?: ISocketRouteProcessor[], socketRoutes?: ISocketRoute[], options?: IWebServerOptions): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Resolve the route processors in to per phase chains, so that the lookups and bindings
|
|
107
|
+
* are performed once when the server is built instead of on every request.
|
|
108
|
+
* @param restRouteProcessors The processors for the incoming REST requests.
|
|
109
|
+
* @param socketRouteProcessors The processors for the incoming socket requests.
|
|
110
|
+
*/
|
|
111
|
+
protected buildProcessorChains(restRouteProcessors?: IRestRouteProcessor[], socketRouteProcessors?: ISocketRouteProcessor[]): void;
|
|
112
|
+
/**
|
|
113
|
+
* Merge the configured body limits over the built-in ones and validate them.
|
|
114
|
+
* @returns The named body limits in bytes.
|
|
115
|
+
* @throws GeneralError If a limit is not a positive integer.
|
|
116
|
+
*/
|
|
117
|
+
protected resolveBodyLimits(): {
|
|
118
|
+
[name: string]: number;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Resolve the CORS options from the web server options, merging in the defaults.
|
|
122
|
+
* @param options The web server options.
|
|
123
|
+
* @returns The resolved CORS options.
|
|
124
|
+
*/
|
|
125
|
+
protected resolveCorsOptions(options?: IWebServerOptions): IServerCorsOptions;
|
|
126
|
+
/**
|
|
127
|
+
* Build the server request from the transport values, the path params and query must already
|
|
128
|
+
* have been decoded by the transport, as decoding them again corrupts values containing %.
|
|
129
|
+
* @param method The request method.
|
|
130
|
+
* @param url The full request url, including the origin.
|
|
131
|
+
* @param body The request body.
|
|
132
|
+
* @param query The request query params.
|
|
133
|
+
* @param pathParams The request path params.
|
|
134
|
+
* @param headers The request headers.
|
|
135
|
+
* @returns The server request.
|
|
136
|
+
*/
|
|
137
|
+
protected buildServerRequest(method: HttpMethod, url: string, body: unknown, query?: IHttpRequestQuery, pathParams?: IHttpRequestPathParams, headers?: IHttpHeaders): IHttpServerRequest;
|
|
138
|
+
/**
|
|
139
|
+
* Validate the processed response before it is sent, so that every transport fails an invalid
|
|
140
|
+
* response in the same way rather than with its own transport specific error.
|
|
141
|
+
* @param httpResponse The processed response.
|
|
142
|
+
* @throws GeneralError If the status code or a header is invalid.
|
|
143
|
+
*/
|
|
144
|
+
protected validateResponse(httpResponse: IHttpResponse): void;
|
|
145
|
+
/**
|
|
146
|
+
* Build the context ids for an incoming request.
|
|
147
|
+
* @param requestOrigin The origin the request was received on.
|
|
148
|
+
* @param headers The request headers.
|
|
149
|
+
* @returns The context ids.
|
|
150
|
+
*/
|
|
151
|
+
protected buildContextIds(requestOrigin: string, headers?: IHttpHeaders): IContextIds;
|
|
152
|
+
/**
|
|
153
|
+
* Run the REST processors for the route.
|
|
154
|
+
* @param restRoute The route to process.
|
|
155
|
+
* @param httpServerRequest The incoming request.
|
|
156
|
+
* @param httpResponse The outgoing response.
|
|
157
|
+
* @param contextIds The context IDs of the request.
|
|
158
|
+
* @param processorState The state handed through the processors.
|
|
159
|
+
*/
|
|
160
|
+
protected runProcessorsRest(restRoute: IRestRoute | undefined, httpServerRequest: IHttpServerRequest, httpResponse: IHttpResponse, contextIds: IContextIds, processorState: {
|
|
161
|
+
[id: string]: unknown;
|
|
162
|
+
}): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Run the socket processors for the route.
|
|
165
|
+
* @param socketRoute The route to process.
|
|
166
|
+
* @param socketServerRequest The incoming request.
|
|
167
|
+
* @param httpResponse The outgoing response.
|
|
168
|
+
* @param contextIds The context IDs of the request.
|
|
169
|
+
* @param processorState The state handed through the processors.
|
|
170
|
+
* @param requestTopic The topic of the request.
|
|
171
|
+
* @param responseEmitter The emitter to send the response on.
|
|
172
|
+
*/
|
|
173
|
+
protected runProcessorsSocket(socketRoute: ISocketRoute, socketServerRequest: ISocketServerRequest, httpResponse: IHttpResponse, contextIds: IContextIds, processorState: {
|
|
174
|
+
[id: string]: unknown;
|
|
175
|
+
}, requestTopic: string, responseEmitter: (topic: string, response: IHttpResponse) => Promise<void>): Promise<void>;
|
|
176
|
+
/**
|
|
177
|
+
* Returns the class name of the component.
|
|
178
|
+
* @returns The class name of the component.
|
|
179
|
+
*/
|
|
180
|
+
abstract className(): string;
|
|
181
|
+
/**
|
|
182
|
+
* Get the web server instance.
|
|
183
|
+
* @returns The web server instance.
|
|
184
|
+
*/
|
|
185
|
+
abstract getInstance(): T;
|
|
186
|
+
/**
|
|
187
|
+
* Build the server.
|
|
188
|
+
* @param restRouteProcessors The processors for incoming requests over REST.
|
|
189
|
+
* @param restRoutes The REST routes.
|
|
190
|
+
* @param socketRouteProcessors The processors for incoming requests over Sockets.
|
|
191
|
+
* @param socketRoutes The socket routes.
|
|
192
|
+
* @param options Options for building the server.
|
|
193
|
+
* @returns A promise that resolves when the server is fully built and ready to start.
|
|
194
|
+
*/
|
|
195
|
+
abstract build(restRouteProcessors?: IRestRouteProcessor[], restRoutes?: IRestRoute[], socketRouteProcessors?: ISocketRouteProcessor[], socketRoutes?: ISocketRoute[], options?: IWebServerOptions): Promise<void>;
|
|
196
|
+
/**
|
|
197
|
+
* Start listening for connections on the transport.
|
|
198
|
+
* @param host The host to bind to.
|
|
199
|
+
* @param port The port to bind to.
|
|
200
|
+
* @returns A promise that resolves when the transport is listening.
|
|
201
|
+
*/
|
|
202
|
+
protected abstract serverListen(host: string, port: number): Promise<void>;
|
|
203
|
+
/**
|
|
204
|
+
* Close the transport and all of its connections.
|
|
205
|
+
* @returns A promise that resolves when the transport has closed.
|
|
206
|
+
*/
|
|
207
|
+
protected abstract serverClose(): Promise<void>;
|
|
208
|
+
/**
|
|
209
|
+
* Get the addresses the transport is bound to.
|
|
210
|
+
* @returns The bound addresses.
|
|
211
|
+
*/
|
|
212
|
+
protected abstract serverAddresses(): {
|
|
213
|
+
address: string;
|
|
214
|
+
family?: string;
|
|
215
|
+
port: number;
|
|
216
|
+
}[];
|
|
217
|
+
/**
|
|
218
|
+
* Whether the transport is serving over TLS.
|
|
219
|
+
* @returns True if the transport is secure.
|
|
220
|
+
*/
|
|
221
|
+
protected abstract serverIsSecure(): boolean;
|
|
222
|
+
/**
|
|
223
|
+
* Whether the transport is currently listening for connections.
|
|
224
|
+
* @returns True if the transport is listening.
|
|
225
|
+
*/
|
|
226
|
+
protected abstract serverIsListening(): boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Whether a GET route is registered for the root path.
|
|
229
|
+
* @returns True if the root route is registered.
|
|
230
|
+
*/
|
|
231
|
+
protected abstract serverHasRootRoute(): boolean;
|
|
232
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IMimeTypeProcessor } from "@3sixty/api-models";
|
|
2
|
+
/**
|
|
3
|
+
* Options for constructing a base server.
|
|
4
|
+
*/
|
|
5
|
+
export interface IBaseServerConstructorOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The type of the logging component to use, defaults to no logging.
|
|
8
|
+
*/
|
|
9
|
+
loggingComponentType?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The mime type processors to use for the request bodies.
|
|
12
|
+
*/
|
|
13
|
+
mimeTypeProcessors?: IMimeTypeProcessor[];
|
|
14
|
+
/**
|
|
15
|
+
* Include the stack with errors.
|
|
16
|
+
* @default false
|
|
17
|
+
*/
|
|
18
|
+
includeErrorStack?: boolean;
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IRestRouteProcessor } from "@3sixty/api-models";
|
|
2
|
+
/**
|
|
3
|
+
* The REST processor phase chains, bound to their processors when the server is built.
|
|
4
|
+
*/
|
|
5
|
+
export interface IRestProcessorChains {
|
|
6
|
+
/**
|
|
7
|
+
* The pre processing phase.
|
|
8
|
+
*/
|
|
9
|
+
pre: NonNullable<IRestRouteProcessor["pre"]>[];
|
|
10
|
+
/**
|
|
11
|
+
* The main processing phase.
|
|
12
|
+
*/
|
|
13
|
+
process: NonNullable<IRestRouteProcessor["process"]>[];
|
|
14
|
+
/**
|
|
15
|
+
* The post processing phase.
|
|
16
|
+
*/
|
|
17
|
+
post: NonNullable<IRestRouteProcessor["post"]>[];
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { HttpMethod } from "@3sixty/web";
|
|
2
|
+
/**
|
|
3
|
+
* The resolved CORS options for a server.
|
|
4
|
+
*/
|
|
5
|
+
export interface IServerCorsOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The allowed origins.
|
|
8
|
+
*/
|
|
9
|
+
origins: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Whether the allowed origins include the wildcard, in which case any origin is allowed.
|
|
12
|
+
*/
|
|
13
|
+
hasWildcardOrigin: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The allowed methods.
|
|
16
|
+
*/
|
|
17
|
+
methods: HttpMethod[];
|
|
18
|
+
/**
|
|
19
|
+
* The allowed headers.
|
|
20
|
+
*/
|
|
21
|
+
allowedHeaders: string[];
|
|
22
|
+
/**
|
|
23
|
+
* The exposed headers.
|
|
24
|
+
*/
|
|
25
|
+
exposedHeaders: string[];
|
|
26
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ISocketRouteProcessor } from "@3sixty/api-models";
|
|
2
|
+
/**
|
|
3
|
+
* The socket processor phase chains, bound to their processors when the server is built.
|
|
4
|
+
*/
|
|
5
|
+
export interface ISocketProcessorChains {
|
|
6
|
+
/**
|
|
7
|
+
* The socket connected phase.
|
|
8
|
+
*/
|
|
9
|
+
connected: NonNullable<ISocketRouteProcessor["connected"]>[];
|
|
10
|
+
/**
|
|
11
|
+
* The socket disconnected phase.
|
|
12
|
+
*/
|
|
13
|
+
disconnected: NonNullable<ISocketRouteProcessor["disconnected"]>[];
|
|
14
|
+
/**
|
|
15
|
+
* The pre processing phase.
|
|
16
|
+
*/
|
|
17
|
+
pre: NonNullable<ISocketRouteProcessor["pre"]>[];
|
|
18
|
+
/**
|
|
19
|
+
* The main processing phase.
|
|
20
|
+
*/
|
|
21
|
+
process: NonNullable<ISocketRouteProcessor["process"]>[];
|
|
22
|
+
/**
|
|
23
|
+
* The post processing phase.
|
|
24
|
+
*/
|
|
25
|
+
post: NonNullable<ISocketRouteProcessor["post"]>[];
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.20.0-next.1](https://github.com/3sixtyglobal/api/compare/api-core-server-v0.20.0-next.0...api-core-server-v0.20.0-next.1) (2026-10-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* authorization ([#51](https://github.com/3sixtyglobal/api/issues/51)) ([023ef94](https://github.com/3sixtyglobal/api/commit/023ef94925114e88522cbe6f703d9b05a202bc6d))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @3sixty/api-models bumped from 0.20.0-next.0 to 0.20.0-next.1
|
|
16
|
+
* @3sixty/api-processors bumped from 0.20.0-next.0 to 0.20.0-next.1
|
package/docs/examples.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Core Server Examples
|
|
2
|
+
|
|
3
|
+
Use these snippets as a starting point when building a web server on a new transport.
|
|
4
|
+
|
|
5
|
+
## BaseServer
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { BaseServer } from '@3sixty/api-core-server';
|
|
9
|
+
import type {
|
|
10
|
+
IRestRoute,
|
|
11
|
+
IRestRouteProcessor,
|
|
12
|
+
ISocketRoute,
|
|
13
|
+
ISocketRouteProcessor,
|
|
14
|
+
IWebServerOptions
|
|
15
|
+
} from '@3sixty/api-models';
|
|
16
|
+
|
|
17
|
+
class MyWebServer extends BaseServer<MyTransport> {
|
|
18
|
+
private readonly _transport: MyTransport;
|
|
19
|
+
|
|
20
|
+
public constructor() {
|
|
21
|
+
super({ loggingComponentType: 'logging' });
|
|
22
|
+
this._transport = new MyTransport();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public className(): string {
|
|
26
|
+
return 'MyWebServer';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public getInstance(): MyTransport {
|
|
30
|
+
return this._transport;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public async build(
|
|
34
|
+
restRouteProcessors?: IRestRouteProcessor[],
|
|
35
|
+
restRoutes?: IRestRoute[],
|
|
36
|
+
socketRouteProcessors?: ISocketRouteProcessor[],
|
|
37
|
+
socketRoutes?: ISocketRoute[],
|
|
38
|
+
options?: IWebServerOptions
|
|
39
|
+
): Promise<void> {
|
|
40
|
+
await this.prepareBuild(
|
|
41
|
+
restRouteProcessors,
|
|
42
|
+
restRoutes,
|
|
43
|
+
socketRouteProcessors,
|
|
44
|
+
socketRoutes,
|
|
45
|
+
options
|
|
46
|
+
);
|
|
47
|
+
// Register the routes on the transport, calling this.runProcessorsRest for each request
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
protected async serverListen(host: string, port: number): Promise<void> {
|
|
51
|
+
await this._transport.listen(host, port);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected async serverClose(): Promise<void> {
|
|
55
|
+
await this._transport.close();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected serverAddresses(): { address: string; family?: string; port: number }[] {
|
|
59
|
+
return this._transport.addresses();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
protected serverIsSecure(): boolean {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
protected serverIsListening(): boolean {
|
|
67
|
+
return this._transport.listening;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
protected serverHasRootRoute(): boolean {
|
|
71
|
+
return this._transport.hasRoute('GET', '/');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const server = new MyWebServer();
|
|
76
|
+
await server.build(restProcessors, restRoutes, undefined, undefined, { port: 3000 });
|
|
77
|
+
await server.start();
|
|
78
|
+
```
|