-
Notifications
You must be signed in to change notification settings - Fork 3.5k
/
Copy pathHTTPRequest.mjs
152 lines (133 loc) · 4.85 KB
/
HTTPRequest.mjs
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
/**
* @author tlwr [[email protected]]
* @author n1474335 [[email protected]]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* HTTP request operation
*/
class HTTPRequest extends Operation {
/**
* HTTPRequest constructor
*/
constructor() {
super();
this.name = "HTTP request";
this.module = "Default";
this.description = [
"Makes an HTTP request and returns the response.",
"<br><br>",
"This operation supports different HTTP verbs like GET, POST, PUT, etc.",
"<br><br>",
"You can add headers line by line in the format <code>Key: Value</code>",
"<br><br>",
"The status code of the response, along with a limited selection of exposed headers, can be viewed by checking the 'Show response metadata' option. Only a limited set of response headers are exposed by the browser for security reasons.",
].join("\n");
this.infoURL = "https://wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields";
this.inputType = "string";
this.outputType = "ArrayBuffer";
this.manualBake = true;
this.args = [
{
"name": "Method",
"type": "option",
"value": [
"GET", "POST", "HEAD",
"PUT", "PATCH", "DELETE",
"CONNECT", "TRACE", "OPTIONS"
]
},
{
"name": "URL",
"type": "string",
"value": ""
},
{
"name": "Headers",
"type": "text",
"value": ""
},
{
"name": "Mode",
"type": "option",
"value": [
"Cross-Origin Resource Sharing",
"No CORS (limited to HEAD, GET or POST)",
]
},
{
"name": "Show response metadata",
"type": "boolean",
"value": false
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
const [method, url, headersText, mode, showResponseMetadata] = args;
if (url.length === 0) return new Uint8Array(0).buffer;
const headers = new Headers();
headersText.split(/\r?\n/).forEach(line => {
line = line.trim();
if (line.length === 0) return;
const split = line.split(":");
if (split.length !== 2) throw `Could not parse header in line: ${line}`;
headers.set(split[0].trim(), split[1].trim());
});
const config = {
method: method,
headers: headers,
mode: modeLookup[mode],
cache: "no-cache",
};
if (method !== "GET" && method !== "HEAD") {
config.body = input;
}
return fetch(url, config)
.then(r => {
if (r.status === 0 && r.type === "opaque") {
throw new OperationError("Error: Null response. Try setting the connection mode to CORS.");
}
if (showResponseMetadata) {
let headers = "";
for (const pair of r.headers.entries()) {
headers += " " + pair[0] + ": " + pair[1] + "\n";
}
return r.arrayBuffer().then(b => {
const headerArray = new TextEncoder().encode(
"####\n Status: " + r.status + " " + r.statusText +
"\n Exposed headers:\n" + headers + "####\n\n");
const resultArray = new Uint8Array(headerArray.byteLength + b.byteLength);
resultArray.set(headerArray, 0);
resultArray.set(new Uint8Array(b), headerArray.byteLength);
return resultArray.buffer;
});
}
return r.arrayBuffer();
})
.catch(e => {
throw new OperationError(e.toString() +
"\n\nThis error could be caused by one of the following:\n" +
" - An invalid URL\n" +
" - Making a request to an insecure resource (HTTP) from a secure source (HTTPS)\n" +
" - Making a cross-origin request to a server which does not support CORS\n");
});
}
}
/**
* Lookup table for HTTP modes
*
* @private
*/
const modeLookup = {
"Cross-Origin Resource Sharing": "cors",
"No CORS (limited to HEAD, GET or POST)": "no-cors",
};
export default HTTPRequest;