ng-talkback 21.0.14 → 21.0.17
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/browser/package.json +1 -1
- package/browser-prod/package.json +1 -1
- package/browser-prod.re-export.json +1 -0
- package/lib/build-info._auto-generated_.d.ts +1 -1
- package/lib/build-info._auto-generated_.js +1 -1
- package/lib/package.json +1 -1
- package/lib-prod/build-info._auto-generated_.js +14 -30
- package/lib-prod/env/env.angular-node-app.js +130 -71
- package/lib-prod/env/env.docs-webapp.js +130 -71
- package/lib-prod/env/env.electron-app.js +130 -71
- package/lib-prod/env/env.mobile-app.js +130 -71
- package/lib-prod/env/env.npm-lib-and-cli-tool.js +130 -71
- package/lib-prod/env/env.vscode-plugin.js +130 -71
- package/lib-prod/env/index.js +6 -23
- package/lib-prod/es6.backend.js +5 -5
- package/lib-prod/features/error-rate.backend.js +23 -24
- package/lib-prod/features/latency.backend.js +26 -29
- package/lib-prod/index._auto-generated_.js +0 -6
- package/lib-prod/index.js +15 -31
- package/lib-prod/logger.backend.js +20 -21
- package/lib-prod/migrations/index.js +1 -19
- package/lib-prod/migrations/migrations_index._auto-generated_.js +0 -4
- package/lib-prod/options.backend.js +86 -82
- package/lib-prod/package.json +1 -1
- package/lib-prod/request-handler.backend.js +124 -138
- package/lib-prod/server.backend.js +78 -84
- package/lib-prod/summary.backend.js +20 -21
- package/lib-prod/talkback-factory.backend.js +17 -18
- package/lib-prod/tape-matcher.backend.js +87 -89
- package/lib-prod/tape-renderer.backend.js +88 -94
- package/lib-prod/tape-store.backend.js +86 -91
- package/lib-prod/tape.backend.js +69 -74
- package/lib-prod/types.backend.js +0 -3
- package/lib-prod/utils/content-encoding.backend.js +34 -35
- package/lib-prod/utils/headers.backend.js +13 -15
- package/lib-prod/utils/media-type.backend.js +45 -46
- package/lib-prod.re-export.json +1 -0
- package/package.json +3 -2
- package/websql/package.json +1 -1
- package/websql-prod/package.json +1 -1
- package/websql-prod.re-export.json +1 -0
- package/lib-prod/build-info._auto-generated_.d.ts +0 -24
- package/lib-prod/build-info._auto-generated_.js.map +0 -1
- package/lib-prod/env/env.angular-node-app.d.ts +0 -64
- package/lib-prod/env/env.angular-node-app.js.map +0 -1
- package/lib-prod/env/env.docs-webapp.d.ts +0 -64
- package/lib-prod/env/env.docs-webapp.js.map +0 -1
- package/lib-prod/env/env.electron-app.d.ts +0 -64
- package/lib-prod/env/env.electron-app.js.map +0 -1
- package/lib-prod/env/env.mobile-app.d.ts +0 -64
- package/lib-prod/env/env.mobile-app.js.map +0 -1
- package/lib-prod/env/env.npm-lib-and-cli-tool.d.ts +0 -64
- package/lib-prod/env/env.npm-lib-and-cli-tool.js.map +0 -1
- package/lib-prod/env/env.vscode-plugin.d.ts +0 -64
- package/lib-prod/env/env.vscode-plugin.js.map +0 -1
- package/lib-prod/env/index.d.ts +0 -6
- package/lib-prod/env/index.js.map +0 -1
- package/lib-prod/es6.backend.d.ts +0 -2
- package/lib-prod/es6.backend.js.map +0 -1
- package/lib-prod/features/error-rate.backend.d.ts +0 -9
- package/lib-prod/features/error-rate.backend.js.map +0 -1
- package/lib-prod/features/latency.backend.d.ts +0 -8
- package/lib-prod/features/latency.backend.js.map +0 -1
- package/lib-prod/index._auto-generated_.d.ts +0 -0
- package/lib-prod/index._auto-generated_.js.map +0 -1
- package/lib-prod/index.d.ts +0 -41
- package/lib-prod/index.js.map +0 -1
- package/lib-prod/logger.backend.d.ts +0 -7
- package/lib-prod/logger.backend.js.map +0 -1
- package/lib-prod/migrations/index.d.ts +0 -1
- package/lib-prod/migrations/index.js.map +0 -1
- package/lib-prod/migrations/migrations_index._auto-generated_.d.ts +0 -0
- package/lib-prod/migrations/migrations_index._auto-generated_.js.map +0 -1
- package/lib-prod/options.backend.d.ts +0 -52
- package/lib-prod/options.backend.js.map +0 -1
- package/lib-prod/request-handler.backend.d.ts +0 -13
- package/lib-prod/request-handler.backend.js.map +0 -1
- package/lib-prod/server.backend.d.ts +0 -17
- package/lib-prod/server.backend.js.map +0 -1
- package/lib-prod/summary.backend.d.ts +0 -8
- package/lib-prod/summary.backend.js.map +0 -1
- package/lib-prod/talkback-factory.backend.d.ts +0 -7
- package/lib-prod/talkback-factory.backend.js.map +0 -1
- package/lib-prod/tape-matcher.backend.d.ts +0 -12
- package/lib-prod/tape-matcher.backend.js.map +0 -1
- package/lib-prod/tape-renderer.backend.d.ts +0 -24
- package/lib-prod/tape-renderer.backend.js.map +0 -1
- package/lib-prod/tape-store.backend.d.ts +0 -16
- package/lib-prod/tape-store.backend.js.map +0 -1
- package/lib-prod/tape.backend.d.ts +0 -19
- package/lib-prod/tape.backend.js.map +0 -1
- package/lib-prod/types.backend.d.ts +0 -43
- package/lib-prod/types.backend.js.map +0 -1
- package/lib-prod/utils/content-encoding.backend.d.ts +0 -10
- package/lib-prod/utils/content-encoding.backend.js.map +0 -1
- package/lib-prod/utils/headers.backend.d.ts +0 -4
- package/lib-prod/utils/headers.backend.js.map +0 -1
- package/lib-prod/utils/media-type.backend.d.ts +0 -10
- package/lib-prod/utils/media-type.backend.js.map +0 -1
|
@@ -1,88 +1,82 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const http = require("http");
|
|
7
|
-
const lib_prod_1 = require("tnp-core/lib-prod");
|
|
1
|
+
import RequestHandler from "./request-handler.backend";
|
|
2
|
+
import Summary from "./summary.backend";
|
|
3
|
+
import TapeStore from "./tape-store.backend";
|
|
4
|
+
import * as http from "http";
|
|
5
|
+
import { https, fse } from "tnp-core/lib-prod";
|
|
8
6
|
class TalkbackServer {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
options;
|
|
8
|
+
tapeStore;
|
|
9
|
+
requestHandler;
|
|
10
|
+
closeSignalHandler;
|
|
11
|
+
server;
|
|
12
|
+
closed = false;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = options;
|
|
15
|
+
this.tapeStore = new TapeStore(this.options);
|
|
16
|
+
this.requestHandler = new RequestHandler(this.tapeStore, this.options);
|
|
17
|
+
this.closeSignalHandler = this.close.bind(this);
|
|
18
|
+
}
|
|
19
|
+
handleRequest(rawReq, res) {
|
|
20
|
+
let reqBody = [];
|
|
21
|
+
rawReq.on("data", (chunk) => {
|
|
22
|
+
reqBody.push(chunk);
|
|
23
|
+
}).on("end", async () => {
|
|
24
|
+
try {
|
|
25
|
+
const req = {
|
|
26
|
+
headers: rawReq.headers,
|
|
27
|
+
url: rawReq.url,
|
|
28
|
+
method: rawReq.method,
|
|
29
|
+
body: Buffer.concat(reqBody)
|
|
30
|
+
};
|
|
31
|
+
const fRes = await this.requestHandler.handle(req);
|
|
32
|
+
res.writeHead(fRes.status, fRes.headers);
|
|
33
|
+
res.end(fRes.body);
|
|
34
|
+
} catch (ex) {
|
|
35
|
+
console.error("Error handling request", ex);
|
|
36
|
+
res.statusCode = 500;
|
|
37
|
+
res.end();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
async start(callback) {
|
|
42
|
+
await this.tapeStore.load();
|
|
43
|
+
const handleRequest = this.handleRequest.bind(this);
|
|
44
|
+
const serverFactory = this.options.https.enabled ? () => {
|
|
45
|
+
const httpsOpts = {
|
|
46
|
+
key: fse.readFileSync(this.options.https.keyPath),
|
|
47
|
+
cert: fse.readFileSync(this.options.https.certPath)
|
|
48
|
+
};
|
|
49
|
+
return https.createServer(httpsOpts, handleRequest);
|
|
50
|
+
} : () => http.createServer(handleRequest);
|
|
51
|
+
this.server = serverFactory();
|
|
52
|
+
console.log(`Starting talkback on ${this.options.port}`);
|
|
53
|
+
this.server.listen(this.options.port, callback);
|
|
54
|
+
process.on("exit", this.closeSignalHandler);
|
|
55
|
+
process.on("SIGINT", this.closeSignalHandler);
|
|
56
|
+
process.on("SIGTERM", this.closeSignalHandler);
|
|
57
|
+
return this.server;
|
|
58
|
+
}
|
|
59
|
+
hasTapeBeenUsed(tapeName) {
|
|
60
|
+
return this.tapeStore.hasTapeBeenUsed(tapeName);
|
|
61
|
+
}
|
|
62
|
+
resetTapeUsage() {
|
|
63
|
+
this.tapeStore.resetTapeUsage();
|
|
64
|
+
}
|
|
65
|
+
close(callback) {
|
|
66
|
+
if (this.closed) {
|
|
67
|
+
return;
|
|
20
68
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
headers: rawReq.headers,
|
|
30
|
-
url: rawReq.url,
|
|
31
|
-
method: rawReq.method,
|
|
32
|
-
body: Buffer.concat(reqBody)
|
|
33
|
-
};
|
|
34
|
-
const fRes = await this.requestHandler.handle(req);
|
|
35
|
-
res.writeHead(fRes.status, fRes.headers);
|
|
36
|
-
res.end(fRes.body);
|
|
37
|
-
}
|
|
38
|
-
catch (ex) {
|
|
39
|
-
console.error("Error handling request", ex);
|
|
40
|
-
res.statusCode = 500;
|
|
41
|
-
res.end();
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
async start(callback) {
|
|
46
|
-
await this.tapeStore.load();
|
|
47
|
-
const handleRequest = this.handleRequest.bind(this);
|
|
48
|
-
const serverFactory = this.options.https.enabled ? () => {
|
|
49
|
-
const httpsOpts = {
|
|
50
|
-
key: lib_prod_1.fse.readFileSync(this.options.https.keyPath),
|
|
51
|
-
cert: lib_prod_1.fse.readFileSync(this.options.https.certPath)
|
|
52
|
-
};
|
|
53
|
-
return lib_prod_1.https.createServer(httpsOpts, handleRequest);
|
|
54
|
-
} : () => http.createServer(handleRequest);
|
|
55
|
-
this.server = serverFactory();
|
|
56
|
-
console.log(`Starting talkback on ${this.options.port}`);
|
|
57
|
-
this.server.listen(this.options.port, callback);
|
|
58
|
-
process.on("exit", this.closeSignalHandler);
|
|
59
|
-
process.on("SIGINT", this.closeSignalHandler);
|
|
60
|
-
process.on("SIGTERM", this.closeSignalHandler);
|
|
61
|
-
return this.server;
|
|
62
|
-
}
|
|
63
|
-
hasTapeBeenUsed(tapeName) {
|
|
64
|
-
return this.tapeStore.hasTapeBeenUsed(tapeName);
|
|
65
|
-
}
|
|
66
|
-
resetTapeUsage() {
|
|
67
|
-
this.tapeStore.resetTapeUsage();
|
|
68
|
-
}
|
|
69
|
-
close(callback) {
|
|
70
|
-
if (this.closed) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
this.closed = true;
|
|
74
|
-
this.server.close(callback);
|
|
75
|
-
// @ts-ignore
|
|
76
|
-
process.removeListener("exit", this.closeSignalHandler);
|
|
77
|
-
// @ts-ignore
|
|
78
|
-
process.removeListener("SIGINT", this.closeSignalHandler);
|
|
79
|
-
// @ts-ignore
|
|
80
|
-
process.removeListener("SIGTERM", this.closeSignalHandler);
|
|
81
|
-
if (this.options.summary) {
|
|
82
|
-
const summary = new summary_backend_1.default(this.tapeStore.tapes, this.options);
|
|
83
|
-
summary.print();
|
|
84
|
-
}
|
|
69
|
+
this.closed = true;
|
|
70
|
+
this.server.close(callback);
|
|
71
|
+
process.removeListener("exit", this.closeSignalHandler);
|
|
72
|
+
process.removeListener("SIGINT", this.closeSignalHandler);
|
|
73
|
+
process.removeListener("SIGTERM", this.closeSignalHandler);
|
|
74
|
+
if (this.options.summary) {
|
|
75
|
+
const summary = new Summary(this.tapeStore.tapes, this.options);
|
|
76
|
+
summary.print();
|
|
85
77
|
}
|
|
78
|
+
}
|
|
86
79
|
}
|
|
87
|
-
|
|
88
|
-
|
|
80
|
+
export {
|
|
81
|
+
TalkbackServer as default
|
|
82
|
+
};
|
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
1
|
class Summary {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
tapes;
|
|
3
|
+
opts;
|
|
4
|
+
constructor(tapes, opts) {
|
|
5
|
+
this.tapes = tapes;
|
|
6
|
+
this.opts = opts;
|
|
7
|
+
}
|
|
8
|
+
print() {
|
|
9
|
+
console.log(`===== SUMMARY (${this.opts.name}) =====`);
|
|
10
|
+
const newTapes = this.tapes.filter((t) => t.new);
|
|
11
|
+
if (newTapes.length > 0) {
|
|
12
|
+
console.log("New tapes:");
|
|
13
|
+
newTapes.forEach((t) => console.log(`- ${t.path}`));
|
|
9
14
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
console.log("New tapes:");
|
|
15
|
-
newTapes.forEach(t => console.log(`- ${t.path}`));
|
|
16
|
-
}
|
|
17
|
-
const unusedTapes = this.tapes.filter(t => !t.used);
|
|
18
|
-
if (unusedTapes.length > 0) {
|
|
19
|
-
console.log("Unused tapes:");
|
|
20
|
-
unusedTapes.forEach(t => console.log(`- ${t.path}`));
|
|
21
|
-
}
|
|
15
|
+
const unusedTapes = this.tapes.filter((t) => !t.used);
|
|
16
|
+
if (unusedTapes.length > 0) {
|
|
17
|
+
console.log("Unused tapes:");
|
|
18
|
+
unusedTapes.forEach((t) => console.log(`- ${t.path}`));
|
|
22
19
|
}
|
|
20
|
+
}
|
|
23
21
|
}
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
export {
|
|
23
|
+
Summary as default
|
|
24
|
+
};
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const server_backend_1 = require("./server.backend");
|
|
6
|
-
const request_handler_backend_1 = require("./request-handler.backend");
|
|
1
|
+
import Options from "./options.backend";
|
|
2
|
+
import TapeStore from "./tape-store.backend";
|
|
3
|
+
import TalkbackServer from "./server.backend";
|
|
4
|
+
import RequestHandler from "./request-handler.backend";
|
|
7
5
|
class TalkbackFactory {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
static server(options) {
|
|
7
|
+
const fullOptions = Options.prepare(options);
|
|
8
|
+
return new TalkbackServer(fullOptions);
|
|
9
|
+
}
|
|
10
|
+
static async requestHandler(options) {
|
|
11
|
+
const fullOptions = Options.prepare(options);
|
|
12
|
+
const tapeStore = new TapeStore(fullOptions);
|
|
13
|
+
await tapeStore.load();
|
|
14
|
+
return new RequestHandler(tapeStore, fullOptions);
|
|
15
|
+
}
|
|
18
16
|
}
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
export {
|
|
18
|
+
TalkbackFactory as default
|
|
19
|
+
};
|
|
@@ -1,97 +1,95 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const media_type_backend_1 = require("./utils/media-type.backend");
|
|
5
|
-
const lib_prod_1 = require("tnp-core/lib-prod");
|
|
1
|
+
import ContentEncoding from "./utils/content-encoding.backend";
|
|
2
|
+
import MediaType from "./utils/media-type.backend";
|
|
3
|
+
import { ___NS__isEqual } from "tnp-core/lib-prod";
|
|
6
4
|
class TapeMatcher {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
tape;
|
|
6
|
+
options;
|
|
7
|
+
constructor(tape, options) {
|
|
8
|
+
this.tape = tape;
|
|
9
|
+
this.options = options;
|
|
10
|
+
}
|
|
11
|
+
sameAs(otherTape) {
|
|
12
|
+
const otherReq = otherTape.req;
|
|
13
|
+
const req = this.tape.req;
|
|
14
|
+
if (!this.isSameUrl(req, otherReq)) {
|
|
15
|
+
return false;
|
|
12
16
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const req = this.tape.req;
|
|
16
|
-
if (!this.isSameUrl(req, otherReq)) {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
if (!this.isSameMethod(req, otherReq)) {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
if (!this.isSameHeaders(req, otherReq)) {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
return this.options.ignoreBody || this.isSameBody(req, otherReq);
|
|
17
|
+
if (!this.isSameMethod(req, otherReq)) {
|
|
18
|
+
return false;
|
|
26
19
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const contentEncoding = new content_encoding_backend_1.default(req);
|
|
30
|
-
let sameBody;
|
|
31
|
-
if (contentEncoding.isUncompressed() && mediaType.isJSON() && req.body.length > 0 && otherReq.body.length > 0) {
|
|
32
|
-
const parsedReqBody = JSON.parse(req.body.toString());
|
|
33
|
-
const parsedOtherReqBody = JSON.parse(otherReq.body.toString());
|
|
34
|
-
sameBody = lib_prod_1._.isEqual(parsedReqBody, parsedOtherReqBody);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
sameBody = req.body.equals(otherReq.body);
|
|
38
|
-
}
|
|
39
|
-
if (!sameBody) {
|
|
40
|
-
if (!this.options.bodyMatcher) {
|
|
41
|
-
this.options.logger.debug(`Not same BODY ${req.body} vs ${otherReq.body}`);
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
const bodyMatches = this.options.bodyMatcher(this.tape, otherReq);
|
|
45
|
-
if (!bodyMatches) {
|
|
46
|
-
this.options.logger.debug(`Not same bodyMatcher ${req.body} vs ${otherReq.body}`);
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return true;
|
|
20
|
+
if (!this.isSameHeaders(req, otherReq)) {
|
|
21
|
+
return false;
|
|
51
22
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
headersSame = headersSame && entryHeader === header;
|
|
65
|
-
});
|
|
66
|
-
if (!headersSame) {
|
|
67
|
-
this.options.logger.debug(`Not same HEADERS values ${JSON.stringify(req.headers)} vs ${JSON.stringify(otherReq.headers)}`);
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
return true;
|
|
23
|
+
return this.options.ignoreBody || this.isSameBody(req, otherReq);
|
|
24
|
+
}
|
|
25
|
+
isSameBody(req, otherReq) {
|
|
26
|
+
const mediaType = new MediaType(req);
|
|
27
|
+
const contentEncoding = new ContentEncoding(req);
|
|
28
|
+
let sameBody;
|
|
29
|
+
if (contentEncoding.isUncompressed() && mediaType.isJSON() && req.body.length > 0 && otherReq.body.length > 0) {
|
|
30
|
+
const parsedReqBody = JSON.parse(req.body.toString());
|
|
31
|
+
const parsedOtherReqBody = JSON.parse(otherReq.body.toString());
|
|
32
|
+
sameBody = ___NS__isEqual(parsedReqBody, parsedOtherReqBody);
|
|
33
|
+
} else {
|
|
34
|
+
sameBody = req.body.equals(otherReq.body);
|
|
71
35
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
36
|
+
if (!sameBody) {
|
|
37
|
+
if (!this.options.bodyMatcher) {
|
|
38
|
+
this.options.logger.debug(`Not same BODY ${req.body} vs ${otherReq.body}`);
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const bodyMatches = this.options.bodyMatcher(this.tape, otherReq);
|
|
42
|
+
if (!bodyMatches) {
|
|
43
|
+
this.options.logger.debug(`Not same bodyMatcher ${req.body} vs ${otherReq.body}`);
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
79
46
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.options.logger.debug(`Not same urlMatcher ${req.url} vs ${otherReq.url}`);
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return true;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
isSameHeaders(req, otherReq) {
|
|
50
|
+
const currentHeadersLength = Object.keys(req.headers).length;
|
|
51
|
+
const otherHeadersLength = Object.keys(otherReq.headers).length;
|
|
52
|
+
const sameNumberOfHeaders = currentHeadersLength === otherHeadersLength;
|
|
53
|
+
if (!sameNumberOfHeaders) {
|
|
54
|
+
this.options.logger.debug(`Not same #HEADERS ${JSON.stringify(req.headers)} vs ${JSON.stringify(otherReq.headers)}`);
|
|
55
|
+
return false;
|
|
94
56
|
}
|
|
57
|
+
let headersSame = true;
|
|
58
|
+
Object.keys(req.headers).forEach((k) => {
|
|
59
|
+
const entryHeader = req.headers[k];
|
|
60
|
+
const header = otherReq.headers[k];
|
|
61
|
+
headersSame = headersSame && entryHeader === header;
|
|
62
|
+
});
|
|
63
|
+
if (!headersSame) {
|
|
64
|
+
this.options.logger.debug(`Not same HEADERS values ${JSON.stringify(req.headers)} vs ${JSON.stringify(otherReq.headers)}`);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
isSameMethod(req, otherReq) {
|
|
70
|
+
const sameMethod = req.method === otherReq.method;
|
|
71
|
+
if (!sameMethod) {
|
|
72
|
+
this.options.logger.debug(`Not same METHOD ${req.method} vs ${otherReq.method}`);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
isSameUrl(req, otherReq) {
|
|
78
|
+
const sameURL = req.url === otherReq.url;
|
|
79
|
+
if (!sameURL) {
|
|
80
|
+
if (!this.options.urlMatcher) {
|
|
81
|
+
this.options.logger.debug(`Not same URL ${req.url} vs ${otherReq.url}`);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
const urlMatches = this.options.urlMatcher(this.tape, otherReq);
|
|
85
|
+
if (!urlMatches) {
|
|
86
|
+
this.options.logger.debug(`Not same urlMatcher ${req.url} vs ${otherReq.url}`);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
95
92
|
}
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
export {
|
|
94
|
+
TapeMatcher as default
|
|
95
|
+
};
|
|
@@ -1,99 +1,93 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const content_encoding_backend_1 = require("./utils/content-encoding.backend");
|
|
7
|
-
const bufferShim = require("buffer-shims");
|
|
8
|
-
// const bufferShim = require('buffer-shims')/
|
|
1
|
+
import Headers from "./utils/headers.backend";
|
|
2
|
+
import MediaType from "./utils/media-type.backend";
|
|
3
|
+
import Tape from "./tape.backend";
|
|
4
|
+
import ContentEncoding from "./utils/content-encoding.backend";
|
|
5
|
+
import * as bufferShim from "buffer-shims";
|
|
9
6
|
class TapeRenderer {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
tape;
|
|
8
|
+
constructor(tape) {
|
|
9
|
+
this.tape = tape;
|
|
10
|
+
}
|
|
11
|
+
static async fromStore(raw, options) {
|
|
12
|
+
const req = { ...raw.req };
|
|
13
|
+
req.body = await this.prepareBody(raw, req, req.body, "req");
|
|
14
|
+
const tape = new Tape(req, options);
|
|
15
|
+
tape.meta = { ...raw.meta };
|
|
16
|
+
const baseRes = { ...raw.res };
|
|
17
|
+
const resBody = await this.prepareBody(tape, baseRes, baseRes.body, "res");
|
|
18
|
+
tape.res = {
|
|
19
|
+
...baseRes,
|
|
20
|
+
body: resBody
|
|
21
|
+
};
|
|
22
|
+
return tape;
|
|
23
|
+
}
|
|
24
|
+
static async prepareBody(tape, reqResObj, rawBody, metaPrefix) {
|
|
25
|
+
const contentEncoding = new ContentEncoding(reqResObj);
|
|
26
|
+
const isTapeUncompressed = tape.meta[metaPrefix + "Uncompressed"];
|
|
27
|
+
const isTapeHumanReadable = tape.meta[metaPrefix + "HumanReadable"];
|
|
28
|
+
const isTapeInPlainText = isTapeUncompressed || contentEncoding.isUncompressed();
|
|
29
|
+
if (isTapeHumanReadable && isTapeInPlainText) {
|
|
30
|
+
const mediaType = new MediaType(reqResObj);
|
|
31
|
+
let bufferContent = rawBody;
|
|
32
|
+
const isResAnObject = typeof bufferContent === "object";
|
|
33
|
+
if (isResAnObject && mediaType.isJSON()) {
|
|
34
|
+
bufferContent = JSON.stringify(bufferContent, null, 2);
|
|
35
|
+
}
|
|
36
|
+
if (Headers.read(reqResObj.headers, "content-length")) {
|
|
37
|
+
Headers.write(reqResObj.headers, "content-length", Buffer.byteLength(bufferContent).toString(), metaPrefix);
|
|
38
|
+
}
|
|
39
|
+
if (isTapeUncompressed) {
|
|
40
|
+
return await contentEncoding.compressedBody(bufferContent);
|
|
41
|
+
}
|
|
42
|
+
return bufferShim.from(bufferContent);
|
|
43
|
+
} else {
|
|
44
|
+
return bufferShim.from(rawBody, "base64");
|
|
13
45
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
tape.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
async render() {
|
|
52
|
-
const reqBody = await this.bodyFor(this.tape.req, "req");
|
|
53
|
-
const resBody = await this.bodyFor(this.tape.res, "res");
|
|
54
|
-
return {
|
|
55
|
-
meta: this.tape.meta,
|
|
56
|
-
req: {
|
|
57
|
-
...this.tape.req,
|
|
58
|
-
body: reqBody
|
|
59
|
-
},
|
|
60
|
-
res: {
|
|
61
|
-
...this.tape.res,
|
|
62
|
-
body: resBody
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
async bodyFor(reqResObj, metaPrefix) {
|
|
67
|
-
const mediaType = new media_type_backend_1.default(reqResObj);
|
|
68
|
-
const contentEncoding = new content_encoding_backend_1.default(reqResObj);
|
|
69
|
-
const bodyLength = reqResObj.body.length;
|
|
70
|
-
const isUncompressed = contentEncoding.isUncompressed();
|
|
71
|
-
const contentEncodingSupported = isUncompressed || contentEncoding.supportedAlgorithm();
|
|
72
|
-
if (mediaType.isHumanReadable() && contentEncodingSupported && bodyLength > 0) {
|
|
73
|
-
this.tape.meta[metaPrefix + "HumanReadable"] = true;
|
|
74
|
-
let body = reqResObj.body;
|
|
75
|
-
if (!isUncompressed) {
|
|
76
|
-
this.tape.meta[metaPrefix + "Uncompressed"] = true;
|
|
77
|
-
body = await contentEncoding.uncompressedBody(body);
|
|
78
|
-
}
|
|
79
|
-
const rawBody = body.toString("utf8");
|
|
80
|
-
if (mediaType.isJSON()) {
|
|
81
|
-
try { // TODO handle this better in future not based on mediaType.isJSON
|
|
82
|
-
const parsed = JSON.parse(rawBody);
|
|
83
|
-
return parsed;
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
return rawBody;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
return rawBody;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
return reqResObj.body.toString("base64");
|
|
46
|
+
}
|
|
47
|
+
async render() {
|
|
48
|
+
const reqBody = await this.bodyFor(this.tape.req, "req");
|
|
49
|
+
const resBody = await this.bodyFor(this.tape.res, "res");
|
|
50
|
+
return {
|
|
51
|
+
meta: this.tape.meta,
|
|
52
|
+
req: {
|
|
53
|
+
...this.tape.req,
|
|
54
|
+
body: reqBody
|
|
55
|
+
},
|
|
56
|
+
res: {
|
|
57
|
+
...this.tape.res,
|
|
58
|
+
body: resBody
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async bodyFor(reqResObj, metaPrefix) {
|
|
63
|
+
const mediaType = new MediaType(reqResObj);
|
|
64
|
+
const contentEncoding = new ContentEncoding(reqResObj);
|
|
65
|
+
const bodyLength = reqResObj.body.length;
|
|
66
|
+
const isUncompressed = contentEncoding.isUncompressed();
|
|
67
|
+
const contentEncodingSupported = isUncompressed || contentEncoding.supportedAlgorithm();
|
|
68
|
+
if (mediaType.isHumanReadable() && contentEncodingSupported && bodyLength > 0) {
|
|
69
|
+
this.tape.meta[metaPrefix + "HumanReadable"] = true;
|
|
70
|
+
let body = reqResObj.body;
|
|
71
|
+
if (!isUncompressed) {
|
|
72
|
+
this.tape.meta[metaPrefix + "Uncompressed"] = true;
|
|
73
|
+
body = await contentEncoding.uncompressedBody(body);
|
|
74
|
+
}
|
|
75
|
+
const rawBody = body.toString("utf8");
|
|
76
|
+
if (mediaType.isJSON()) {
|
|
77
|
+
try {
|
|
78
|
+
const parsed = JSON.parse(rawBody);
|
|
79
|
+
return parsed;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
return rawBody;
|
|
95
82
|
}
|
|
83
|
+
} else {
|
|
84
|
+
return rawBody;
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
return reqResObj.body.toString("base64");
|
|
96
88
|
}
|
|
89
|
+
}
|
|
97
90
|
}
|
|
98
|
-
|
|
99
|
-
|
|
91
|
+
export {
|
|
92
|
+
TapeRenderer as default
|
|
93
|
+
};
|