@litert/televoke 0.4.4 → 0.4.6
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/CHANGES.md +12 -0
- package/lib/Client/Common.d.ts +1 -1
- package/lib/Client/Common.d.ts.map +1 -1
- package/lib/Client/HttpClient.d.ts.map +1 -1
- package/lib/Client/HttpClient.js +17 -9
- package/lib/Client/HttpClient.js.map +1 -1
- package/lib/Client/HttpsClient.d.ts.map +1 -1
- package/lib/Client/HttpsClient.js +17 -9
- package/lib/Client/HttpsClient.js.map +1 -1
- package/lib/Client/TCPClient.d.ts +5 -0
- package/lib/Client/TCPClient.d.ts.map +1 -1
- package/lib/Client/TCPClient.js +8 -4
- package/lib/Client/TCPClient.js.map +1 -1
- package/lib/Client/TLSClient.d.ts.map +1 -1
- package/lib/Client/TLSClient.js +3 -4
- package/lib/Client/TLSClient.js.map +1 -1
- package/lib/Client/index.js +5 -1
- package/lib/Client/index.js.map +1 -1
- package/lib/Common/API.d.ts +1 -1
- package/lib/Common/API.d.ts.map +1 -1
- package/lib/Common/Request.d.ts +1 -1
- package/lib/Common/Request.d.ts.map +1 -1
- package/lib/Common/Response.js +1 -1
- package/lib/Common/Response.js.map +1 -1
- package/lib/Common/index.js +5 -1
- package/lib/Common/index.js.map +1 -1
- package/lib/Encoder/Decoder.d.ts.map +1 -1
- package/lib/Encoder/Decoder.js +23 -13
- package/lib/Encoder/Decoder.js.map +1 -1
- package/lib/Encoder/Encoder.d.ts.map +1 -1
- package/lib/Encoder/Encoder.js +4 -4
- package/lib/Encoder/Encoder.js.map +1 -1
- package/lib/Server/Common/Gateway.d.ts +3 -1
- package/lib/Server/Common/Gateway.d.ts.map +1 -1
- package/lib/Server/Common/Request.d.ts +2 -1
- package/lib/Server/Common/Request.d.ts.map +1 -1
- package/lib/Server/Common/Router.d.ts +2 -2
- package/lib/Server/Common/Router.d.ts.map +1 -1
- package/lib/Server/Common/Server.d.ts +6 -0
- package/lib/Server/Common/Server.d.ts.map +1 -1
- package/lib/Server/Common/index.js +5 -1
- package/lib/Server/Common/index.js.map +1 -1
- package/lib/Server/Errors.d.ts +1 -0
- package/lib/Server/Errors.d.ts.map +1 -1
- package/lib/Server/Errors.js +7 -1
- package/lib/Server/Errors.js.map +1 -1
- package/lib/Server/Gateways/Http.d.ts +1 -1
- package/lib/Server/Gateways/Http.d.ts.map +1 -1
- package/lib/Server/Gateways/Http.js +30 -13
- package/lib/Server/Gateways/Http.js.map +1 -1
- package/lib/Server/Gateways/TCP.d.ts +6 -1
- package/lib/Server/Gateways/TCP.d.ts.map +1 -1
- package/lib/Server/Gateways/TCP.js +19 -9
- package/lib/Server/Gateways/TCP.js.map +1 -1
- package/lib/Server/Server.d.ts.map +1 -1
- package/lib/Server/Server.js +30 -16
- package/lib/Server/Server.js.map +1 -1
- package/lib/Server/index.js +5 -1
- package/lib/Server/index.js.map +1 -1
- package/lib/index.js +5 -1
- package/lib/index.js.map +1 -1
- package/package.json +7 -9
- package/src/lib/Client/Common.ts +2 -1
- package/src/lib/Client/HttpClient.ts +19 -16
- package/src/lib/Client/HttpsClient.ts +19 -16
- package/src/lib/Client/TCPClient.ts +16 -12
- package/src/lib/Client/TLSClient.ts +12 -13
- package/src/lib/Common/Request.ts +1 -1
- package/src/lib/Encoder/Decoder.ts +28 -13
- package/src/lib/Encoder/Encoder.ts +4 -5
- package/src/lib/Server/Common/Gateway.ts +4 -0
- package/src/lib/Server/Common/Request.ts +3 -1
- package/src/lib/Server/Common/Router.ts +7 -2
- package/src/lib/Server/Common/Server.ts +7 -0
- package/src/lib/Server/Errors.ts +7 -0
- package/src/lib/Server/Gateways/Http.ts +37 -13
- package/src/lib/Server/Gateways/TCP.ts +21 -10
- package/src/lib/Server/Server.ts +38 -16
- package/src/lib/Server/SimpleRouter.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litert/televoke",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.6",
|
|
4
4
|
"description": "A simple RPC service framework.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -36,14 +36,12 @@
|
|
|
36
36
|
"types": "lib/index.d.ts",
|
|
37
37
|
"typings": "lib/index.d.ts",
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@commitlint/cli": "^
|
|
40
|
-
"@commitlint/config-conventional": "^
|
|
41
|
-
"@
|
|
42
|
-
"@
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"husky": "^7.0.1",
|
|
46
|
-
"typescript": "^4.3.5"
|
|
39
|
+
"@commitlint/cli": "^17.7.2",
|
|
40
|
+
"@commitlint/config-conventional": "^17.6.6",
|
|
41
|
+
"@litert/eslint-plugin-rules": "^0.1.5",
|
|
42
|
+
"@types/node": "^20.8.4",
|
|
43
|
+
"husky": "^8.0.3",
|
|
44
|
+
"typescript": "^5.2.2"
|
|
47
45
|
},
|
|
48
46
|
"engines": {
|
|
49
47
|
"node": ">=12.0.0"
|
package/src/lib/Client/Common.ts
CHANGED
|
@@ -32,7 +32,8 @@ export interface IResponse<T> extends G.IRawResponse<T> {
|
|
|
32
32
|
crt: number;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export interface IClient<TAPIs extends G.IServiceAPIs = G.IServiceAPIs>
|
|
35
|
+
export interface IClient<TAPIs extends G.IServiceAPIs = G.IServiceAPIs>
|
|
36
|
+
extends Events.IObservable<Events.ICallbackDefinitions> {
|
|
36
37
|
|
|
37
38
|
connect(): Promise<void>;
|
|
38
39
|
|
|
@@ -23,17 +23,17 @@ import { Events } from '@litert/observable';
|
|
|
23
23
|
|
|
24
24
|
class HttpClient extends Events.EventEmitter<Events.ICallbackDefinitions> implements C.IClient {
|
|
25
25
|
|
|
26
|
-
private _agent: $Http.Agent;
|
|
26
|
+
private readonly _agent: $Http.Agent;
|
|
27
27
|
|
|
28
28
|
public onError!: any;
|
|
29
29
|
|
|
30
30
|
public constructor(
|
|
31
|
-
private _host: string,
|
|
32
|
-
private _port: number,
|
|
33
|
-
private _ridGenerator: C.IRIDGenerator,
|
|
34
|
-
private _path: string = '/',
|
|
35
|
-
private _timeout: number = 30000,
|
|
36
|
-
private _apiNameWrapper?: (name: string) => string
|
|
31
|
+
private readonly _host: string,
|
|
32
|
+
private readonly _port: number,
|
|
33
|
+
private readonly _ridGenerator: C.IRIDGenerator,
|
|
34
|
+
private readonly _path: string = '/',
|
|
35
|
+
private readonly _timeout: number = 30000,
|
|
36
|
+
private readonly _apiNameWrapper?: (name: string) => string
|
|
37
37
|
) {
|
|
38
38
|
|
|
39
39
|
super();
|
|
@@ -75,7 +75,7 @@ class HttpClient extends Events.EventEmitter<Events.ICallbackDefinitions> implem
|
|
|
75
75
|
|
|
76
76
|
if (length > G.MAX_PACKET_SIZE) {
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
reject(new GE.E_PACKET_TOO_LARGE()); return;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const req = $Http.request({
|
|
@@ -85,21 +85,22 @@ class HttpClient extends Events.EventEmitter<Events.ICallbackDefinitions> implem
|
|
|
85
85
|
agent: this._agent,
|
|
86
86
|
method: 'POST',
|
|
87
87
|
headers: {
|
|
88
|
-
'content-length': Buffer.byteLength(content)
|
|
88
|
+
'content-length': Buffer.byteLength(content),
|
|
89
|
+
'x-tv-ver': 1
|
|
89
90
|
},
|
|
90
91
|
timeout: this._timeout
|
|
91
92
|
}, (resp) => {
|
|
92
93
|
|
|
93
94
|
if (!resp.headers['content-length']) {
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
reject(new E.E_INVALID_RESPONSE()); return;
|
|
96
97
|
}
|
|
97
98
|
|
|
98
99
|
const length = parseInt(resp.headers['content-length']);
|
|
99
100
|
|
|
100
101
|
if (!Number.isSafeInteger(length) || length > G.MAX_PACKET_SIZE) { // Maximum request packet is 64MB
|
|
101
102
|
|
|
102
|
-
|
|
103
|
+
reject(new GE.E_PACKET_TOO_LARGE()); return;
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
const buf = Buffer.allocUnsafe(length);
|
|
@@ -118,7 +119,7 @@ class HttpClient extends Events.EventEmitter<Events.ICallbackDefinitions> implem
|
|
|
118
119
|
resp.removeAllListeners('data');
|
|
119
120
|
resp.destroy();
|
|
120
121
|
|
|
121
|
-
|
|
122
|
+
reject(new GE.E_INVALID_PACKET()); return;
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
chunk.copy(buf, index);
|
|
@@ -133,7 +134,7 @@ class HttpClient extends Events.EventEmitter<Events.ICallbackDefinitions> implem
|
|
|
133
134
|
}
|
|
134
135
|
catch {
|
|
135
136
|
|
|
136
|
-
|
|
137
|
+
reject(new GE.E_INVALID_PACKET()); return;
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
const data = rawData as C.IResponse<any>;
|
|
@@ -168,9 +169,11 @@ class HttpClient extends Events.EventEmitter<Events.ICallbackDefinitions> implem
|
|
|
168
169
|
});
|
|
169
170
|
});
|
|
170
171
|
|
|
171
|
-
req.once('timeout', () =>
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
req.once('timeout', () => {
|
|
173
|
+
reject(new E.E_REQUEST_TIMEOUT({
|
|
174
|
+
metadata: { api, requestId: rid, time: Date.now(), details: null }
|
|
175
|
+
}));
|
|
176
|
+
});
|
|
174
177
|
|
|
175
178
|
req.once('error', reject);
|
|
176
179
|
|
|
@@ -23,17 +23,17 @@ import { Events } from '@litert/observable';
|
|
|
23
23
|
|
|
24
24
|
class HttpsClient extends Events.EventEmitter<Events.ICallbackDefinitions> implements C.IClient {
|
|
25
25
|
|
|
26
|
-
private _agent: $Https.Agent;
|
|
26
|
+
private readonly _agent: $Https.Agent;
|
|
27
27
|
|
|
28
28
|
public onError!: any;
|
|
29
29
|
|
|
30
30
|
public constructor(
|
|
31
|
-
private _host: string,
|
|
32
|
-
private _port: number,
|
|
33
|
-
private _ridGenerator: C.IRIDGenerator,
|
|
34
|
-
private _path: string = '',
|
|
35
|
-
private _timeout: number = 30000,
|
|
36
|
-
private _apiNameWrapper?: (name: string) => string,
|
|
31
|
+
private readonly _host: string,
|
|
32
|
+
private readonly _port: number,
|
|
33
|
+
private readonly _ridGenerator: C.IRIDGenerator,
|
|
34
|
+
private readonly _path: string = '',
|
|
35
|
+
private readonly _timeout: number = 30000,
|
|
36
|
+
private readonly _apiNameWrapper?: (name: string) => string,
|
|
37
37
|
tlsAgentOptions?: $Https.AgentOptions
|
|
38
38
|
) {
|
|
39
39
|
|
|
@@ -78,7 +78,7 @@ class HttpsClient extends Events.EventEmitter<Events.ICallbackDefinitions> imple
|
|
|
78
78
|
|
|
79
79
|
if (length > G.MAX_PACKET_SIZE) {
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
reject(new GE.E_PACKET_TOO_LARGE()); return;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
const req = $Https.request({
|
|
@@ -88,21 +88,22 @@ class HttpsClient extends Events.EventEmitter<Events.ICallbackDefinitions> imple
|
|
|
88
88
|
agent: this._agent,
|
|
89
89
|
method: 'POST',
|
|
90
90
|
headers: {
|
|
91
|
-
'content-length': Buffer.byteLength(content)
|
|
91
|
+
'content-length': Buffer.byteLength(content),
|
|
92
|
+
'x-tv-ver': 1
|
|
92
93
|
},
|
|
93
94
|
timeout: this._timeout
|
|
94
95
|
}, (resp) => {
|
|
95
96
|
|
|
96
97
|
if (!resp.headers['content-length']) {
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
reject(new E.E_INVALID_RESPONSE()); return;
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
const length = parseInt(resp.headers['content-length']);
|
|
102
103
|
|
|
103
104
|
if (!Number.isSafeInteger(length) || length > G.MAX_PACKET_SIZE) { // Maximum request packet is 64MB
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
reject(new GE.E_PACKET_TOO_LARGE()); return;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
const buf = Buffer.allocUnsafe(length);
|
|
@@ -121,7 +122,7 @@ class HttpsClient extends Events.EventEmitter<Events.ICallbackDefinitions> imple
|
|
|
121
122
|
resp.removeAllListeners('data');
|
|
122
123
|
resp.destroy();
|
|
123
124
|
|
|
124
|
-
|
|
125
|
+
reject(new GE.E_INVALID_PACKET()); return;
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
chunk.copy(buf, index);
|
|
@@ -136,7 +137,7 @@ class HttpsClient extends Events.EventEmitter<Events.ICallbackDefinitions> imple
|
|
|
136
137
|
}
|
|
137
138
|
catch {
|
|
138
139
|
|
|
139
|
-
|
|
140
|
+
reject(new GE.E_INVALID_PACKET()); return;
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
const data = rawData as C.IResponse<any>;
|
|
@@ -171,9 +172,11 @@ class HttpsClient extends Events.EventEmitter<Events.ICallbackDefinitions> imple
|
|
|
171
172
|
});
|
|
172
173
|
});
|
|
173
174
|
|
|
174
|
-
req.once('timeout', () =>
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
req.once('timeout', () => {
|
|
176
|
+
reject(new E.E_REQUEST_TIMEOUT({
|
|
177
|
+
metadata: { api, requestId: rid, time: Date.now(), details: null }
|
|
178
|
+
}));
|
|
179
|
+
});
|
|
177
180
|
|
|
178
181
|
req.once('error', reject);
|
|
179
182
|
|
|
@@ -17,11 +17,10 @@
|
|
|
17
17
|
import * as $Net from 'net';
|
|
18
18
|
import * as C from './Common';
|
|
19
19
|
import * as G from '../Common';
|
|
20
|
-
import { Promises } from '@litert/observable';
|
|
20
|
+
import { Promises, Events } from '@litert/observable';
|
|
21
21
|
import * as E from './Errors';
|
|
22
22
|
import { createDecoder } from '../Encoder/Decoder';
|
|
23
23
|
import { createEncoder } from '../Encoder/Encoder';
|
|
24
|
-
import { Events } from '@litert/observable';
|
|
25
24
|
|
|
26
25
|
enum EStatus {
|
|
27
26
|
|
|
@@ -48,7 +47,7 @@ interface IRequest {
|
|
|
48
47
|
|
|
49
48
|
class TCPClient extends Events.EventEmitter<Events.ICallbackDefinitions> implements C.IClient {
|
|
50
49
|
|
|
51
|
-
private static _$promises = Promises.getGlobalFactory();
|
|
50
|
+
private static readonly _$promises = Promises.getGlobalFactory();
|
|
52
51
|
|
|
53
52
|
private static _$clientCounter = 0;
|
|
54
53
|
|
|
@@ -56,11 +55,11 @@ class TCPClient extends Events.EventEmitter<Events.ICallbackDefinitions> impleme
|
|
|
56
55
|
|
|
57
56
|
private _status: EStatus = EStatus.IDLE;
|
|
58
57
|
|
|
59
|
-
private _clientId: number = TCPClient._$clientCounter++;
|
|
58
|
+
private readonly _clientId: number = TCPClient._$clientCounter++;
|
|
60
59
|
|
|
61
|
-
private _connPrId: string;
|
|
60
|
+
private readonly _connPrId: string;
|
|
62
61
|
|
|
63
|
-
private _closePrId: string;
|
|
62
|
+
private readonly _closePrId: string;
|
|
64
63
|
|
|
65
64
|
private _sent: Record<string, IRequest> = {};
|
|
66
65
|
|
|
@@ -70,14 +69,14 @@ class TCPClient extends Events.EventEmitter<Events.ICallbackDefinitions> impleme
|
|
|
70
69
|
|
|
71
70
|
private _sendingQty: number = 0;
|
|
72
71
|
|
|
73
|
-
private _encoder = createEncoder();
|
|
72
|
+
private readonly _encoder = createEncoder();
|
|
74
73
|
|
|
75
74
|
public constructor(
|
|
76
|
-
private _host: string,
|
|
77
|
-
private _port: number,
|
|
78
|
-
private _ridGenerator: C.IRIDGenerator,
|
|
79
|
-
private _timeout: number = 30000,
|
|
80
|
-
private _apiNameWrapper?: (name: string) => string
|
|
75
|
+
private readonly _host: string,
|
|
76
|
+
private readonly _port: number,
|
|
77
|
+
private readonly _ridGenerator: C.IRIDGenerator,
|
|
78
|
+
private readonly _timeout: number = 30000,
|
|
79
|
+
private readonly _apiNameWrapper?: (name: string) => string
|
|
81
80
|
) {
|
|
82
81
|
|
|
83
82
|
super();
|
|
@@ -404,6 +403,11 @@ export interface ITCPClientOptions {
|
|
|
404
403
|
apiNameWrapper?: (name: string) => string;
|
|
405
404
|
}
|
|
406
405
|
|
|
406
|
+
/**
|
|
407
|
+
* Create a client of TCP-base televoke/1 protocol.
|
|
408
|
+
*
|
|
409
|
+
* @deprecated This legacy TCP-based televoke/1 protocol is no longer maintained, and will be removed in v2.0.0
|
|
410
|
+
*/
|
|
407
411
|
export function createTCPClient<TAPIs extends G.IServiceAPIs>(opts: ITCPClientOptions): C.IClient<TAPIs> {
|
|
408
412
|
|
|
409
413
|
return new TCPClient(
|
|
@@ -17,11 +17,10 @@
|
|
|
17
17
|
import * as $TLS from 'tls';
|
|
18
18
|
import * as C from './Common';
|
|
19
19
|
import * as G from '../Common';
|
|
20
|
-
import { Promises } from '@litert/observable';
|
|
20
|
+
import { Promises, Events } from '@litert/observable';
|
|
21
21
|
import * as E from './Errors';
|
|
22
22
|
import { createDecoder } from '../Encoder/Decoder';
|
|
23
23
|
import { createEncoder } from '../Encoder/Encoder';
|
|
24
|
-
import { Events } from '@litert/observable';
|
|
25
24
|
|
|
26
25
|
enum EStatus {
|
|
27
26
|
|
|
@@ -48,7 +47,7 @@ interface IRequest {
|
|
|
48
47
|
|
|
49
48
|
class TLSClient extends Events.EventEmitter<Events.ICallbackDefinitions> implements C.IClient {
|
|
50
49
|
|
|
51
|
-
private static _$promises = Promises.getGlobalFactory();
|
|
50
|
+
private static readonly _$promises = Promises.getGlobalFactory();
|
|
52
51
|
|
|
53
52
|
private static _$clientCounter = 0;
|
|
54
53
|
|
|
@@ -56,11 +55,11 @@ class TLSClient extends Events.EventEmitter<Events.ICallbackDefinitions> impleme
|
|
|
56
55
|
|
|
57
56
|
private _status: EStatus = EStatus.IDLE;
|
|
58
57
|
|
|
59
|
-
private _clientId: number = TLSClient._$clientCounter++;
|
|
58
|
+
private readonly _clientId: number = TLSClient._$clientCounter++;
|
|
60
59
|
|
|
61
|
-
private _connPrId: string;
|
|
60
|
+
private readonly _connPrId: string;
|
|
62
61
|
|
|
63
|
-
private _closePrId: string;
|
|
62
|
+
private readonly _closePrId: string;
|
|
64
63
|
|
|
65
64
|
private _sent: Record<string, IRequest> = {};
|
|
66
65
|
|
|
@@ -70,15 +69,15 @@ class TLSClient extends Events.EventEmitter<Events.ICallbackDefinitions> impleme
|
|
|
70
69
|
|
|
71
70
|
private _sendingQty: number = 0;
|
|
72
71
|
|
|
73
|
-
private _encoder = createEncoder();
|
|
72
|
+
private readonly _encoder = createEncoder();
|
|
74
73
|
|
|
75
74
|
public constructor(
|
|
76
|
-
private _host: string,
|
|
77
|
-
private _port: number,
|
|
78
|
-
private _ridGenerator: C.IRIDGenerator,
|
|
79
|
-
private _timeout: number = 30000,
|
|
80
|
-
private _apiNameWrapper?: (name: string) => string,
|
|
81
|
-
private _tlsOptions?: $TLS.ConnectionOptions
|
|
75
|
+
private readonly _host: string,
|
|
76
|
+
private readonly _port: number,
|
|
77
|
+
private readonly _ridGenerator: C.IRIDGenerator,
|
|
78
|
+
private readonly _timeout: number = 30000,
|
|
79
|
+
private readonly _apiNameWrapper?: (name: string) => string,
|
|
80
|
+
private readonly _tlsOptions?: $TLS.ConnectionOptions
|
|
82
81
|
) {
|
|
83
82
|
|
|
84
83
|
super();
|
|
@@ -37,7 +37,7 @@ class Decoder implements C.IDecoder<any> {
|
|
|
37
37
|
|
|
38
38
|
private _packetLength!: number;
|
|
39
39
|
|
|
40
|
-
private _plBuf: Buffer = Buffer.allocUnsafe(
|
|
40
|
+
private readonly _plBuf: Buffer = Buffer.allocUnsafe(8);
|
|
41
41
|
|
|
42
42
|
private _plBufLength: number = 0;
|
|
43
43
|
|
|
@@ -72,7 +72,7 @@ class Decoder implements C.IDecoder<any> {
|
|
|
72
72
|
|
|
73
73
|
try {
|
|
74
74
|
|
|
75
|
-
data = JSON.parse(chunk.
|
|
75
|
+
data = JSON.parse(chunk.subarray(0, this._packetLength).toString());
|
|
76
76
|
}
|
|
77
77
|
catch (e) {
|
|
78
78
|
|
|
@@ -81,7 +81,7 @@ class Decoder implements C.IDecoder<any> {
|
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
chunk = chunk.
|
|
84
|
+
chunk = chunk.subarray(this._packetLength);
|
|
85
85
|
this.reset();
|
|
86
86
|
|
|
87
87
|
try {
|
|
@@ -98,15 +98,15 @@ class Decoder implements C.IDecoder<any> {
|
|
|
98
98
|
|
|
99
99
|
if (chunk.length + this._bufLength >= this._packetLength) {
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
const restLength = this._packetLength - this._bufLength;
|
|
102
102
|
chunk.copy(this._buf, this._bufLength, 0, this._packetLength - this._bufLength);
|
|
103
|
-
chunk = chunk.
|
|
103
|
+
chunk = chunk.subarray(restLength);
|
|
104
104
|
|
|
105
105
|
let data: any;
|
|
106
106
|
|
|
107
107
|
try {
|
|
108
108
|
|
|
109
|
-
data = JSON.parse(this._buf.
|
|
109
|
+
data = JSON.parse(this._buf.subarray(0, this._packetLength).toString());
|
|
110
110
|
}
|
|
111
111
|
catch (e) {
|
|
112
112
|
|
|
@@ -137,13 +137,21 @@ class Decoder implements C.IDecoder<any> {
|
|
|
137
137
|
|
|
138
138
|
if (this._plBufLength) {
|
|
139
139
|
|
|
140
|
-
if (this._plBufLength + chunk.byteLength >=
|
|
140
|
+
if (this._plBufLength + chunk.byteLength >= 8) {
|
|
141
141
|
|
|
142
|
-
chunk.copy(this._plBuf, this._plBufLength, 0,
|
|
142
|
+
chunk.copy(this._plBuf, this._plBufLength, 0, 8 - this._plBufLength);
|
|
143
|
+
|
|
144
|
+
chunk = chunk.subarray(8 - this._plBufLength);
|
|
145
|
+
|
|
146
|
+
if (this._plBuf.readUInt32LE(0) !== 1) {
|
|
147
|
+
|
|
148
|
+
this.onProtocolError(new GE.E_INVALID_PACKET());
|
|
149
|
+
this.reset();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
143
152
|
|
|
144
|
-
chunk = chunk.slice(4 - this._plBufLength);
|
|
145
153
|
this._plBufLength = 0;
|
|
146
|
-
this._packetLength = this._plBuf.readUInt32LE(
|
|
154
|
+
this._packetLength = this._plBuf.readUInt32LE(4);
|
|
147
155
|
}
|
|
148
156
|
else {
|
|
149
157
|
|
|
@@ -155,10 +163,17 @@ class Decoder implements C.IDecoder<any> {
|
|
|
155
163
|
}
|
|
156
164
|
else {
|
|
157
165
|
|
|
158
|
-
if (chunk.length >=
|
|
166
|
+
if (chunk.length >= 8) {
|
|
167
|
+
|
|
168
|
+
if (chunk.readUInt32LE(0) !== 1) {
|
|
169
|
+
|
|
170
|
+
this.onProtocolError(new GE.E_INVALID_PACKET());
|
|
171
|
+
this.reset();
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
159
174
|
|
|
160
|
-
this._packetLength = chunk.readUInt32LE(
|
|
161
|
-
chunk = chunk.
|
|
175
|
+
this._packetLength = chunk.readUInt32LE(4);
|
|
176
|
+
chunk = chunk.subarray(8);
|
|
162
177
|
this._plBufLength = 0;
|
|
163
178
|
}
|
|
164
179
|
else {
|
|
@@ -22,16 +22,15 @@ class Encoder implements C.IEncoder {
|
|
|
22
22
|
|
|
23
23
|
content = JSON.stringify(content);
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const ret = Buffer.allocUnsafe(8);
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
ret.writeUInt32LE(contentLength, 0);
|
|
30
|
-
ret.write(content, 4);
|
|
27
|
+
ret.writeUInt32LE(1, 0);
|
|
28
|
+
ret.writeUInt32LE(Buffer.byteLength(content), 4);
|
|
31
29
|
|
|
32
30
|
if (socket.writable) {
|
|
33
31
|
|
|
34
32
|
socket.write(ret);
|
|
33
|
+
socket.write(content);
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
}
|
|
@@ -16,9 +16,14 @@
|
|
|
16
16
|
|
|
17
17
|
import { IRequest } from './Request';
|
|
18
18
|
|
|
19
|
-
export type IHandler<
|
|
19
|
+
export type IHandler<TApi extends (...args: any[]) => any> = (
|
|
20
|
+
...args: Parameters<TApi>
|
|
21
|
+
) => ReturnType<TApi> | Promise<ReturnType<TApi>>;
|
|
20
22
|
|
|
21
|
-
export type IHandlerEx<
|
|
23
|
+
export type IHandlerEx<TApi extends (...args: any[]) => any> = (
|
|
24
|
+
req: IRequest<Parameters<TApi>>,
|
|
25
|
+
...args: Parameters<TApi>
|
|
26
|
+
) => ReturnType<TApi> | Promise<ReturnType<TApi>>;
|
|
22
27
|
|
|
23
28
|
export interface IRouter {
|
|
24
29
|
|
|
@@ -35,6 +35,13 @@ export interface IServer extends Events.IObservable<IServerEvents> {
|
|
|
35
35
|
*/
|
|
36
36
|
addGateway(name: string, gateway: IGateway): this;
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Get a mounted gateway by name.
|
|
40
|
+
*
|
|
41
|
+
* @param name The name of the gateway.
|
|
42
|
+
*/
|
|
43
|
+
getGateway(name: string): IGateway;
|
|
44
|
+
|
|
38
45
|
/**
|
|
39
46
|
* Unmount a gateway.
|
|
40
47
|
*
|
package/src/lib/Server/Errors.ts
CHANGED
|
@@ -71,3 +71,10 @@ export const E_GATEWAY_BUSY = errorRegistry.register({
|
|
|
71
71
|
metadata: {},
|
|
72
72
|
type: 'public'
|
|
73
73
|
});
|
|
74
|
+
|
|
75
|
+
export const E_GATEWAY_NOT_FOUND = errorRegistry.register({
|
|
76
|
+
name: 'gateway_not_found',
|
|
77
|
+
message: 'No such a gateway.',
|
|
78
|
+
metadata: {},
|
|
79
|
+
type: 'public'
|
|
80
|
+
});
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import * as $Net from 'net';
|
|
17
18
|
import * as C from '../Common';
|
|
18
19
|
import * as G from '../../Common';
|
|
19
20
|
import * as E from '../Errors';
|
|
@@ -27,9 +28,28 @@ enum EStatus {
|
|
|
27
28
|
CLOSING,
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
const INVALID_REQUEST_RESPONSE = Buffer.from('{"rid":"null","body":INVALID REQUEST,"sst":1698886839989,"srt":0,"code":4}');
|
|
32
|
+
|
|
33
|
+
function refuseBadRequest(resp: $Http.ServerResponse): void {
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
|
|
37
|
+
resp.writeHead(400, {
|
|
38
|
+
'content-length': INVALID_REQUEST_RESPONSE.byteLength,
|
|
39
|
+
});
|
|
40
|
+
const socket = resp.socket!;
|
|
41
|
+
resp.end(INVALID_REQUEST_RESPONSE);
|
|
42
|
+
socket.destroy();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
|
|
46
|
+
// do nothing.
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
30
50
|
class HttpGateway implements C.IGateway {
|
|
31
51
|
|
|
32
|
-
private _server: $Http.Server = $Http.createServer(this._onRequest.bind(this));
|
|
52
|
+
private readonly _server: $Http.Server = $Http.createServer(this._onRequest.bind(this));
|
|
33
53
|
|
|
34
54
|
private _status: EStatus = EStatus.IDLE;
|
|
35
55
|
|
|
@@ -41,16 +61,16 @@ class HttpGateway implements C.IGateway {
|
|
|
41
61
|
) => void;
|
|
42
62
|
|
|
43
63
|
public constructor(
|
|
44
|
-
|
|
45
|
-
|
|
64
|
+
public host: string,
|
|
65
|
+
public port: number,
|
|
66
|
+
private readonly _backlog?: number,
|
|
46
67
|
) { }
|
|
47
68
|
|
|
48
69
|
private _onRequest(req: $Http.IncomingMessage, resp: $Http.ServerResponse): void {
|
|
49
70
|
|
|
50
71
|
if (req.method !== 'POST' || !req.headers['content-length']) {
|
|
51
72
|
|
|
52
|
-
|
|
53
|
-
resp.socket!.destroy();
|
|
73
|
+
refuseBadRequest(resp);
|
|
54
74
|
return;
|
|
55
75
|
}
|
|
56
76
|
|
|
@@ -58,8 +78,7 @@ class HttpGateway implements C.IGateway {
|
|
|
58
78
|
|
|
59
79
|
if (!Number.isSafeInteger(length) || length > G.MAX_PACKET_SIZE) { // Maximum request packet is 64MB
|
|
60
80
|
|
|
61
|
-
|
|
62
|
-
resp.socket!.destroy();
|
|
81
|
+
refuseBadRequest(resp);
|
|
63
82
|
return;
|
|
64
83
|
}
|
|
65
84
|
|
|
@@ -79,7 +98,7 @@ class HttpGateway implements C.IGateway {
|
|
|
79
98
|
|
|
80
99
|
req.removeAllListeners('end');
|
|
81
100
|
req.removeAllListeners('data');
|
|
82
|
-
|
|
101
|
+
refuseBadRequest(resp);
|
|
83
102
|
return;
|
|
84
103
|
}
|
|
85
104
|
|
|
@@ -91,11 +110,12 @@ class HttpGateway implements C.IGateway {
|
|
|
91
110
|
try {
|
|
92
111
|
|
|
93
112
|
input = JSON.parse(buf as any);
|
|
113
|
+
input.ip = (req.socket.address() as any).address;
|
|
94
114
|
}
|
|
95
115
|
catch (e) {
|
|
96
116
|
|
|
117
|
+
refuseBadRequest(resp);
|
|
97
118
|
this.onError(e);
|
|
98
|
-
req.destroy();
|
|
99
119
|
return;
|
|
100
120
|
}
|
|
101
121
|
|
|
@@ -130,11 +150,15 @@ class HttpGateway implements C.IGateway {
|
|
|
130
150
|
|
|
131
151
|
return new Promise((resolve, reject) => {
|
|
132
152
|
|
|
133
|
-
this._server.listen(this.
|
|
153
|
+
this._server.listen(this.port, this.host, this._backlog)
|
|
134
154
|
.once('listening', () => {
|
|
135
155
|
|
|
136
156
|
this._server.removeAllListeners('error');
|
|
137
157
|
this._status = EStatus.WORKING;
|
|
158
|
+
if (this.port === 0) {
|
|
159
|
+
|
|
160
|
+
this.port = (this._server.address() as $Net.AddressInfo).port;
|
|
161
|
+
}
|
|
138
162
|
resolve();
|
|
139
163
|
})
|
|
140
164
|
.once('error', (e) => {
|
|
@@ -167,13 +191,13 @@ class HttpGateway implements C.IGateway {
|
|
|
167
191
|
case EStatus.WORKING:
|
|
168
192
|
return new Promise((resolve) => {
|
|
169
193
|
|
|
170
|
-
this._server.close(() => resolve());
|
|
194
|
+
this._server.close(() => { resolve(); });
|
|
171
195
|
});
|
|
172
196
|
}
|
|
173
197
|
}
|
|
174
198
|
}
|
|
175
199
|
|
|
176
|
-
export function createHttpGateway(host: string, port: number): C.IGateway {
|
|
200
|
+
export function createHttpGateway(host: string, port: number, backlog?: number): C.IGateway {
|
|
177
201
|
|
|
178
|
-
return new HttpGateway(host, port);
|
|
202
|
+
return new HttpGateway(host, port, backlog);
|
|
179
203
|
}
|