serpapi
Version:
Scrape and parse search engine results using SerpApi.
107 lines (106 loc) • 3.92 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.execute = exports.buildRequestOptions = exports.getSource = exports._internals = void 0;
const version_js_1 = require("../version.js");
const https_1 = __importDefault(require("https"));
const querystring_1 = __importDefault(require("querystring"));
const process_1 = __importDefault(require("process"));
const errors_js_1 = require("./errors.js");
const config_js_1 = require("./config.js");
/**
* This `_internals` object is needed to support stubbing/spying of
* certain functions in this file.
* https://deno.land/manual@v1.28.3/basics/testing/mocking
*
* It's also useful to encapsulate functions that are polyfilled.
*/
exports._internals = {
execute: execute,
getHostnameAndPort: getHostnameAndPort,
};
/** Facilitates stubbing in tests */
function getHostnameAndPort() {
return {
hostname: "serpapi.com",
port: 443,
};
}
function getSource() {
var _a, _b;
const moduleSource = `serpapi@${version_js_1.version}`;
if (typeof Deno == "object") {
const denoVersion = (_a = Deno.version) === null || _a === void 0 ? void 0 : _a.deno;
if (denoVersion) {
return `deno@${denoVersion},${moduleSource}`;
}
}
else if (typeof process_1.default == "object") {
const nodeVersion = (_b = process_1.default.versions) === null || _b === void 0 ? void 0 : _b.node;
if (nodeVersion) {
return `nodejs@${nodeVersion},${moduleSource}`;
}
}
return `nodejs,${moduleSource}`;
}
exports.getSource = getSource;
function buildRequestOptions(path, parameters) {
const clonedParams = Object.assign({}, parameters);
for (const k in clonedParams) {
if (k === "requestOptions" ||
k === "timeout" ||
clonedParams[k] === undefined) {
delete clonedParams[k];
}
}
const basicOptions = Object.assign(Object.assign({}, exports._internals.getHostnameAndPort()), { path: `${path}?${querystring_1.default.stringify(clonedParams)}`, method: "GET" });
return Object.assign(Object.assign(Object.assign({}, config_js_1.config.requestOptions), parameters.requestOptions), basicOptions);
}
exports.buildRequestOptions = buildRequestOptions;
function execute(path, parameters, timeout) {
const options = buildRequestOptions(path, Object.assign(Object.assign({}, parameters), { source: getSource() }));
return new Promise((resolve, reject) => {
let timer;
const handleResponse = (resp) => {
resp.setEncoding("utf8");
let data = "";
// A chunk of data has been received
resp.on("data", (chunk) => {
data += chunk;
});
// The whole response has been received
resp.on("end", () => {
try {
if (resp.statusCode == 200) {
resolve(data);
}
else {
reject(data);
}
}
catch (e) {
reject(e);
}
finally {
if (timer)
clearTimeout(timer);
}
});
};
const handleError = (err) => {
reject(err);
if (timer)
clearTimeout(timer);
};
const req = https_1.default.get(options, handleResponse).on("error", handleError);
if (timeout > 0) {
timer = setTimeout(() => {
reject(new errors_js_1.RequestTimeoutError());
req.destroy();
}, timeout);
}
});
}
exports.execute = execute;