-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathrequestbinCurl.js
More file actions
216 lines (171 loc) · 5.92 KB
/
requestbinCurl.js
File metadata and controls
216 lines (171 loc) · 5.92 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
const usageStr =
`USAGE:
node requestbinCurl.js http://requestb.in/1234asdf?inspect
node requestbinCurl.js http://requestb.in/1234asdf?inspect#13mgnv -p
node requestbinCurl.js requestb.in/1234asdf`;
const https = require('https');
// get the url form the command line arguments
const url = process.argv[2];
const prettyPrint = process.argv[3] === '-p';
if (!url) {
console.error(usageStr);
return process.exit(1);
}
// parse the URL
const result = parseRBUrl(url);
if (!result || !result.rbBinId) {
console.error('Unrecognized RequestBin URL.');
return process.exit(1);
}
const {rbBinId, rbRequestId} = result;
// get a RequestBin request based on the params parsed from the URL
getTargetedRBRequest(rbBinId, rbRequestId, (fatalErr, err, rbRequest) => {
if (fatalErr) throw fatalErr;
if (err) {
console.error(err.message);
return process.exit(1);
}
if (!rbRequest) {
console.error('');
}
// convert the RequestBin request into a curl command
const curlCommand = createCurlCommandFromRBRequest(rbRequest, prettyPrint);
console.log(curlCommand);
return process.exit(0);
});
function parseRBUrl(rbUrl) {
const regexPattern =
'^\\s*' + // start of string with optional leading whitespace
'(https?://)?' + // optional http(s) protocol
'(www\\.)?' + // optional www subdomain
'requestb\\.in' + // domain
'(:\\d+)?' + // optional port
'/(.+?)' + // path
'(\\?.*?)?' + // optional query string params
'(#(.*?))?' + // optional anchor
'\\s*$'; // end of string with optional trailing whitespace
const regexFlags = 'i'; // ignore case (eh, why not?)
const regex = new RegExp(regexPattern, regexFlags);
const result = regex.exec(rbUrl);
if (!result) {
return null;
}
const encodedRBBinId = result[4];
const encodedRBRequestId = result[7];
const rbBinId = encodedRBBinId ? decodeURIComponent(encodedRBBinId ) : null;
const rbRequestId = encodedRBRequestId? decodeURIComponent(encodedRBRequestId) : null;
return {
rbBinId,
rbRequestId
};
}
function getTargetedRBRequest(rbBinId, rbRequestId, cb) {
// get either the RequestBin request with the given ID or the latest request from the bin
if (rbRequestId) {
return getRBRequest(rbBinId, rbRequestId, (fatalErr, err, rbRequest) => {
return cb(fatalErr, err, rbRequest);
});
}
else {
return getRBBinRequests(rbBinId, (fatalErr, err, rbRequests) => {
if (fatalErr) return cb(fatalErr);
if (err) return cb(null, err);
if (rbRequests.length === 0) {
return cb(null, new Error('No RequestBin requests exist in bin with ID "' + rbBinId + '".'));
}
// get the newest/latest/most recent RequestBin request
let latestRBRequest = rbRequests[0];
for (let i = 0; i < rbRequests.length; ++i) {
const rbRequest = rbRequests[i];
if (rbRequest.time > latestRBRequest.time) {
latestRBRequest = rbRequest;
}
}
return cb(null, null, latestRBRequest);
});
}
}
function getRBBinRequests(rbBinId, cb) {
const endpoint = `/bins/${rbBinId}/requests`;
callRBAPI(endpoint, (err, result) => {
if (err) return cb(err);
if (result.res.statusCode !== 200 || !Array.isArray(result.body)) {
return cb(null, new Error(`Unrecognized response from RequestBin API.\nURL: ${result.url}\nStatus: ${result.res.statusCode}\n${result.bodyStr}`));
}
const rbRequests = result.body;
return cb(null, null, rbRequests);
});
}
function getRBRequest(rbBinId, rbRequestId, cb) {
let endpoint = `/bins/${rbBinId}/requests/${rbRequestId}`;
callRBAPI(endpoint, (err, result) => {
if (err) return cb(err);
if (result.res.statusCode !== 200 || typeof result.body !== 'object' || result.body === null || Array.isArray(result.body)) {
return cb(null, new Error(`Unrecognized response from RequestBin API.\nURL: ${result.url}\nStatus: ${result.res.statusCode}\n${result.bodyStr}`));
}
let rbRequest = result.body;
return cb(null, null, rbRequest);
});
}
function callRBAPI(endpoint, cb) {
const url = `https://requestb.in/api/v1${endpoint}`;
const req = https.get(url, res => {
res.setEncoding('utf8');
let bodyStr = '';
res.on('data', chunk => bodyStr += chunk);
res.on('end', () => {
let body = null;
try {
body = JSON.parse(bodyStr);
}
catch(err) {}
return cb(null, {
url,
res,
bodyStr,
body
});
});
});
req.on('error', err => {
return cb(err);
});
}
function createCurlCommandFromRBRequest(rbRequest, prettyPrint) {
const args = [];
// set the method
args.push('-X ' + escapeShellArg(rbRequest.method));
// set the headers
for (let headerName in rbRequest.headers) {
const headerVal = rbRequest.headers[headerName];
args.push('-H ' + escapeShellArg(headerName + ': ' + headerVal));
}
// set the body
args.push('-d ' + escapeShellArg(rbRequest.raw));
// set query string param part of the URL
let qsParamsStr = createQSParamsStr(rbRequest.query_string);
let url = qsParamsStr;
args.push(escapeShellArg(url));
// create the cURL command
const sepStr = prettyPrint? ' \\\n ' : ' ';
const curlCommand = 'curl' + sepStr + args.join(sepStr);
return curlCommand;
}
function createQSParamsStr(qsParamMap) {
let qsParamsStr = '';
for (let qsParamName in qsParamMap) {
const qsParamVal = qsParamMap[qsParamName];
if (qsParamsStr.length === 0) {
qsParamsStr += '?';
}
else {
qsParamsStr += '&';
}
// RequestBin decodes the query string params (gumble grumble...) so we need to re-encode them
qsParamsStr += encodeURIComponent(qsParamName) + '=' + encodeURIComponent(qsParamVal);
}
return qsParamsStr;
}
function escapeShellArg(str) {
return '\'' + str.replace(/'/g, '\'\\\'\'') + '\''; // replace ' with '\\''
}