@nmtjs/http-transport 0.0.1 → 0.0.2

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.
@@ -45,11 +45,13 @@ export class HttpTransportServer {
45
45
  type: this.transportType,
46
46
  subscriptions: new Map()
47
47
  });
48
+ const responseHeaders = new Headers();
48
49
  container.provide(connectionData, {
49
50
  query: requestData.query,
50
51
  headers: requestData.headers,
51
52
  proxiedRemoteAddress: Buffer.from(res.getProxiedRemoteAddressAsText()).toString(),
52
- remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString()
53
+ remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString(),
54
+ responseHeaders
53
55
  });
54
56
  container.provide(providers.connection, connection);
55
57
  container.provide(providers.signal, ac.signal);
@@ -63,10 +65,14 @@ export class HttpTransportServer {
63
65
  signal: ac.signal,
64
66
  payload
65
67
  });
66
- tryEnd(()=>res.writeStatus('200 OK').writeHeader('Content-Type', format.encoder.contentType).end(format.encoder.encode({
68
+ tryEnd(()=>{
69
+ res.writeStatus('200 OK').writeHeader('Content-Type', format.encoder.contentType);
70
+ responseHeaders.forEach((v, k)=>res.writeHeader(k, v));
71
+ res.end(format.encoder.encode({
67
72
  error: null,
68
73
  result: response
69
- })));
74
+ }));
75
+ });
70
76
  } catch (error) {
71
77
  if (error instanceof ApiError) {
72
78
  tryEnd(()=>res.writeStatus('200 OK').end(format.encoder.encode({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../lib/server.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { once } from 'node:events'\nimport {\n type AnyProcedure,\n ApiError,\n type ApplicationContext,\n type Connection,\n type Container,\n Scope,\n ServerDownStream,\n ServerUpStream,\n type Service,\n SubscriptionResponse,\n onAbort,\n providers,\n} from '@nmtjs/application'\nimport {\n type ApiBlobMetadata,\n type EncodeRpcContext,\n MessageType,\n TransportType,\n decodeNumber,\n encodeNumber,\n} from '@nmtjs/common'\nimport {\n App,\n type HttpResponse,\n SSLApp,\n type TemplatedApp,\n} from 'uWebSockets.js'\nimport { connectionData } from './providers.ts'\nimport type { HttpTransportOptions } from './types.ts'\nimport { InternalError, getFormat, getRequestData } from './utils.ts'\n\nexport class HttpTransportServer {\n protected server!: TemplatedApp\n protected readonly transportType = TransportType.HTTP\n\n constructor(\n protected readonly application: ApplicationContext,\n protected readonly options: HttpTransportOptions,\n ) {\n this.server = this.options.tls ? SSLApp(options.tls!) : App()\n\n this.server\n .get('/healthy', (res) => {\n res.cork(() => {\n // cors\n res.writeHeader('Access-Control-Allow-Origin', '*')\n res.writeHeader('Access-Control-Allow-Headers', 'Content-Type')\n res.writeHeader('Access-Control-Allow-Methods', 'GET')\n res.writeHeader('Content-Type', 'text/plain')\n res.end('OK')\n })\n })\n .post('/api/:service/:procudure', async (res, req) => {\n const ac = new AbortController()\n res.onAborted(() => ac.abort())\n const tryEnd = (cb) => {\n if (!ac.signal.aborted) res.cork(cb)\n }\n\n try {\n const requestData = getRequestData(req)\n\n const serviceName = req.getParameter(0)!\n const procedureName = req.getParameter(1)!\n\n const service = this.application.registry.services.get(serviceName)\n\n if (!service) throw new Error(`Service ${serviceName} not found`)\n if (this.transportType in service.contract.transports === false)\n throw new Error(`Service ${serviceName} not supported`)\n\n const format = getFormat(requestData, this.application.format)\n const body = await this.getBody(res)\n const container = this.application.container.createScope(Scope.Call)\n const payload = body.byteLength ? format.decoder.decode(body) : null\n const connection = this.application.connections.add({\n services: [serviceName],\n type: this.transportType,\n subscriptions: new Map(),\n })\n\n container.provide(connectionData, {\n query: requestData.query,\n headers: requestData.headers,\n proxiedRemoteAddress: Buffer.from(\n res.getProxiedRemoteAddressAsText(),\n ).toString(),\n remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString(),\n })\n container.provide(providers.connection, connection)\n container.provide(providers.signal, ac.signal)\n\n const { procedure } = this.api.find(\n serviceName,\n procedureName,\n this.transportType,\n )\n\n try {\n const response = await this.handleRPC({\n connection,\n service,\n procedure,\n container,\n signal: ac.signal,\n payload,\n })\n\n tryEnd(() =>\n res\n .writeStatus('200 OK')\n .writeHeader('Content-Type', format.encoder.contentType)\n .end(format.encoder.encode({ error: null, result: response })),\n )\n } catch (error: any) {\n if (error instanceof ApiError) {\n tryEnd(() =>\n res\n .writeStatus('200 OK')\n .end(format.encoder.encode({ error, result: null })),\n )\n } else {\n tryEnd(() =>\n res.writeStatus('200 OK').end(\n format.encoder.encode({\n error: InternalError(),\n result: null,\n }),\n ),\n )\n }\n this.logError(error)\n } finally {\n this.application.connections.remove(connection)\n this.handleContainerDisposal(container)\n }\n } catch (error: any) {\n this.logError(error)\n tryEnd(() =>\n res.writeStatus('500 Internal Server Error').endWithoutBody(),\n )\n }\n })\n }\n\n async start() {\n return new Promise<void>((resolve, reject) => {\n const hostname = this.options.hostname ?? '127.0.0.1'\n this.server.listen(hostname, this.options.port!, (socket) => {\n if (socket) {\n this.logger.info(\n 'Server started on %s:%s',\n hostname,\n this.options.port!,\n )\n resolve()\n } else {\n reject(new Error('Failed to start server'))\n }\n })\n })\n }\n\n async stop() {\n this.server.close()\n }\n\n protected get api() {\n return this.application.api\n }\n\n protected get logger() {\n return this.application.logger\n }\n\n protected async logError(\n cause: Error,\n message = 'Unknown error while processing request',\n ) {\n this.logger.error(new Error(message, { cause }))\n }\n\n protected handleContainerDisposal(container: Container) {\n container.dispose()\n }\n\n protected async handleRPC(options: {\n connection: Connection\n service: Service\n procedure: AnyProcedure\n container: Container\n signal: AbortSignal\n payload: any\n }) {\n return await this.api.call({\n ...options,\n transport: this.transportType,\n })\n }\n\n protected async getBody(res: HttpResponse) {\n return new Promise<Buffer>((resolve) => {\n const chunks: Buffer[] = []\n res.onData((chunk, isLast) => {\n chunks.push(Buffer.from(chunk))\n if (isLast) {\n resolve(Buffer.concat(chunks))\n }\n })\n })\n }\n}\n"],"names":["ApiError","Scope","providers","TransportType","App","SSLApp","connectionData","InternalError","getFormat","getRequestData","HttpTransportServer","server","transportType","constructor","application","options","HTTP","tls","get","res","cork","writeHeader","end","post","req","ac","AbortController","onAborted","abort","tryEnd","cb","signal","aborted","requestData","serviceName","getParameter","procedureName","service","registry","services","Error","contract","transports","format","body","getBody","container","createScope","Call","payload","byteLength","decoder","decode","connection","connections","add","type","subscriptions","Map","provide","query","headers","proxiedRemoteAddress","Buffer","from","getProxiedRemoteAddressAsText","toString","remoteAddress","getRemoteAddressAsText","procedure","api","find","response","handleRPC","writeStatus","encoder","contentType","encode","error","result","logError","remove","handleContainerDisposal","endWithoutBody","start","Promise","resolve","reject","hostname","listen","port","socket","logger","info","stop","close","cause","message","dispose","call","transport","chunks","onData","chunk","isLast","push","concat"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../lib/server.ts"],"sourcesContent":["import {\n type AnyProcedure,\n ApiError,\n type ApplicationContext,\n type Connection,\n type Container,\n Scope,\n type Service,\n providers,\n} from '@nmtjs/application'\nimport { TransportType } from '@nmtjs/common'\nimport {\n App,\n type HttpResponse,\n SSLApp,\n type TemplatedApp,\n} from 'uWebSockets.js'\nimport { connectionData } from './providers.ts'\nimport type { HttpTransportOptions } from './types.ts'\nimport { InternalError, getFormat, getRequestData } from './utils.ts'\n\nexport class HttpTransportServer {\n protected server!: TemplatedApp\n protected readonly transportType = TransportType.HTTP\n\n constructor(\n protected readonly application: ApplicationContext,\n protected readonly options: HttpTransportOptions,\n ) {\n this.server = this.options.tls ? SSLApp(options.tls!) : App()\n\n this.server\n .get('/healthy', (res) => {\n res.cork(() => {\n // cors\n res.writeHeader('Access-Control-Allow-Origin', '*')\n res.writeHeader('Access-Control-Allow-Headers', 'Content-Type')\n res.writeHeader('Access-Control-Allow-Methods', 'GET')\n res.writeHeader('Content-Type', 'text/plain')\n res.end('OK')\n })\n })\n .post('/api/:service/:procudure', async (res, req) => {\n const ac = new AbortController()\n res.onAborted(() => ac.abort())\n const tryEnd = (cb) => {\n if (!ac.signal.aborted) res.cork(cb)\n }\n\n try {\n const requestData = getRequestData(req)\n\n const serviceName = req.getParameter(0)!\n const procedureName = req.getParameter(1)!\n\n const service = this.application.registry.services.get(serviceName)\n\n if (!service) throw new Error(`Service ${serviceName} not found`)\n if (this.transportType in service.contract.transports === false)\n throw new Error(`Service ${serviceName} not supported`)\n\n const format = getFormat(requestData, this.application.format)\n const body = await this.getBody(res)\n const container = this.application.container.createScope(Scope.Call)\n const payload = body.byteLength ? format.decoder.decode(body) : null\n const connection = this.application.connections.add({\n services: [serviceName],\n type: this.transportType,\n subscriptions: new Map(),\n })\n\n const responseHeaders = new Headers()\n\n container.provide(connectionData, {\n query: requestData.query,\n headers: requestData.headers,\n proxiedRemoteAddress: Buffer.from(\n res.getProxiedRemoteAddressAsText(),\n ).toString(),\n remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString(),\n responseHeaders,\n })\n container.provide(providers.connection, connection)\n container.provide(providers.signal, ac.signal)\n\n const { procedure } = this.api.find(\n serviceName,\n procedureName,\n this.transportType,\n )\n\n try {\n const response = await this.handleRPC({\n connection,\n service,\n procedure,\n container,\n signal: ac.signal,\n payload,\n })\n\n tryEnd(() => {\n res\n .writeStatus('200 OK')\n .writeHeader('Content-Type', format.encoder.contentType)\n responseHeaders.forEach((v, k) => res.writeHeader(k, v))\n res.end(format.encoder.encode({ error: null, result: response }))\n })\n } catch (error: any) {\n if (error instanceof ApiError) {\n tryEnd(() =>\n res\n .writeStatus('200 OK')\n .end(format.encoder.encode({ error, result: null })),\n )\n } else {\n tryEnd(() =>\n res.writeStatus('200 OK').end(\n format.encoder.encode({\n error: InternalError(),\n result: null,\n }),\n ),\n )\n }\n this.logError(error)\n } finally {\n this.application.connections.remove(connection)\n this.handleContainerDisposal(container)\n }\n } catch (error: any) {\n this.logError(error)\n tryEnd(() =>\n res.writeStatus('500 Internal Server Error').endWithoutBody(),\n )\n }\n })\n }\n\n async start() {\n return new Promise<void>((resolve, reject) => {\n const hostname = this.options.hostname ?? '127.0.0.1'\n this.server.listen(hostname, this.options.port!, (socket) => {\n if (socket) {\n this.logger.info(\n 'Server started on %s:%s',\n hostname,\n this.options.port!,\n )\n resolve()\n } else {\n reject(new Error('Failed to start server'))\n }\n })\n })\n }\n\n async stop() {\n this.server.close()\n }\n\n protected get api() {\n return this.application.api\n }\n\n protected get logger() {\n return this.application.logger\n }\n\n protected async logError(\n cause: Error,\n message = 'Unknown error while processing request',\n ) {\n this.logger.error(new Error(message, { cause }))\n }\n\n protected handleContainerDisposal(container: Container) {\n container.dispose()\n }\n\n protected async handleRPC(options: {\n connection: Connection\n service: Service\n procedure: AnyProcedure\n container: Container\n signal: AbortSignal\n payload: any\n }) {\n return await this.api.call({\n ...options,\n transport: this.transportType,\n })\n }\n\n protected async getBody(res: HttpResponse) {\n return new Promise<Buffer>((resolve) => {\n const chunks: Buffer[] = []\n res.onData((chunk, isLast) => {\n chunks.push(Buffer.from(chunk))\n if (isLast) {\n resolve(Buffer.concat(chunks))\n }\n })\n })\n }\n}\n"],"names":["ApiError","Scope","providers","TransportType","App","SSLApp","connectionData","InternalError","getFormat","getRequestData","HttpTransportServer","server","transportType","constructor","application","options","HTTP","tls","get","res","cork","writeHeader","end","post","req","ac","AbortController","onAborted","abort","tryEnd","cb","signal","aborted","requestData","serviceName","getParameter","procedureName","service","registry","services","Error","contract","transports","format","body","getBody","container","createScope","Call","payload","byteLength","decoder","decode","connection","connections","add","type","subscriptions","Map","responseHeaders","Headers","provide","query","headers","proxiedRemoteAddress","Buffer","from","getProxiedRemoteAddressAsText","toString","remoteAddress","getRemoteAddressAsText","procedure","api","find","response","handleRPC","writeStatus","encoder","contentType","forEach","v","k","encode","error","result","logError","remove","handleContainerDisposal","endWithoutBody","start","Promise","resolve","reject","hostname","listen","port","socket","logger","info","stop","close","cause","message","dispose","call","transport","chunks","onData","chunk","isLast","push","concat"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../lib/types.ts"],"sourcesContent":["import type { AppOptions } from 'uWebSockets.js'\n\nexport type HttpTransportOptions = {\n port?: number\n hostname?: string\n unix?: string\n tls?: AppOptions\n maxPayloadLength?: number\n maxStreamChunkLength?: number\n}\n\nexport type HttpConnectionData = {\n headers: Map<string, string>\n query: URLSearchParams\n remoteAddress: string\n proxiedRemoteAddress: string\n}\n"],"names":[],"mappings":"AAWA,WAKC"}
1
+ {"version":3,"sources":["../../../lib/types.ts"],"sourcesContent":["import type { AppOptions } from 'uWebSockets.js'\n\nexport type HttpTransportOptions = {\n port?: number\n hostname?: string\n unix?: string\n tls?: AppOptions\n maxPayloadLength?: number\n maxStreamChunkLength?: number\n}\n\nexport type HttpConnectionData = {\n headers: Map<string, string>\n query: URLSearchParams\n remoteAddress: string\n proxiedRemoteAddress: string\n responseHeaders: Headers\n}\n"],"names":[],"mappings":"AAWA,WAMC"}
package/lib/server.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { randomUUID } from 'node:crypto'
2
- import { once } from 'node:events'
3
1
  import {
4
2
  type AnyProcedure,
5
3
  ApiError,
@@ -7,21 +5,10 @@ import {
7
5
  type Connection,
8
6
  type Container,
9
7
  Scope,
10
- ServerDownStream,
11
- ServerUpStream,
12
8
  type Service,
13
- SubscriptionResponse,
14
- onAbort,
15
9
  providers,
16
10
  } from '@nmtjs/application'
17
- import {
18
- type ApiBlobMetadata,
19
- type EncodeRpcContext,
20
- MessageType,
21
- TransportType,
22
- decodeNumber,
23
- encodeNumber,
24
- } from '@nmtjs/common'
11
+ import { TransportType } from '@nmtjs/common'
25
12
  import {
26
13
  App,
27
14
  type HttpResponse,
@@ -82,6 +69,8 @@ export class HttpTransportServer {
82
69
  subscriptions: new Map(),
83
70
  })
84
71
 
72
+ const responseHeaders = new Headers()
73
+
85
74
  container.provide(connectionData, {
86
75
  query: requestData.query,
87
76
  headers: requestData.headers,
@@ -89,6 +78,7 @@ export class HttpTransportServer {
89
78
  res.getProxiedRemoteAddressAsText(),
90
79
  ).toString(),
91
80
  remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString(),
81
+ responseHeaders,
92
82
  })
93
83
  container.provide(providers.connection, connection)
94
84
  container.provide(providers.signal, ac.signal)
@@ -109,12 +99,13 @@ export class HttpTransportServer {
109
99
  payload,
110
100
  })
111
101
 
112
- tryEnd(() =>
102
+ tryEnd(() => {
113
103
  res
114
104
  .writeStatus('200 OK')
115
105
  .writeHeader('Content-Type', format.encoder.contentType)
116
- .end(format.encoder.encode({ error: null, result: response })),
117
- )
106
+ responseHeaders.forEach((v, k) => res.writeHeader(k, v))
107
+ res.end(format.encoder.encode({ error: null, result: response }))
108
+ })
118
109
  } catch (error: any) {
119
110
  if (error instanceof ApiError) {
120
111
  tryEnd(() =>
package/lib/types.ts CHANGED
@@ -14,4 +14,5 @@ export type HttpConnectionData = {
14
14
  query: URLSearchParams
15
15
  remoteAddress: string
16
16
  proxiedRemoteAddress: string
17
+ responseHeaders: Headers
17
18
  }
package/package.json CHANGED
@@ -29,7 +29,7 @@
29
29
  "LICENSE.md",
30
30
  "README.md"
31
31
  ],
32
- "version": "0.0.1",
32
+ "version": "0.0.2",
33
33
  "scripts": {
34
34
  "build": "neemata-build ./index.ts './lib/**/*.ts'",
35
35
  "type-check": "tsc --noEmit"