@mionjs/platform-node 0.8.0-alpha.0 → 0.8.4-alpha.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.
|
@@ -39,6 +39,8 @@ async function startNodeServer(options) {
|
|
|
39
39
|
reject(e);
|
|
40
40
|
});
|
|
41
41
|
server.listen(httpOptions.port, () => {
|
|
42
|
+
const { options: _nativeOpts, ...serializableConfig } = httpOptions;
|
|
43
|
+
router.setPlatformConfig(serializableConfig);
|
|
42
44
|
resolve(server);
|
|
43
45
|
});
|
|
44
46
|
const shutdownHandler = function() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mionHttp.cjs","sources":["../../../src/mionHttp.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {dispatchRoute, getRouterFatalErrorResponse, resetRouter, decodeQueryBody} from '@mionjs/router';\nimport {createServer as createHttp} from 'http';\nimport {createServer as createHttps} from 'https';\nimport {DEFAULT_HTTP_OPTIONS} from './constants.ts';\nimport type {NodeHttpOptions} from './types.ts';\nimport type {IncomingMessage, Server as HttpServer, ServerResponse} from 'http';\nimport type {Server as HttpsServer} from 'https';\nimport type {MionHeaders, MionResponse} from '@mionjs/router';\nimport {getENV, isMionCompileMode, SerializerModes} from '@mionjs/core';\nimport type {SerializerCode} from '@mionjs/core';\nimport {RpcError} from '@mionjs/core';\nimport {headersFromIncomingMessage, headersFromServerResponse} from './headers.ts';\n\n// ############# PRIVATE STATE #############\n\nlet httpOptions: Readonly<NodeHttpOptions> = {...DEFAULT_HTTP_OPTIONS};\n\n// ############# PUBLIC METHODS #############\n\nexport function resetNodeHttpOpts() {\n httpOptions = {...DEFAULT_HTTP_OPTIONS};\n resetRouter();\n}\n\nexport function setNodeHttpOpts(options?: Partial<NodeHttpOptions>) {\n httpOptions = {\n ...httpOptions,\n ...options,\n };\n\n return httpOptions;\n}\n\nexport async function startNodeServer(options?: Partial<NodeHttpOptions>): Promise<HttpServer | HttpsServer> {\n const isTest = getENV('NODE_ENV') === 'test';\n const isCompiling = isMionCompileMode();\n\n if (options) setNodeHttpOpts(options);\n const port = httpOptions.port !== 80 ? `:${httpOptions.port}` : '';\n const url = `${httpOptions.protocol}://localhost${port}`;\n if (!isTest && !isCompiling)\n console.log(`mion node server running on ${url}`, {\n port: httpOptions.port,\n httpOptions,\n });\n\n return new Promise<HttpServer | HttpsServer>((resolve, reject) => {\n const server =\n httpOptions.protocol === 'https'\n ? createHttps(httpOptions.options, httpRequestHandler)\n : createHttp(httpOptions.options, httpRequestHandler);\n\n if (isCompiling) {\n console.log('Compiling routes metadata and skipping mion server initialization...');\n return resolve(server);\n }\n\n server.on('error', (e) => {\n reject(e);\n });\n\n server.listen(httpOptions.port, () => {\n resolve(server);\n });\n\n const shutdownHandler = function () {\n if (!isTest) console.log(`Shutting down mion server on ${url}`);\n server.close(() => {\n process.exit(0);\n });\n };\n\n process.on('SIGINT', shutdownHandler);\n process.on('SIGTERM', shutdownHandler);\n });\n}\n\n// ############# PRIVATE METHODS #############\n\n// exported as can be used in some server to proxy node requests\nexport function httpRequestHandler(httpReq: IncomingMessage, httpResponse: ServerResponse): void {\n let replied = false;\n const nodeUrl = httpReq.url || '/';\n const queryIndex = nodeUrl.indexOf('?');\n const path = queryIndex === -1 ? nodeUrl : nodeUrl.substring(0, queryIndex);\n const urlQuery = queryIndex === -1 ? undefined : nodeUrl.substring(queryIndex + 1);\n let size = 0;\n const bodyChunks: any[] = [];\n\n httpResponse.setHeader('server', '@mionjs');\n const reqHeaders = headersFromIncomingMessage(httpReq);\n const respHeaders = headersFromServerResponse(httpResponse, httpOptions.defaultResponseHeaders);\n\n httpReq.on('data', (data) => {\n bodyChunks.push(data);\n const chunkLength = bodyChunks[bodyChunks.length - 1].length;\n size += chunkLength;\n if (size > httpOptions.maxBodySize && !replied) {\n replied = true;\n const error = new RpcError({\n publicMessage: 'Payload Too Large',\n type: 'request-payload-too-large',\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpReq.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'request-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n\n httpReq.on('end', async () => {\n if (replied) return;\n const buffer = Buffer.concat(bodyChunks);\n const contentType = httpReq.headers['content-type'] || '';\n const isBinary = contentType.startsWith('application/octet-stream');\n let reqRawBody: any = isBinary ? buffer : buffer.toString();\n let reqBodyType: SerializerCode = isBinary ? SerializerModes.binary : SerializerModes.stringifyJson;\n const queryBody = decodeQueryBody(urlQuery, reqRawBody || undefined);\n if (queryBody) {\n reqRawBody = queryBody.rawBody;\n reqBodyType = queryBody.bodyType;\n }\n\n try {\n const mionResponse = await dispatchRoute(\n path,\n reqRawBody,\n reqHeaders,\n respHeaders,\n httpReq,\n httpResponse,\n reqBodyType,\n urlQuery\n );\n if (replied || httpResponse.writableEnded) return;\n replied = true;\n reply(httpResponse, mionResponse);\n } catch (e) {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Unknown Error',\n type: 'unknown-error',\n originalError: e as Error,\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpResponse.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'response-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n}\n\n// only called when there is an http error or weird unhandled route errors\nfunction fatalFail(httpResponse: ServerResponse, respHeaders: MionHeaders, error: RpcError<string>) {\n if (httpResponse.writableEnded) return;\n const routeResponse = getRouterFatalErrorResponse(error, respHeaders);\n reply(httpResponse, routeResponse);\n}\n\nfunction reply(httpResp: ServerResponse, mionResp: MionResponse) {\n httpResp.statusCode = mionResp.statusCode;\n const bodyType = mionResp.serializer;\n switch (bodyType) {\n case SerializerModes.stringifyJson: {\n const buffer = Buffer.from(mionResp.rawBody as string, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n // content-type already set by serializer\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.json: {\n // Platform adapter stringifies the prepared body object\n const jsonString = JSON.stringify(mionResp.body);\n const buffer = Buffer.from(jsonString, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.binary: {\n const serializer = mionResp.binSerializer!;\n httpResp.setHeader('content-length', serializer.getLength());\n // content-type already set by serializer\n httpResp.end(serializer.getBufferView());\n // Release buffer when response is finished\n const onFinish = () => serializer.markAsEnded();\n httpResp.on('finish', onFinish);\n httpResp.on('close', onFinish); // Fallback for aborted connection\n break;\n }\n default: {\n const error = new RpcError({\n publicMessage: 'unknown-mion-response-format',\n type: 'unknown-error',\n errorData: {bodyType},\n });\n fatalFail(httpResp, mionResp.headers, error);\n }\n }\n}\n"],"names":["DEFAULT_HTTP_OPTIONS","resetRouter","getENV","isMionCompileMode","createHttps","createHttp","headersFromIncomingMessage","headersFromServerResponse","RpcError","SerializerModes","decodeQueryBody","dispatchRoute","getRouterFatalErrorResponse"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mionHttp.cjs","sources":["../../../src/mionHttp.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {dispatchRoute, getRouterFatalErrorResponse, resetRouter, decodeQueryBody, setPlatformConfig} from '@mionjs/router';\nimport {createServer as createHttp} from 'http';\nimport {createServer as createHttps} from 'https';\nimport {DEFAULT_HTTP_OPTIONS} from './constants.ts';\nimport type {NodeHttpOptions} from './types.ts';\nimport type {IncomingMessage, Server as HttpServer, ServerResponse} from 'http';\nimport type {Server as HttpsServer} from 'https';\nimport type {MionHeaders, MionResponse} from '@mionjs/router';\nimport {getENV, isMionCompileMode, SerializerModes} from '@mionjs/core';\nimport type {SerializerCode} from '@mionjs/core';\nimport {RpcError} from '@mionjs/core';\nimport {headersFromIncomingMessage, headersFromServerResponse} from './headers.ts';\n\n// ############# PRIVATE STATE #############\n\nlet httpOptions: Readonly<NodeHttpOptions> = {...DEFAULT_HTTP_OPTIONS};\n\n// ############# PUBLIC METHODS #############\n\nexport function resetNodeHttpOpts() {\n httpOptions = {...DEFAULT_HTTP_OPTIONS};\n resetRouter();\n}\n\nexport function setNodeHttpOpts(options?: Partial<NodeHttpOptions>) {\n httpOptions = {\n ...httpOptions,\n ...options,\n };\n\n return httpOptions;\n}\n\nexport async function startNodeServer(options?: Partial<NodeHttpOptions>): Promise<HttpServer | HttpsServer> {\n const isTest = getENV('NODE_ENV') === 'test';\n const isCompiling = isMionCompileMode();\n\n if (options) setNodeHttpOpts(options);\n const port = httpOptions.port !== 80 ? `:${httpOptions.port}` : '';\n const url = `${httpOptions.protocol}://localhost${port}`;\n if (!isTest && !isCompiling)\n console.log(`mion node server running on ${url}`, {\n port: httpOptions.port,\n httpOptions,\n });\n\n return new Promise<HttpServer | HttpsServer>((resolve, reject) => {\n const server =\n httpOptions.protocol === 'https'\n ? createHttps(httpOptions.options, httpRequestHandler)\n : createHttp(httpOptions.options, httpRequestHandler);\n\n if (isCompiling) {\n console.log('Compiling routes metadata and skipping mion server initialization...');\n return resolve(server);\n }\n\n server.on('error', (e) => {\n reject(e);\n });\n\n server.listen(httpOptions.port, () => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {options: _nativeOpts, ...serializableConfig} = httpOptions;\n setPlatformConfig(serializableConfig);\n resolve(server);\n });\n\n const shutdownHandler = function () {\n if (!isTest) console.log(`Shutting down mion server on ${url}`);\n server.close(() => {\n process.exit(0);\n });\n };\n\n process.on('SIGINT', shutdownHandler);\n process.on('SIGTERM', shutdownHandler);\n });\n}\n\n// ############# PRIVATE METHODS #############\n\n// exported as can be used in some server to proxy node requests\nexport function httpRequestHandler(httpReq: IncomingMessage, httpResponse: ServerResponse): void {\n let replied = false;\n const nodeUrl = httpReq.url || '/';\n const queryIndex = nodeUrl.indexOf('?');\n const path = queryIndex === -1 ? nodeUrl : nodeUrl.substring(0, queryIndex);\n const urlQuery = queryIndex === -1 ? undefined : nodeUrl.substring(queryIndex + 1);\n let size = 0;\n const bodyChunks: any[] = [];\n\n httpResponse.setHeader('server', '@mionjs');\n const reqHeaders = headersFromIncomingMessage(httpReq);\n const respHeaders = headersFromServerResponse(httpResponse, httpOptions.defaultResponseHeaders);\n\n httpReq.on('data', (data) => {\n bodyChunks.push(data);\n const chunkLength = bodyChunks[bodyChunks.length - 1].length;\n size += chunkLength;\n if (size > httpOptions.maxBodySize && !replied) {\n replied = true;\n const error = new RpcError({\n publicMessage: 'Payload Too Large',\n type: 'request-payload-too-large',\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpReq.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'request-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n\n httpReq.on('end', async () => {\n if (replied) return;\n const buffer = Buffer.concat(bodyChunks);\n const contentType = httpReq.headers['content-type'] || '';\n const isBinary = contentType.startsWith('application/octet-stream');\n let reqRawBody: any = isBinary ? buffer : buffer.toString();\n let reqBodyType: SerializerCode = isBinary ? SerializerModes.binary : SerializerModes.stringifyJson;\n const queryBody = decodeQueryBody(urlQuery, reqRawBody || undefined);\n if (queryBody) {\n reqRawBody = queryBody.rawBody;\n reqBodyType = queryBody.bodyType;\n }\n\n try {\n const mionResponse = await dispatchRoute(\n path,\n reqRawBody,\n reqHeaders,\n respHeaders,\n httpReq,\n httpResponse,\n reqBodyType,\n urlQuery\n );\n if (replied || httpResponse.writableEnded) return;\n replied = true;\n reply(httpResponse, mionResponse);\n } catch (e) {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Unknown Error',\n type: 'unknown-error',\n originalError: e as Error,\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpResponse.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'response-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n}\n\n// only called when there is an http error or weird unhandled route errors\nfunction fatalFail(httpResponse: ServerResponse, respHeaders: MionHeaders, error: RpcError<string>) {\n if (httpResponse.writableEnded) return;\n const routeResponse = getRouterFatalErrorResponse(error, respHeaders);\n reply(httpResponse, routeResponse);\n}\n\nfunction reply(httpResp: ServerResponse, mionResp: MionResponse) {\n httpResp.statusCode = mionResp.statusCode;\n const bodyType = mionResp.serializer;\n switch (bodyType) {\n case SerializerModes.stringifyJson: {\n const buffer = Buffer.from(mionResp.rawBody as string, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n // content-type already set by serializer\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.json: {\n // Platform adapter stringifies the prepared body object\n const jsonString = JSON.stringify(mionResp.body);\n const buffer = Buffer.from(jsonString, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.binary: {\n const serializer = mionResp.binSerializer!;\n httpResp.setHeader('content-length', serializer.getLength());\n // content-type already set by serializer\n httpResp.end(serializer.getBufferView());\n // Release buffer when response is finished\n const onFinish = () => serializer.markAsEnded();\n httpResp.on('finish', onFinish);\n httpResp.on('close', onFinish); // Fallback for aborted connection\n break;\n }\n default: {\n const error = new RpcError({\n publicMessage: 'unknown-mion-response-format',\n type: 'unknown-error',\n errorData: {bodyType},\n });\n fatalFail(httpResp, mionResp.headers, error);\n }\n }\n}\n"],"names":["DEFAULT_HTTP_OPTIONS","resetRouter","getENV","isMionCompileMode","createHttps","createHttp","setPlatformConfig","headersFromIncomingMessage","headersFromServerResponse","RpcError","SerializerModes","decodeQueryBody","dispatchRoute","getRouterFatalErrorResponse"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { decodeQueryBody, dispatchRoute, resetRouter, getRouterFatalErrorResponse } from "@mionjs/router";
|
|
1
|
+
import { decodeQueryBody, dispatchRoute, resetRouter, setPlatformConfig, getRouterFatalErrorResponse } from "@mionjs/router";
|
|
2
2
|
import { createServer as createServer$1 } from "http";
|
|
3
3
|
import { createServer } from "https";
|
|
4
4
|
import { DEFAULT_HTTP_OPTIONS } from "./constants.js";
|
|
@@ -37,6 +37,8 @@ async function startNodeServer(options) {
|
|
|
37
37
|
reject(e);
|
|
38
38
|
});
|
|
39
39
|
server.listen(httpOptions.port, () => {
|
|
40
|
+
const { options: _nativeOpts, ...serializableConfig } = httpOptions;
|
|
41
|
+
setPlatformConfig(serializableConfig);
|
|
40
42
|
resolve(server);
|
|
41
43
|
});
|
|
42
44
|
const shutdownHandler = function() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mionHttp.js","sources":["../../../src/mionHttp.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {dispatchRoute, getRouterFatalErrorResponse, resetRouter, decodeQueryBody} from '@mionjs/router';\nimport {createServer as createHttp} from 'http';\nimport {createServer as createHttps} from 'https';\nimport {DEFAULT_HTTP_OPTIONS} from './constants.ts';\nimport type {NodeHttpOptions} from './types.ts';\nimport type {IncomingMessage, Server as HttpServer, ServerResponse} from 'http';\nimport type {Server as HttpsServer} from 'https';\nimport type {MionHeaders, MionResponse} from '@mionjs/router';\nimport {getENV, isMionCompileMode, SerializerModes} from '@mionjs/core';\nimport type {SerializerCode} from '@mionjs/core';\nimport {RpcError} from '@mionjs/core';\nimport {headersFromIncomingMessage, headersFromServerResponse} from './headers.ts';\n\n// ############# PRIVATE STATE #############\n\nlet httpOptions: Readonly<NodeHttpOptions> = {...DEFAULT_HTTP_OPTIONS};\n\n// ############# PUBLIC METHODS #############\n\nexport function resetNodeHttpOpts() {\n httpOptions = {...DEFAULT_HTTP_OPTIONS};\n resetRouter();\n}\n\nexport function setNodeHttpOpts(options?: Partial<NodeHttpOptions>) {\n httpOptions = {\n ...httpOptions,\n ...options,\n };\n\n return httpOptions;\n}\n\nexport async function startNodeServer(options?: Partial<NodeHttpOptions>): Promise<HttpServer | HttpsServer> {\n const isTest = getENV('NODE_ENV') === 'test';\n const isCompiling = isMionCompileMode();\n\n if (options) setNodeHttpOpts(options);\n const port = httpOptions.port !== 80 ? `:${httpOptions.port}` : '';\n const url = `${httpOptions.protocol}://localhost${port}`;\n if (!isTest && !isCompiling)\n console.log(`mion node server running on ${url}`, {\n port: httpOptions.port,\n httpOptions,\n });\n\n return new Promise<HttpServer | HttpsServer>((resolve, reject) => {\n const server =\n httpOptions.protocol === 'https'\n ? createHttps(httpOptions.options, httpRequestHandler)\n : createHttp(httpOptions.options, httpRequestHandler);\n\n if (isCompiling) {\n console.log('Compiling routes metadata and skipping mion server initialization...');\n return resolve(server);\n }\n\n server.on('error', (e) => {\n reject(e);\n });\n\n server.listen(httpOptions.port, () => {\n resolve(server);\n });\n\n const shutdownHandler = function () {\n if (!isTest) console.log(`Shutting down mion server on ${url}`);\n server.close(() => {\n process.exit(0);\n });\n };\n\n process.on('SIGINT', shutdownHandler);\n process.on('SIGTERM', shutdownHandler);\n });\n}\n\n// ############# PRIVATE METHODS #############\n\n// exported as can be used in some server to proxy node requests\nexport function httpRequestHandler(httpReq: IncomingMessage, httpResponse: ServerResponse): void {\n let replied = false;\n const nodeUrl = httpReq.url || '/';\n const queryIndex = nodeUrl.indexOf('?');\n const path = queryIndex === -1 ? nodeUrl : nodeUrl.substring(0, queryIndex);\n const urlQuery = queryIndex === -1 ? undefined : nodeUrl.substring(queryIndex + 1);\n let size = 0;\n const bodyChunks: any[] = [];\n\n httpResponse.setHeader('server', '@mionjs');\n const reqHeaders = headersFromIncomingMessage(httpReq);\n const respHeaders = headersFromServerResponse(httpResponse, httpOptions.defaultResponseHeaders);\n\n httpReq.on('data', (data) => {\n bodyChunks.push(data);\n const chunkLength = bodyChunks[bodyChunks.length - 1].length;\n size += chunkLength;\n if (size > httpOptions.maxBodySize && !replied) {\n replied = true;\n const error = new RpcError({\n publicMessage: 'Payload Too Large',\n type: 'request-payload-too-large',\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpReq.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'request-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n\n httpReq.on('end', async () => {\n if (replied) return;\n const buffer = Buffer.concat(bodyChunks);\n const contentType = httpReq.headers['content-type'] || '';\n const isBinary = contentType.startsWith('application/octet-stream');\n let reqRawBody: any = isBinary ? buffer : buffer.toString();\n let reqBodyType: SerializerCode = isBinary ? SerializerModes.binary : SerializerModes.stringifyJson;\n const queryBody = decodeQueryBody(urlQuery, reqRawBody || undefined);\n if (queryBody) {\n reqRawBody = queryBody.rawBody;\n reqBodyType = queryBody.bodyType;\n }\n\n try {\n const mionResponse = await dispatchRoute(\n path,\n reqRawBody,\n reqHeaders,\n respHeaders,\n httpReq,\n httpResponse,\n reqBodyType,\n urlQuery\n );\n if (replied || httpResponse.writableEnded) return;\n replied = true;\n reply(httpResponse, mionResponse);\n } catch (e) {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Unknown Error',\n type: 'unknown-error',\n originalError: e as Error,\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpResponse.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'response-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n}\n\n// only called when there is an http error or weird unhandled route errors\nfunction fatalFail(httpResponse: ServerResponse, respHeaders: MionHeaders, error: RpcError<string>) {\n if (httpResponse.writableEnded) return;\n const routeResponse = getRouterFatalErrorResponse(error, respHeaders);\n reply(httpResponse, routeResponse);\n}\n\nfunction reply(httpResp: ServerResponse, mionResp: MionResponse) {\n httpResp.statusCode = mionResp.statusCode;\n const bodyType = mionResp.serializer;\n switch (bodyType) {\n case SerializerModes.stringifyJson: {\n const buffer = Buffer.from(mionResp.rawBody as string, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n // content-type already set by serializer\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.json: {\n // Platform adapter stringifies the prepared body object\n const jsonString = JSON.stringify(mionResp.body);\n const buffer = Buffer.from(jsonString, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.binary: {\n const serializer = mionResp.binSerializer!;\n httpResp.setHeader('content-length', serializer.getLength());\n // content-type already set by serializer\n httpResp.end(serializer.getBufferView());\n // Release buffer when response is finished\n const onFinish = () => serializer.markAsEnded();\n httpResp.on('finish', onFinish);\n httpResp.on('close', onFinish); // Fallback for aborted connection\n break;\n }\n default: {\n const error = new RpcError({\n publicMessage: 'unknown-mion-response-format',\n type: 'unknown-error',\n errorData: {bodyType},\n });\n fatalFail(httpResp, mionResp.headers, error);\n }\n }\n}\n"],"names":["createHttps","createHttp"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mionHttp.js","sources":["../../../src/mionHttp.ts"],"sourcesContent":["/* ########\n * 2022 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport {dispatchRoute, getRouterFatalErrorResponse, resetRouter, decodeQueryBody, setPlatformConfig} from '@mionjs/router';\nimport {createServer as createHttp} from 'http';\nimport {createServer as createHttps} from 'https';\nimport {DEFAULT_HTTP_OPTIONS} from './constants.ts';\nimport type {NodeHttpOptions} from './types.ts';\nimport type {IncomingMessage, Server as HttpServer, ServerResponse} from 'http';\nimport type {Server as HttpsServer} from 'https';\nimport type {MionHeaders, MionResponse} from '@mionjs/router';\nimport {getENV, isMionCompileMode, SerializerModes} from '@mionjs/core';\nimport type {SerializerCode} from '@mionjs/core';\nimport {RpcError} from '@mionjs/core';\nimport {headersFromIncomingMessage, headersFromServerResponse} from './headers.ts';\n\n// ############# PRIVATE STATE #############\n\nlet httpOptions: Readonly<NodeHttpOptions> = {...DEFAULT_HTTP_OPTIONS};\n\n// ############# PUBLIC METHODS #############\n\nexport function resetNodeHttpOpts() {\n httpOptions = {...DEFAULT_HTTP_OPTIONS};\n resetRouter();\n}\n\nexport function setNodeHttpOpts(options?: Partial<NodeHttpOptions>) {\n httpOptions = {\n ...httpOptions,\n ...options,\n };\n\n return httpOptions;\n}\n\nexport async function startNodeServer(options?: Partial<NodeHttpOptions>): Promise<HttpServer | HttpsServer> {\n const isTest = getENV('NODE_ENV') === 'test';\n const isCompiling = isMionCompileMode();\n\n if (options) setNodeHttpOpts(options);\n const port = httpOptions.port !== 80 ? `:${httpOptions.port}` : '';\n const url = `${httpOptions.protocol}://localhost${port}`;\n if (!isTest && !isCompiling)\n console.log(`mion node server running on ${url}`, {\n port: httpOptions.port,\n httpOptions,\n });\n\n return new Promise<HttpServer | HttpsServer>((resolve, reject) => {\n const server =\n httpOptions.protocol === 'https'\n ? createHttps(httpOptions.options, httpRequestHandler)\n : createHttp(httpOptions.options, httpRequestHandler);\n\n if (isCompiling) {\n console.log('Compiling routes metadata and skipping mion server initialization...');\n return resolve(server);\n }\n\n server.on('error', (e) => {\n reject(e);\n });\n\n server.listen(httpOptions.port, () => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {options: _nativeOpts, ...serializableConfig} = httpOptions;\n setPlatformConfig(serializableConfig);\n resolve(server);\n });\n\n const shutdownHandler = function () {\n if (!isTest) console.log(`Shutting down mion server on ${url}`);\n server.close(() => {\n process.exit(0);\n });\n };\n\n process.on('SIGINT', shutdownHandler);\n process.on('SIGTERM', shutdownHandler);\n });\n}\n\n// ############# PRIVATE METHODS #############\n\n// exported as can be used in some server to proxy node requests\nexport function httpRequestHandler(httpReq: IncomingMessage, httpResponse: ServerResponse): void {\n let replied = false;\n const nodeUrl = httpReq.url || '/';\n const queryIndex = nodeUrl.indexOf('?');\n const path = queryIndex === -1 ? nodeUrl : nodeUrl.substring(0, queryIndex);\n const urlQuery = queryIndex === -1 ? undefined : nodeUrl.substring(queryIndex + 1);\n let size = 0;\n const bodyChunks: any[] = [];\n\n httpResponse.setHeader('server', '@mionjs');\n const reqHeaders = headersFromIncomingMessage(httpReq);\n const respHeaders = headersFromServerResponse(httpResponse, httpOptions.defaultResponseHeaders);\n\n httpReq.on('data', (data) => {\n bodyChunks.push(data);\n const chunkLength = bodyChunks[bodyChunks.length - 1].length;\n size += chunkLength;\n if (size > httpOptions.maxBodySize && !replied) {\n replied = true;\n const error = new RpcError({\n publicMessage: 'Payload Too Large',\n type: 'request-payload-too-large',\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpReq.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'request-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n\n httpReq.on('end', async () => {\n if (replied) return;\n const buffer = Buffer.concat(bodyChunks);\n const contentType = httpReq.headers['content-type'] || '';\n const isBinary = contentType.startsWith('application/octet-stream');\n let reqRawBody: any = isBinary ? buffer : buffer.toString();\n let reqBodyType: SerializerCode = isBinary ? SerializerModes.binary : SerializerModes.stringifyJson;\n const queryBody = decodeQueryBody(urlQuery, reqRawBody || undefined);\n if (queryBody) {\n reqRawBody = queryBody.rawBody;\n reqBodyType = queryBody.bodyType;\n }\n\n try {\n const mionResponse = await dispatchRoute(\n path,\n reqRawBody,\n reqHeaders,\n respHeaders,\n httpReq,\n httpResponse,\n reqBodyType,\n urlQuery\n );\n if (replied || httpResponse.writableEnded) return;\n replied = true;\n reply(httpResponse, mionResponse);\n } catch (e) {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Unknown Error',\n type: 'unknown-error',\n originalError: e as Error,\n });\n fatalFail(httpResponse, respHeaders, error);\n }\n });\n\n httpResponse.on('error', (e) => {\n if (replied) return;\n replied = true;\n const error = new RpcError({\n publicMessage: 'Connection Error',\n type: 'response-connection-error',\n originalError: e,\n });\n fatalFail(httpResponse, respHeaders, error);\n });\n}\n\n// only called when there is an http error or weird unhandled route errors\nfunction fatalFail(httpResponse: ServerResponse, respHeaders: MionHeaders, error: RpcError<string>) {\n if (httpResponse.writableEnded) return;\n const routeResponse = getRouterFatalErrorResponse(error, respHeaders);\n reply(httpResponse, routeResponse);\n}\n\nfunction reply(httpResp: ServerResponse, mionResp: MionResponse) {\n httpResp.statusCode = mionResp.statusCode;\n const bodyType = mionResp.serializer;\n switch (bodyType) {\n case SerializerModes.stringifyJson: {\n const buffer = Buffer.from(mionResp.rawBody as string, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n // content-type already set by serializer\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.json: {\n // Platform adapter stringifies the prepared body object\n const jsonString = JSON.stringify(mionResp.body);\n const buffer = Buffer.from(jsonString, 'utf8');\n httpResp.setHeader('content-length', buffer.byteLength);\n httpResp.end(buffer);\n break;\n }\n case SerializerModes.binary: {\n const serializer = mionResp.binSerializer!;\n httpResp.setHeader('content-length', serializer.getLength());\n // content-type already set by serializer\n httpResp.end(serializer.getBufferView());\n // Release buffer when response is finished\n const onFinish = () => serializer.markAsEnded();\n httpResp.on('finish', onFinish);\n httpResp.on('close', onFinish); // Fallback for aborted connection\n break;\n }\n default: {\n const error = new RpcError({\n publicMessage: 'unknown-mion-response-format',\n type: 'unknown-error',\n errorData: {bodyType},\n });\n fatalFail(httpResp, mionResp.headers, error);\n }\n }\n}\n"],"names":["createHttps","createHttp"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mionjs/platform-node",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4-alpha.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "mion HTTP Server for quick Api development.",
|
|
6
6
|
"keywords": [
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"url": "https://github.com/MionKit/mion/issues"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@mionjs/core": "^0.8.
|
|
57
|
-
"@mionjs/router": "^0.8.
|
|
56
|
+
"@mionjs/core": "^0.8.4-alpha.0",
|
|
57
|
+
"@mionjs/router": "^0.8.4-alpha.0"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "26f07a965e43529d4255e6f2ac8a633513026314"
|
|
60
60
|
}
|