flagpole
Version:
Simple and fast DOM integration, headless or headful browser, and REST API testing framework.
382 lines • 11.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpRequest = exports.HttpMethodVerbAllowedValues = void 0;
const httpresponse_1 = require("./httpresponse");
const needle = require("needle");
const tunnel = require("tunnel");
const FormData = require("form-data");
const form_urlencoded_1 = require("form-urlencoded");
const image_probe_1 = require("@zerodeps/image-probe");
const flagpoleexecution_1 = require("./flagpoleexecution");
const CONTENT_TYPE_JSON = "application/json";
const CONTENT_TYPE_FORM_MULTIPART = "multipart/form-data";
const CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
const ENCODING_GZIP = "gzip,deflate";
exports.HttpMethodVerbAllowedValues = [
"get",
"head",
"delete",
"patch",
"post",
"put",
"options",
];
class HttpRequest {
constructor(opts) {
this._uri = null;
this._method = "get";
this._headers = {};
this._cookies = {};
this._verifyCert = false;
this._timeout = { open: 10000 };
this._maxRedirects = 10;
this._fetched = false;
this._browser = {};
this._type = "generic";
this.setOptions(opts);
}
get uri() {
return this._uri;
}
set uri(value) {
if (!this.isImmutable) {
this._uri = value;
}
}
get method() {
return this._method;
}
set method(value) {
if (!this.isImmutable) {
this._method = value;
}
}
get type() {
return this._type;
}
set type(value) {
if (!this.isImmutable) {
this._type = value;
if (value === "json") {
this.headers["Content-Type"] = CONTENT_TYPE_JSON;
}
}
}
get headers() {
return this._headers;
}
set headers(value) {
if (!this.isImmutable) {
this._headers = value;
}
}
get cookies() {
return this._cookies;
}
set cookies(value) {
if (!this.isImmutable) {
this._cookies = value;
}
}
get auth() {
return this._auth;
}
set auth(value) {
if (!this.isImmutable) {
this._auth = value;
}
}
get authType() {
return this._authType;
}
set authType(value) {
if (!this.isImmutable) {
this._authType = value;
}
}
get maxRedirects() {
return this._maxRedirects;
}
set maxRedirects(value) {
if (!this.isImmutable) {
this._maxRedirects = value;
}
}
get timeout() {
return this._timeout;
}
set timeout(value) {
if (!this.isImmutable) {
this._timeout = value;
}
}
get proxy() {
return this._proxy;
}
set proxy(value) {
if (!this.isImmutable) {
this._proxy = value;
}
}
get verifyCert() {
return this._verifyCert;
}
set verifyCert(value) {
if (!this.isImmutable) {
this._verifyCert = value;
}
}
get data() {
return this._data;
}
set data(value) {
if (!this.isImmutable) {
this._data = value;
}
}
get browser() {
return this._browser;
}
set browser(value) {
if (!this.isImmutable) {
this._browser = value;
}
}
get proxyAgent() {
if (this._proxy) {
return tunnel.httpOverHttp({
proxy: {
host: this._proxy.host,
port: this._proxy.port,
proxyAuth: `${this._proxy.auth.username}:${this._proxy.auth.password}`,
},
});
}
}
get isImmutable() {
return this._fetched;
}
get outputFile() {
return this._outputFile;
}
set outputFile(value) {
if (!this.isImmutable) {
this._outputFile = value;
}
}
get options() {
return {
uri: this._uri,
method: this._method,
headers: this._headers,
cookies: this._cookies,
verifyCert: this._verifyCert,
proxy: this._proxy,
maxRedirects: this._maxRedirects,
timeout: this._timeout,
auth: this._auth,
authType: this._authType,
outputFile: this._outputFile,
data: this._data,
type: this._type,
};
}
get needleOptions() {
var _a, _b;
return {
agent: this.proxyAgent,
auth: this._authType || "auto",
compressed: this.headers["Accept-Encoding"] === ENCODING_GZIP,
cookies: this.cookies,
follow_max: this.maxRedirects,
headers: this.headers,
json: this.headers["Content-Type"] === CONTENT_TYPE_JSON,
multipart: this.headers["Content-Type"] === CONTENT_TYPE_FORM_MULTIPART,
open_timeout: this.timeout.open,
output: this.outputFile,
parse_cookies: true,
parse_response: false,
password: (_a = this.auth) === null || _a === void 0 ? void 0 : _a.password,
read_timeout: this.timeout.read,
rejectUnauthorized: this.verifyCert,
username: (_b = this.auth) === null || _b === void 0 ? void 0 : _b.username,
user_agent: "Flagpole",
};
}
get httpOptions() {
return {
agent: this.proxyAgent,
headers: this.headers,
method: this.method,
timeout: this.timeout.open,
};
}
get gotOptions() {
return {
agent: this.proxyAgent,
allowGetBody: true,
body: this.data,
followRedirect: this.maxRedirects > 0,
headers: this.headers,
maxRedirects: this.maxRedirects,
method: this.method,
timeout: this.timeout.open,
};
}
urlEncodeForm(data) {
const encoded = [];
Object.keys(data).forEach((key) => {
encoded.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`);
});
return encoded.join("&");
}
setOptions(opts) {
if (!this.isImmutable) {
this._type = opts.type || this._type;
this._uri = opts.uri || this._uri;
this._method = opts.method || this._method;
this._headers = opts.headers || this._headers;
this._cookies = opts.cookies || this._cookies;
this._verifyCert =
typeof opts.verifyCert === "undefined"
? this._verifyCert
: opts.verifyCert;
this._proxy = opts.proxy;
this._maxRedirects =
typeof opts.maxRedirects === "undefined"
? this._maxRedirects
: opts.maxRedirects;
this._timeout = (() => {
if (!opts.timeout) {
return this._timeout;
}
if (typeof opts.timeout == "number") {
return {
open: opts.timeout,
};
}
return opts.timeout;
})();
this._auth = opts.auth || this._auth;
this._browser = opts.browserOptions || this._browser;
this._data = opts.data || this._data;
this._outputFile = opts.outputFile || this._outputFile;
}
return this;
}
setCookie(key, value) {
if (!this.isImmutable) {
this._cookies[key] = value;
}
}
getCookie(key) {
return this._cookies[key];
}
setHeader(key, value) {
if (!this.isImmutable) {
this._headers[key] = value;
}
}
getHeader(key) {
return this._headers[key];
}
setJsonData(data) {
this.setHeader("Content-Type", CONTENT_TYPE_JSON);
this.data = data;
}
setFormData(data, isMultipart) {
if (data instanceof FormData && !isMultipart) {
throw new Error("This format of form data must be multipart.");
}
this.setHeader("Content-Type", isMultipart ? CONTENT_TYPE_FORM_MULTIPART : CONTENT_TYPE_FORM);
if (data instanceof FormData) {
this.data = data;
}
else if (isMultipart) {
const formData = new FormData();
Object.keys(data).forEach((key) => formData.append(key, data[key]));
this.data = formData;
}
else {
this.data = form_urlencoded_1.default(data);
}
return this;
}
fetch(opts) {
if (this._fetched) {
throw new Error("This request was already fetched.");
}
this._fetched = true;
if (this._uri === null) {
throw new Error("Invalid URI");
}
if (this.type === "image") {
return this._fetchImage(opts);
}
else {
return this._fetchHttp(opts);
}
}
_fetchHttp(opts) {
return new Promise((resolve, reject) => {
if (this.options.cacheKey) {
const response = flagpoleexecution_1.FlagpoleExecution.global.getCache(this.options.cacheKey);
if (response !== null) {
return resolve(response);
}
}
const stream = needle.request(this.method === "options" ? "head" : this.method, this.uri || "/", this.data || null, this.needleOptions, (err, resp) => {
if (!err && resp) {
const response = httpresponse_1.HttpResponse.fromNeedle(resp);
if (this.options.cacheKey) {
flagpoleexecution_1.FlagpoleExecution.global.setCache(this.options.cacheKey, response);
}
return resolve(response);
}
reject(err);
});
if (opts === null || opts === void 0 ? void 0 : opts.redirect) {
stream.on("redirect", opts.redirect);
}
});
}
_fetchImage(opts) {
return new Promise((resolve, reject) => {
const stream = needle.request("get", this.uri || "/", null, this.needleOptions);
if (opts === null || opts === void 0 ? void 0 : opts.redirect) {
stream.on("redirect", opts.redirect);
}
const response = {
statusCode: 0,
length: 0,
url: this.uri || "",
headers: {},
imageData: {
width: 0,
height: 0,
type: "",
mimeType: "",
},
};
stream
.on("header", (statusCode, headers) => {
response.statusCode = statusCode;
response.headers = headers;
response.length = Number(headers["content-length"]);
})
.on("readable", () => {
const chunk = stream.read(512);
response.imageData =
image_probe_1.ImageProbe.fromBuffer(chunk) || response.imageData;
stream.pause();
try {
stream.destroy();
}
catch (_a) { }
resolve(httpresponse_1.HttpResponse.fromProbeImage(response));
});
});
}
}
exports.HttpRequest = HttpRequest;
//# sourceMappingURL=httprequest.js.map