tencentcloud-sdk-nodejs-intl-en 3.0.871 → 3.0.872
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/examples/cls/v20201016/cls.proto +34 -0
- package/examples/cls/v20201016/upload_log.js +68 -0
- package/package.json +1 -1
- package/tencentcloud/common/abstract_client.js +35 -8
- package/tencentcloud/common/common_client.js +31 -0
- package/tencentcloud/common/http/http_connection.js +12 -7
- package/tencentcloud/common/index.js +2 -0
- package/tencentcloud/common/profile/http_profile.js +12 -1
- package/tencentcloud/common/sdk_version.js +1 -1
- package/tencentcloud/common/sign.js +7 -4
- package/tencentcloud/common/sse_response_model.js +154 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
syntax = "proto2";
|
|
2
|
+
|
|
3
|
+
package cls;
|
|
4
|
+
|
|
5
|
+
message Log
|
|
6
|
+
{
|
|
7
|
+
message Content
|
|
8
|
+
{
|
|
9
|
+
required string key = 1; // 每组字段的 key
|
|
10
|
+
required string value = 2; // 每组字段的 value
|
|
11
|
+
}
|
|
12
|
+
required int64 time = 1; // 时间戳,UNIX时间格式
|
|
13
|
+
repeated Content contents = 2; // 一条日志里的多个kv组合
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
message LogTag
|
|
17
|
+
{
|
|
18
|
+
required string key = 1;
|
|
19
|
+
required string value = 2;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
message LogGroup
|
|
23
|
+
{
|
|
24
|
+
repeated Log logs = 1; // 多条日志合成的日志数组
|
|
25
|
+
optional string contextFlow = 2; // 目前暂无效用
|
|
26
|
+
optional string filename = 3; // 日志文件名
|
|
27
|
+
optional string source = 4; // 日志来源,一般使用机器IP
|
|
28
|
+
repeated LogTag logTags = 5;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
message LogGroupList
|
|
32
|
+
{
|
|
33
|
+
repeated LogGroup logGroupList = 1; // 日志组列表
|
|
34
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const tencentcloud = require("../../../../tencentcloud-sdk-nodejs-intl-en");
|
|
2
|
+
const protobuf = require("protobufjs")
|
|
3
|
+
const lz4 = require("lz4")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
|
|
6
|
+
const Credential = tencentcloud.common.Credential;
|
|
7
|
+
const ClientProfile = tencentcloud.common.ClientProfile;
|
|
8
|
+
const HttpProfile = tencentcloud.common.HttpProfile;
|
|
9
|
+
const CommonClient = tencentcloud.common.CommonClient
|
|
10
|
+
|
|
11
|
+
let cred = new Credential(process.env.TENCENTCLOUD_SECRET_ID, process.env.TENCENTCLOUD_SECRET_KEY);
|
|
12
|
+
|
|
13
|
+
let httpProfile = new HttpProfile();
|
|
14
|
+
httpProfile.endpoint = "cls.tencentcloudapi.com";
|
|
15
|
+
httpProfile.headers["X-CLS-TopicId"] = "c241abf2-7acd-470d-845a-fb1da6916c99"; // 替换为自己业务的 topic
|
|
16
|
+
httpProfile.headers["X-CLS-HashKey"] = ""; // 可选参数
|
|
17
|
+
httpProfile.headers["X-CLS-CompressType"] = "lz4"; // lz4压缩方式, 空字符串意味不压缩
|
|
18
|
+
|
|
19
|
+
let clientProfile = new ClientProfile();
|
|
20
|
+
clientProfile.signMethod = "TC3-HMAC-SHA256";
|
|
21
|
+
clientProfile.httpProfile = httpProfile;
|
|
22
|
+
|
|
23
|
+
let client = new CommonClient('cls.tencentcloudapi.com', '2020-10-16', cred, "ap-guangzhou", clientProfile);
|
|
24
|
+
|
|
25
|
+
let params = compress(getBodyInfo())
|
|
26
|
+
|
|
27
|
+
client.requestOctetStream('UploadLog', params, function(err, response) {
|
|
28
|
+
if (err) {
|
|
29
|
+
console.log(err);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log(response)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
function compress(input) {
|
|
38
|
+
const output = Buffer.alloc(lz4.encodeBound(input.length))
|
|
39
|
+
const compressedBlockSize = lz4.encodeBlock(input, output)
|
|
40
|
+
return output.slice(0, compressedBlockSize)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getBodyInfo() {
|
|
44
|
+
const root = protobuf.loadSync(path.join(__dirname, "cls.proto"))
|
|
45
|
+
const LogGroupList = root.lookupType("cls.LogGroupList")
|
|
46
|
+
const payload = {
|
|
47
|
+
logGroupList: [
|
|
48
|
+
{
|
|
49
|
+
logs: [
|
|
50
|
+
{
|
|
51
|
+
time: Date.now(),
|
|
52
|
+
contents: [
|
|
53
|
+
{
|
|
54
|
+
key: "name",
|
|
55
|
+
value: "张三",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
key: "age",
|
|
59
|
+
value: "18",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
}
|
|
67
|
+
return LogGroupList.encode(payload).finish()
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ const ClientProfile = require("./profile/client_profile");
|
|
|
4
4
|
const Sign = require("./sign");
|
|
5
5
|
const HttpConnection = require("./http/http_connection");
|
|
6
6
|
const TencentCloudSDKHttpException = require("./exception/tencent_cloud_sdk_exception");
|
|
7
|
+
const SSEResponseModel = require("./sse_response_model");
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* @inner
|
|
@@ -80,6 +81,26 @@ class AbstractClient {
|
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
/**
|
|
85
|
+
* @inner
|
|
86
|
+
*/
|
|
87
|
+
requestOctetStream(action, req, resp, options, cb) {
|
|
88
|
+
if (typeof options === 'function') {
|
|
89
|
+
cb = options
|
|
90
|
+
options = {}
|
|
91
|
+
}
|
|
92
|
+
options = Object.assign({}, options, {
|
|
93
|
+
headers: {
|
|
94
|
+
"Content-Type": "application/octet-stream; charset=utf-8",
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
if (this.profile.signMethod === 'TC3-HMAC-SHA256') {
|
|
98
|
+
this.doRequestWithSign3(action, req, options).then(data => this.succRequest(resp, cb, data), error => this.failRequest(error, cb));
|
|
99
|
+
} else {
|
|
100
|
+
this.doRequest(action, req).then(data => this.succRequest(resp, cb, data), error => this.failRequest(error, cb));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
83
104
|
/**
|
|
84
105
|
* @inner
|
|
85
106
|
*/
|
|
@@ -92,7 +113,8 @@ class AbstractClient {
|
|
|
92
113
|
method: this.profile.httpProfile.reqMethod,
|
|
93
114
|
url: this.profile.httpProfile.protocol + this.getEndpoint() + this.path,
|
|
94
115
|
data: params,
|
|
95
|
-
timeout: this.profile.httpProfile.reqTimeout * 1000
|
|
116
|
+
timeout: this.profile.httpProfile.reqTimeout * 1000,
|
|
117
|
+
headers: Object.assign({}, this.profile.httpProfile.headers),
|
|
96
118
|
});
|
|
97
119
|
} catch (error) {
|
|
98
120
|
throw new TencentCloudSDKHttpException(error.message);
|
|
@@ -119,7 +141,8 @@ class AbstractClient {
|
|
|
119
141
|
multipart: options.multipart,
|
|
120
142
|
timeout: this.profile.httpProfile.reqTimeout * 1000,
|
|
121
143
|
token: this.credential.token,
|
|
122
|
-
requestClient: this.sdkVersion
|
|
144
|
+
requestClient: this.sdkVersion,
|
|
145
|
+
headers: Object.assign({}, this.profile.httpProfile.headers, options.headers),
|
|
123
146
|
})
|
|
124
147
|
} catch (e) {
|
|
125
148
|
throw new TencentCloudSDKHttpException(e.message)
|
|
@@ -133,13 +156,17 @@ class AbstractClient {
|
|
|
133
156
|
tcError.httpCode = res.status
|
|
134
157
|
throw tcError;
|
|
135
158
|
} else {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const tcError = new TencentCloudSDKHttpException(data.Response.Error.Message, data.Response.RequestId)
|
|
139
|
-
tcError.code = data.Response.Error.Code
|
|
140
|
-
throw tcError;
|
|
159
|
+
if (res.headers.get("content-type") === "text/event-stream") {
|
|
160
|
+
return new SSEResponseModel(res.body)
|
|
141
161
|
} else {
|
|
142
|
-
|
|
162
|
+
const data = await res.json();
|
|
163
|
+
if (data.Response.Error) {
|
|
164
|
+
const tcError = new TencentCloudSDKHttpException(data.Response.Error.Message, data.Response.RequestId)
|
|
165
|
+
tcError.code = data.Response.Error.Code
|
|
166
|
+
throw tcError;
|
|
167
|
+
} else {
|
|
168
|
+
return data.Response;
|
|
169
|
+
}
|
|
143
170
|
}
|
|
144
171
|
}
|
|
145
172
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const AbstractClient = require('./abstract_client')
|
|
2
|
+
const SSEResponseModel = require("./sse_response_model");
|
|
3
|
+
|
|
4
|
+
class CommonClient extends AbstractClient {
|
|
5
|
+
/**
|
|
6
|
+
* @inner
|
|
7
|
+
*/
|
|
8
|
+
succRequest(resp, cb, data) {
|
|
9
|
+
if (data instanceof SSEResponseModel) {
|
|
10
|
+
cb(null, data);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
cb(null, JSON.stringify(data))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @inner
|
|
18
|
+
*/
|
|
19
|
+
request(action, params, options, cb) {
|
|
20
|
+
super.request(action, params, null, options, cb);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @inner
|
|
25
|
+
*/
|
|
26
|
+
requestOctetStream(action, params, options, cb) {
|
|
27
|
+
super.requestOctetStream(action, params, null, options, cb);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = CommonClient;
|
|
@@ -10,10 +10,10 @@ const fetch = require('./fetch');
|
|
|
10
10
|
* @inner
|
|
11
11
|
*/
|
|
12
12
|
class HttpConnection {
|
|
13
|
-
static async doRequest({ method, url, data, timeout }) {
|
|
13
|
+
static async doRequest({ method, url, data, timeout, headers }) {
|
|
14
14
|
let config = {
|
|
15
15
|
method: method,
|
|
16
|
-
headers
|
|
16
|
+
headers,
|
|
17
17
|
timeout
|
|
18
18
|
};
|
|
19
19
|
if (method === "GET") {
|
|
@@ -38,7 +38,8 @@ class HttpConnection {
|
|
|
38
38
|
multipart = false,
|
|
39
39
|
timeout = 60000,
|
|
40
40
|
token,
|
|
41
|
-
requestClient
|
|
41
|
+
requestClient,
|
|
42
|
+
headers = {}
|
|
42
43
|
}) {
|
|
43
44
|
// data 中可能带有 readStream,由于需要计算整个 body 的 hash,
|
|
44
45
|
// 所以这里把 readStream 转为 Buffer
|
|
@@ -68,7 +69,8 @@ class HttpConnection {
|
|
|
68
69
|
'X-TC-Timestamp': timestamp,
|
|
69
70
|
'X-TC-Version': version,
|
|
70
71
|
'X-TC-Token': token,
|
|
71
|
-
'X-TC-RequestClient': requestClient
|
|
72
|
+
'X-TC-RequestClient': requestClient,
|
|
73
|
+
...headers,
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
|
|
@@ -81,8 +83,10 @@ class HttpConnection {
|
|
|
81
83
|
config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
82
84
|
}
|
|
83
85
|
if (method === 'POST' && !multipart) {
|
|
84
|
-
config.body =
|
|
85
|
-
config.headers[
|
|
86
|
+
config.body = data
|
|
87
|
+
const contentType = config.headers["Content-Type"] || "application/json"
|
|
88
|
+
if (!isBuffer(data)) config.body = JSON.stringify(data)
|
|
89
|
+
config.headers["Content-Type"] = contentType
|
|
86
90
|
}
|
|
87
91
|
if (method === 'POST' && multipart) {
|
|
88
92
|
form = new FormData();
|
|
@@ -102,7 +106,8 @@ class HttpConnection {
|
|
|
102
106
|
secretId,
|
|
103
107
|
secretKey,
|
|
104
108
|
multipart,
|
|
105
|
-
boundary: form ? form.getBoundary() : undefined
|
|
109
|
+
boundary: form ? form.getBoundary() : undefined,
|
|
110
|
+
headers: config.headers,
|
|
106
111
|
})
|
|
107
112
|
|
|
108
113
|
config.headers['Authorization'] = signature
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* HTTP settings.
|
|
3
3
|
* @class
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object.<string, string>} StringRecord
|
|
7
|
+
* @property {string} key
|
|
8
|
+
* @property {string} value
|
|
9
|
+
*/
|
|
5
10
|
class HttpProfile {
|
|
6
11
|
|
|
7
12
|
/**
|
|
@@ -9,8 +14,9 @@ class HttpProfile {
|
|
|
9
14
|
* @param {string} endpoint Domain name, such as cvm.ap-shanghai.tencentcloud.com.
|
|
10
15
|
* @param {string} reqMethod HTTP method, only supports GET and POST.
|
|
11
16
|
* @param {number} reqTimeout Request timeout value, in seconds, default 60.
|
|
17
|
+
* @param {StringRecord} headers HTTP headers, default {}.
|
|
12
18
|
*/
|
|
13
|
-
constructor(protocol, endpoint, reqMethod, reqTimeout) {
|
|
19
|
+
constructor(protocol, endpoint, reqMethod, reqTimeout, headers) {
|
|
14
20
|
/**
|
|
15
21
|
* @type {string}
|
|
16
22
|
*/
|
|
@@ -30,6 +36,11 @@ class HttpProfile {
|
|
|
30
36
|
* @type {number}
|
|
31
37
|
*/
|
|
32
38
|
this.reqTimeout = reqTimeout || 60;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @type {StringRecord}
|
|
42
|
+
*/
|
|
43
|
+
this.headers = headers || {};
|
|
33
44
|
}
|
|
34
45
|
}
|
|
35
46
|
module.exports = HttpProfile;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const sdkVersion = "3.0.
|
|
1
|
+
const sdkVersion = "3.0.872";
|
|
2
2
|
module.exports = sdkVersion
|
|
@@ -29,22 +29,24 @@ class Sign {
|
|
|
29
29
|
secretId,
|
|
30
30
|
secretKey,
|
|
31
31
|
multipart,
|
|
32
|
-
boundary
|
|
32
|
+
boundary,
|
|
33
|
+
headers: configHeaders = {},
|
|
33
34
|
}) {
|
|
34
35
|
const urlObj = new URL(url)
|
|
36
|
+
const contentType = configHeaders["Content-Type"]
|
|
35
37
|
|
|
36
38
|
// 通用头部
|
|
37
39
|
let headers = ''
|
|
38
40
|
let signedHeaders = ''
|
|
39
41
|
if (method === 'GET') {
|
|
40
42
|
signedHeaders = 'content-type'
|
|
41
|
-
headers =
|
|
43
|
+
headers = `content-type:${contentType}\n`
|
|
42
44
|
} else if (method === 'POST') {
|
|
43
45
|
signedHeaders = 'content-type'
|
|
44
46
|
if (multipart) {
|
|
45
47
|
headers = `content-type:multipart/form-data; boundary=${boundary}\n`
|
|
46
48
|
} else {
|
|
47
|
-
headers =
|
|
49
|
+
headers = `content-type:${contentType}\n`
|
|
48
50
|
}
|
|
49
51
|
}
|
|
50
52
|
headers += `host:${urlObj.hostname}\n`
|
|
@@ -72,7 +74,8 @@ class Sign {
|
|
|
72
74
|
hash.update(`--\r\n`)
|
|
73
75
|
payload_hash = hash.digest('hex')
|
|
74
76
|
} else {
|
|
75
|
-
|
|
77
|
+
const hashMessage = Buffer.isBuffer(payload) ? payload : JSON.stringify(payload)
|
|
78
|
+
payload_hash = payload ? getHash(hashMessage) : getHash('')
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
const canonicalRequest =
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const { EventEmitter } = require('events')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @interface EventSourceMessage
|
|
5
|
+
* @description Represents a type EventSourceMessage.
|
|
6
|
+
* @property {string} id - The event ID to set the EventSource object's last event ID value.
|
|
7
|
+
* @property {string} event - A string identifying the type of event described.
|
|
8
|
+
* @property {string} data - The event data.
|
|
9
|
+
* @property {string} retry - The reconnection interval (in milliseconds) to wait before retrying the connection (optional).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
class SSEEventEmitter extends EventEmitter {}
|
|
13
|
+
|
|
14
|
+
class SSEResponseModel {
|
|
15
|
+
/**
|
|
16
|
+
* Initialize the SSE response model.
|
|
17
|
+
* @param {NodeJS.ReadableStream} stream
|
|
18
|
+
*/
|
|
19
|
+
constructor(stream) {
|
|
20
|
+
this.stream = stream
|
|
21
|
+
this.eventSource = new SSEEventEmitter()
|
|
22
|
+
this.init()
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @inner
|
|
27
|
+
*/
|
|
28
|
+
init() {
|
|
29
|
+
const { stream, eventSource } = this
|
|
30
|
+
stream.on("data", (chunk) => {
|
|
31
|
+
if (chunk !== null) {
|
|
32
|
+
const messages = chunk.toString().split("\n\n")
|
|
33
|
+
for (let i = 0; i < messages.length; i++) {
|
|
34
|
+
if (messages[i].length > 0) {
|
|
35
|
+
eventSource.emit("message", this.parseSSEMessage(messages[i]))
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
stream.on("close", () => {
|
|
41
|
+
eventSource.emit("close")
|
|
42
|
+
})
|
|
43
|
+
stream.on("error", (err) => {
|
|
44
|
+
eventSource.emit("error", err)
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @inner
|
|
50
|
+
* @param {string} chunk
|
|
51
|
+
*/
|
|
52
|
+
parseSSEMessage(chunk) {
|
|
53
|
+
/**
|
|
54
|
+
* @type {EventSourceMessage}
|
|
55
|
+
*/
|
|
56
|
+
const message = {
|
|
57
|
+
data: "",
|
|
58
|
+
event: "",
|
|
59
|
+
id: "",
|
|
60
|
+
retry: undefined,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const lines = chunk.split("\n")
|
|
64
|
+
for (let i = 0; i < lines.length; i++) {
|
|
65
|
+
const line = lines[i]
|
|
66
|
+
// line is of format "<field>:<value>" or "<field>: <value>"
|
|
67
|
+
const colonIndex = line.indexOf(":")
|
|
68
|
+
if (colonIndex <= 0) continue // exclude comments and lines with no values
|
|
69
|
+
const field = line.slice(0, colonIndex)
|
|
70
|
+
const value = line.slice(colonIndex + (line[colonIndex + 1] === " " ? 2 : 1))
|
|
71
|
+
|
|
72
|
+
switch (field) {
|
|
73
|
+
case "data":
|
|
74
|
+
message.data = message.data ? message.data + "\n" + value : value
|
|
75
|
+
break
|
|
76
|
+
case "event":
|
|
77
|
+
message.event = value
|
|
78
|
+
break
|
|
79
|
+
case "id":
|
|
80
|
+
message.id = value
|
|
81
|
+
break
|
|
82
|
+
case "retry":
|
|
83
|
+
const retry = parseInt(value, 10)
|
|
84
|
+
if (!isNaN(retry)) {
|
|
85
|
+
// per spec, ignore non-integers
|
|
86
|
+
message.retry = retry
|
|
87
|
+
}
|
|
88
|
+
break
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return message
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* add event listener.
|
|
97
|
+
* @param {"message"} event - The event type.
|
|
98
|
+
* @param {(message: EventSourceMessage) => void} listener - The event listener for "message" event.
|
|
99
|
+
* @returns {this}
|
|
100
|
+
* @param {"close"} event - The event type.
|
|
101
|
+
* @param {() => void} listener - The event listener for "close" event.
|
|
102
|
+
* @returns {this}
|
|
103
|
+
* @param {"error"} event - The event type.
|
|
104
|
+
* @param {(err: Error) => void} listener - The event listener for "error" event.
|
|
105
|
+
* @returns {this}
|
|
106
|
+
* @param {string} event - The event type.
|
|
107
|
+
* @param {any} listener - The event listener for other events.
|
|
108
|
+
* @returns {this}
|
|
109
|
+
*/
|
|
110
|
+
on(event, listener) {
|
|
111
|
+
this.eventSource.on(event, listener)
|
|
112
|
+
return this
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @param {"message"} event - The event type.
|
|
117
|
+
* @param {(message: EventSourceMessage) => void} listener - The event listener for "message" event.
|
|
118
|
+
* @returns {this}
|
|
119
|
+
* @param {"close"} event - The event type.
|
|
120
|
+
* @param {() => void} listener - The event listener for "close" event.
|
|
121
|
+
* @returns {this}
|
|
122
|
+
* @param {"error"} event - The event type.
|
|
123
|
+
* @param {(err: Error) => void} listener - The event listener for "error" event.
|
|
124
|
+
* @returns {this}
|
|
125
|
+
* @param {string} event - The event type.
|
|
126
|
+
* @param {any} listener - The event listener for other events.
|
|
127
|
+
* @returns {this}
|
|
128
|
+
*/
|
|
129
|
+
removeListener(event, listener) {
|
|
130
|
+
this.eventSource.removeListener(event, listener)
|
|
131
|
+
return this
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @function
|
|
136
|
+
* @name Symbol.asyncIterator
|
|
137
|
+
* @description Async iterator function for Symbol.asyncIterator.
|
|
138
|
+
* @returns {AsyncIterableIterator<EventSourceMessage>}
|
|
139
|
+
*/
|
|
140
|
+
async *[Symbol.asyncIterator]() {
|
|
141
|
+
for await (const chunk of this.stream) {
|
|
142
|
+
if (chunk !== null) {
|
|
143
|
+
const messages = chunk.toString().split("\n\n")
|
|
144
|
+
for (let i = 0; i < messages.length; i++) {
|
|
145
|
+
if (messages[i].length > 0) {
|
|
146
|
+
yield this.parseSSEMessage(messages[i])
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = SSEResponseModel;
|