forked from Kong/httpsnippet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttpsnippet.js
More file actions
233 lines (233 loc) · 11.5 KB
/
Copy pathhttpsnippet.js
File metadata and controls
233 lines (233 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
exports.HTTPSnippet = exports.addTargetClient = exports.addTarget = exports.extname = exports.availableTargets = void 0;
var form_data_1 = __importDefault(require("form-data"));
var querystring_1 = require("querystring");
var url_1 = require("url");
var form_data_2 = require("./helpers/form-data");
var har_validator_1 = require("./helpers/har-validator");
var headers_1 = require("./helpers/headers");
var reducer_1 = require("./helpers/reducer");
var targets_1 = require("./targets/targets");
var utils_1 = require("./helpers/utils");
__createBinding(exports, utils_1, "availableTargets");
__createBinding(exports, utils_1, "extname");
var targets_2 = require("./targets/targets");
__createBinding(exports, targets_2, "addTarget");
__createBinding(exports, targets_2, "addTargetClient");
var DEBUG_MODE = false;
var debug = {
// eslint-disable-next-line @typescript-eslint/no-empty-function -- intentional noop
info: DEBUG_MODE ? console.info : function () { }
};
var isHarEntry = function (value) {
return typeof value === 'object' &&
'log' in value &&
typeof value.log === 'object' &&
'entries' in value.log &&
Array.isArray(value.log.entries);
};
var HTTPSnippet = /** @class */ (function () {
function HTTPSnippet(input) {
var _this = this;
this.requests = [];
this.prepare = function (harRequest) {
var e_1, _a;
var _b, _c, _d;
var request = __assign(__assign({}, harRequest), { fullUrl: '', uriObj: {}, queryObj: {}, headersObj: {}, cookiesObj: {}, allHeaders: {} });
// construct query objects
if (request.queryString && request.queryString.length) {
debug.info('queryString found, constructing queryString pair map');
request.queryObj = request.queryString.reduce(reducer_1.reducer, {});
}
// construct headers objects
if (request.headers && request.headers.length) {
var http2VersionRegex_1 = /^HTTP\/2/;
request.headersObj = request.headers.reduce(function (accumulator, _a) {
var _b;
var name = _a.name, value = _a.value;
var headerName = http2VersionRegex_1.exec(request.httpVersion)
? name.toLocaleLowerCase()
: name;
return __assign(__assign({}, accumulator), (_b = {}, _b[headerName] = value, _b));
}, {});
}
// construct headers objects
if (request.cookies && request.cookies.length) {
request.cookiesObj = request.cookies.reduceRight(function (accumulator, _a) {
var _b;
var name = _a.name, value = _a.value;
return (__assign(__assign({}, accumulator), (_b = {}, _b[name] = value, _b)));
}, {});
}
// construct Cookie header
var cookies = (_b = request.cookies) === null || _b === void 0 ? void 0 : _b.map(function (_a) {
var name = _a.name, value = _a.value;
return "".concat(encodeURIComponent(name), "=").concat(encodeURIComponent(value));
});
if (cookies === null || cookies === void 0 ? void 0 : cookies.length) {
request.allHeaders.cookie = cookies.join('; ');
}
switch (request.postData.mimeType) {
case 'multipart/mixed':
case 'multipart/related':
case 'multipart/form-data':
case 'multipart/alternative':
// reset values
request.postData.text = '';
request.postData.mimeType = 'multipart/form-data';
if ((_c = request.postData) === null || _c === void 0 ? void 0 : _c.params) {
var form_1 = new form_data_1["default"]();
// TODO: THIS ABSOLUTELY MUST BE REMOVED.
// IT BREAKS SOME USE-CASES FOR MULTIPART FORMS THAT DEPEND ON BEING ABLE TO SET THE BOUNDARY.
// easter egg
var boundary = '---011000010111000001101001'; // this is binary for "api". yep.
(_d = request.postData) === null || _d === void 0 ? void 0 : _d.params.forEach(function (param) {
var name = param.name;
var value = param.value || '';
var filename = param.fileName || null;
if ((0, form_data_2.isBlob)(value)) {
// @ts-expect-error TODO
form_1.append(name, value, filename);
}
else {
form_1.append(name, value);
}
});
try {
for (var _e = __values((0, form_data_2.formDataIterator)(form_1, boundary)), _f = _e.next(); !_f.done; _f = _e.next()) {
var data_1 = _f.value;
request.postData.text += data_1;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_f && !_f.done && (_a = _e["return"])) _a.call(_e);
}
finally { if (e_1) throw e_1.error; }
}
request.postData.boundary = boundary;
// Since headers are case-sensitive we need to see if there's an existing `Content-Type` header that we can override.
var contentTypeHeader = (0, headers_1.getHeaderName)(request.headersObj, 'content-type') || 'content-type';
request.headersObj[contentTypeHeader] = "multipart/form-data; boundary=".concat(boundary);
}
break;
case 'application/x-www-form-urlencoded':
if (!request.postData.params) {
request.postData.text = '';
}
else {
// @ts-expect-error the `har-format` types make this challenging
request.postData.paramsObj = request.postData.params.reduce(reducer_1.reducer, {});
// always overwrite
request.postData.text = (0, querystring_1.stringify)(request.postData.paramsObj);
}
break;
case 'text/json':
case 'text/x-json':
case 'application/json':
case 'application/x-json':
request.postData.mimeType = 'application/json';
if (request.postData.text) {
try {
request.postData.jsonObj = JSON.parse(request.postData.text);
}
catch (e) {
debug.info(e);
// force back to `text/plain` if headers have proper content-type value, then this should also work
request.postData.mimeType = 'text/plain';
}
}
break;
}
// create allHeaders object
var allHeaders = __assign(__assign({}, request.allHeaders), request.headersObj);
var urlWithParsedQuery = (0, url_1.parse)(request.url, true, true); //?
// query string key/value pairs in with literal querystrings containd within the url
request.queryObj = __assign(__assign({}, request.queryObj), urlWithParsedQuery.query); //?
// reset uriObj values for a clean url
var search = (0, querystring_1.stringify)(request.queryObj);
var uriObj = __assign(__assign({}, urlWithParsedQuery), { query: request.queryObj, search: search, path: search ? "".concat(urlWithParsedQuery.pathname, "?").concat(search) : urlWithParsedQuery.pathname });
// keep the base url clean of queryString
var url = (0, url_1.format)(__assign(__assign({}, urlWithParsedQuery), { query: null, search: null })); //?
var fullUrl = (0, url_1.format)(__assign(__assign({}, urlWithParsedQuery), uriObj)); //?
return __assign(__assign({}, request), { allHeaders: allHeaders, fullUrl: fullUrl, url: url, uriObj: uriObj });
};
this.convert = function (targetId, clientId, options) {
if (!options && clientId) {
options = clientId;
}
var target = targets_1.targets[targetId];
if (!target) {
return false;
}
var convert = target.clientsById[clientId || target.info["default"]].convert;
var results = _this.requests.map(function (request) { return convert(request, options); });
return results.length === 1 ? results[0] : results;
};
var entries = [];
// prep the main container
this.requests = [];
// is it har?
if (isHarEntry(input)) {
entries = input.log.entries;
}
else {
entries = [
{
request: input
},
];
}
entries.forEach(function (_a) {
var _b;
var request = _a.request;
// add optional properties to make validation successful
var req = __assign({ bodySize: 0, headersSize: 0, headers: [], cookies: [], httpVersion: 'HTTP/1.1', queryString: [], postData: {
mimeType: ((_b = request.postData) === null || _b === void 0 ? void 0 : _b.mimeType) || 'application/octet-stream'
} }, request);
if ((0, har_validator_1.validateHarRequest)(req)) {
_this.requests.push(_this.prepare(req));
}
});
}
return HTTPSnippet;
}());
exports.HTTPSnippet = HTTPSnippet;