UNPKG

@pipedream/platform

Version:

Pipedream platform globals (typing and runtime type checking)

187 lines (186 loc) 6.33 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformConfigForOauth = void 0; const axios_1 = require("axios"); const querystring = require("querystring"); const utils_1 = require("./utils"); const errors_1 = require("./errors"); function cleanObject(o = {}) { for (const k in o) { if (typeof o[k] === "undefined") { delete o[k]; } } } // remove query params from url and put into config.params function removeSearchFromUrl(config) { if (!config.url) return; const { url, baseURL, } = config; const newUrl = new URL((baseURL !== null && baseURL !== void 0 ? baseURL : "") + url); const queryString = newUrl.search.substr(1); if (queryString) { // https://stackoverflow.com/a/8649003/387413 const urlParams = JSON.parse("{\"" + queryString.replace(/&/g, "\",\"").replace(/=/g, "\":\"") + "\"}", function (key, value) { return key === "" ? value : decodeURIComponent(value); }); for (const k in urlParams) { if (!config.params) config.params = {}; if (k in config.params) continue; // params object > url query params config.params[k] = urlParams[k]; } newUrl.search = ""; config.url = newUrl.toString(); // if ends with ? should be okay, but could be cleaner } } // https://github.com/ttezel/twit/blob/master/lib/helpers.js#L11 function oauth1ParamsSerializer(p) { return querystring.stringify(p) .replace(/!/g, "%21") .replace(/'/g, "%27") .replace(/\(/g, "%28") .replace(/\)/g, "%29") .replace(/\*/g, "%2A"); } function transformConfigForOauth(config) { var _a; const newUrl = axios_1.default.getUri({ ...config, paramsSerializer: oauth1ParamsSerializer, }); const requestData = { method: config.method || "get", url: newUrl, }; // the OAuth specification explicitly states that only form-encoded data should be included let hasContentType = false; let formEncodedContentType = false; for (const k in config.headers || {}) { if (/content-type/i.test(k)) { hasContentType = true; formEncodedContentType = ((_a = config.headers) === null || _a === void 0 ? void 0 : _a[k]) === "application/x-www-form-urlencoded"; break; } } if (config.data && typeof config.data === "object" && formEncodedContentType) { requestData.data = config.data; } else if (typeof config.data === "string" && (!hasContentType || formEncodedContentType)) { requestData.data = querystring.parse(config.data); } config.paramsSerializer = oauth1ParamsSerializer; return requestData; } exports.transformConfigForOauth = transformConfigForOauth; async function getOauthSignature(config, signConfig) { const { oauthSignerUri, token, } = signConfig; const requestData = transformConfigForOauth(config); const payload = { requestData, token, }; return (await axios_1.default.post(oauthSignerUri, payload)).data; } // XXX warn about mutating config object... or clone? async function callAxios(step, config, signConfig) { cleanObject(config.headers); cleanObject(config.params); if (typeof config.data === "object") { cleanObject(config.data); } if (config.body != null) { throw new errors_1.ConfigurationError("unexpected body, use only data instead"); } removeSearchFromUrl(config); // OAuth1 request if (signConfig) { const oauthSignature = await getOauthSignature(config, signConfig); if (!config.headers) config.headers = {}; config.headers.Authorization = oauthSignature; } try { if (config.debug) { stepExport(step, config, "debug_config"); } const response = await axios_1.default(config); if (config.debug) { stepExport(step, response.data, "debug_response"); } return config.returnFullResponse ? response : response.data; } catch (err) { if (err.response) { convertAxiosError(err); stepExport(step, err.response, "debug"); } throw err; } } function stepExport(step, message, key) { message = utils_1.cloneSafe(message); if (step) { if (step.export) { step.export(key, message); return; } step[key] = message; } console.log(`export: ${key} - ${JSON.stringify(message, null, 2)}`); } function convertAxiosError(err) { delete err.response.request; err.name = `${err.name} - ${err.message}`; try { err.message = JSON.stringify(err.response.data); } catch (error) { console.error("Error trying to convert `err.response.data` to string"); } return err; } function create(config, signConfig) { const axiosInstance = axios_1.default.create(config); if (config === null || config === void 0 ? void 0 : config.debug) { stepExport(this, config, "debug_config"); } axiosInstance.interceptors.request.use(async (config) => { if (signConfig) { const oauthSignature = await getOauthSignature(config, signConfig); if (!config.headers) config.headers = {}; config.headers.Authorization = oauthSignature; } cleanObject(config.headers); cleanObject(config.params); if (typeof config.data === "object") { cleanObject(config.data); } removeSearchFromUrl(config); return config; }); axiosInstance.interceptors.response.use((response) => { const config = response.config; if (config.debug) { stepExport(this, response.data, "debug_response"); } return config.returnFullResponse ? response : response.data; }, (error) => { if (error.response) { convertAxiosError(error); stepExport(this, error.response, "debug"); } throw error; }); return axiosInstance; } callAxios.create = create; exports.default = callAxios;