1 | ;
|
2 | /**
|
3 | * @license
|
4 | * Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
|
5 | * This code may only be used under the BSD style license found at
|
6 | * http://polymer.github.io/LICENSE.txt
|
7 | * The complete set of authors may be found at
|
8 | * http://polymer.github.io/AUTHORS.txt
|
9 | * The complete set of contributors may be found at
|
10 | * http://polymer.github.io/CONTRIBUTORS.txt
|
11 | * Code distributed by Google as part of the polymer project is also
|
12 | * subject to an additional IP rights grant found at
|
13 | * http://polymer.github.io/PATENTS.txt
|
14 | */
|
15 | Object.defineProperty(exports, "__esModule", { value: true });
|
16 | function transformResponse(transformer) {
|
17 | return (req, res, next) => {
|
18 | let ended = false;
|
19 | const chunks = [];
|
20 | let _shouldTransform = null;
|
21 | // Note: this function memoizes its result.
|
22 | function shouldTransform() {
|
23 | if (_shouldTransform == null) {
|
24 | const successful = res.statusCode >= 200 && res.statusCode < 300;
|
25 | _shouldTransform =
|
26 | successful && !!transformer.shouldTransform(req, res);
|
27 | }
|
28 | return _shouldTransform;
|
29 | }
|
30 | // Cast is required because this method is overloaded, but assigning a
|
31 | // method to a variable seems to pick only one of the overload signatures.
|
32 | const _write = res.write;
|
33 | res.write = function (chunk, cbOrEncoding, cb) {
|
34 | if (ended) {
|
35 | _write.call(this, chunk, cbOrEncoding, cb);
|
36 | return false;
|
37 | }
|
38 | if (shouldTransform()) {
|
39 | const buffer = (typeof chunk === 'string') ?
|
40 | Buffer.from(chunk, cbOrEncoding) :
|
41 | chunk;
|
42 | chunks.push(buffer);
|
43 | return true;
|
44 | }
|
45 | else {
|
46 | return _write.call(this, chunk, cbOrEncoding, cb);
|
47 | }
|
48 | };
|
49 | // Cast is required because this method is overloaded, but assigning a
|
50 | // method to a variable seems to pick only one of the overload signatures.
|
51 | const _end = res.end;
|
52 | res.end = function (cbOrChunk, cbOrEncoding, cb) {
|
53 | if (ended) {
|
54 | return;
|
55 | }
|
56 | ended = true;
|
57 | if (shouldTransform()) {
|
58 | if (Buffer.isBuffer(cbOrChunk)) {
|
59 | chunks.push(cbOrChunk);
|
60 | }
|
61 | else if (typeof cbOrChunk === 'string') {
|
62 | chunks.push(Buffer.from(cbOrChunk, cbOrEncoding));
|
63 | }
|
64 | const body = Buffer.concat(chunks).toString('utf8');
|
65 | let newBody = body;
|
66 | try {
|
67 | newBody = transformer.transform(req, res, body);
|
68 | }
|
69 | catch (e) {
|
70 | console.warn('Error', e);
|
71 | }
|
72 | // TODO(justinfagnani): re-enable setting of content-length when we know
|
73 | // why it was causing truncated files. Could be multi-byte characters.
|
74 | // Assumes single-byte code points!
|
75 | // res.setHeader('Content-Length', `${newBody.length}`);
|
76 | res.removeHeader('Content-Length');
|
77 | // TODO(aomarks) Shouldn't we call the callbacks?
|
78 | return _end.call(this, newBody);
|
79 | }
|
80 | else {
|
81 | return _end.call(this, cbOrChunk, cbOrEncoding, cb);
|
82 | }
|
83 | };
|
84 | next();
|
85 | };
|
86 | }
|
87 | exports.transformResponse = transformResponse;
|
88 | //# sourceMappingURL=transform-middleware.js.map |
\ | No newline at end of file |