@sentry/node
Version:
Sentry Node SDK using OpenTelemetry for performance instrumentation
129 lines (117 loc) • 3.96 kB
JavaScript
import * as url from 'url';
/**
* Makes sure options is an url object
* return an object with default value and parsed options
* @param logger component logger
* @param options original options for the request
* @param [extraOptions] additional options for the request
*/
const getRequestInfo = (
logger,
options,
extraOptions,
) => {
let pathname;
let origin;
let optionsParsed;
let invalidUrl = false;
if (typeof options === 'string') {
try {
const convertedOptions = stringUrlToHttpOptions(options);
optionsParsed = convertedOptions;
pathname = convertedOptions.pathname || '/';
} catch (e) {
invalidUrl = true;
logger.verbose(
'Unable to parse URL provided to HTTP request, using fallback to determine path. Original error:',
e,
);
// for backward compatibility with how url.parse() behaved.
optionsParsed = {
path: options,
};
pathname = optionsParsed.path || '/';
}
origin = `${optionsParsed.protocol || 'http:'}//${optionsParsed.host}`;
if (extraOptions !== undefined) {
Object.assign(optionsParsed, extraOptions);
}
} else if (options instanceof url.URL) {
optionsParsed = {
protocol: options.protocol,
hostname:
typeof options.hostname === 'string' && options.hostname.startsWith('[')
? options.hostname.slice(1, -1)
: options.hostname,
path: `${options.pathname || ''}${options.search || ''}`,
};
if (options.port !== '') {
optionsParsed.port = Number(options.port);
}
if (options.username || options.password) {
optionsParsed.auth = `${options.username}:${options.password}`;
}
pathname = options.pathname;
origin = options.origin;
if (extraOptions !== undefined) {
Object.assign(optionsParsed, extraOptions);
}
} else {
optionsParsed = Object.assign({ protocol: options.host ? 'http:' : undefined }, options);
const hostname =
optionsParsed.host ||
(optionsParsed.port != null ? `${optionsParsed.hostname}${optionsParsed.port}` : optionsParsed.hostname);
origin = `${optionsParsed.protocol || 'http:'}//${hostname}`;
pathname = (options ).pathname;
if (!pathname && optionsParsed.path) {
try {
const parsedUrl = new URL(optionsParsed.path, origin);
pathname = parsedUrl.pathname || '/';
} catch (e) {
pathname = '/';
}
}
}
// some packages return method in lowercase..
// ensure upperCase for consistency
const method = optionsParsed.method ? optionsParsed.method.toUpperCase() : 'GET';
return { origin, pathname, method, optionsParsed, invalidUrl };
};
/**
* Mimics Node.js conversion of URL strings to RequestOptions expected by
* `http.request` and `https.request` APIs.
*
* See https://github.com/nodejs/node/blob/2505e217bba05fc581b572c685c5cf280a16c5a3/lib/internal/url.js#L1415-L1437
*
* @param stringUrl
* @throws TypeError if the URL is not valid.
*/
function stringUrlToHttpOptions(stringUrl) {
// This is heavily inspired by Node.js handling of the same situation, trying
// to follow it as closely as possible while keeping in mind that we only
// deal with string URLs, not URL objects.
const { hostname, pathname, port, username, password, search, protocol, hash, href, origin, host } = new URL(
stringUrl,
);
const options
= {
protocol: protocol,
hostname: hostname && hostname[0] === '[' ? hostname.slice(1, -1) : hostname,
hash: hash,
search: search,
pathname: pathname,
path: `${pathname || ''}${search || ''}`,
href: href,
origin: origin,
host: host,
};
if (port !== '') {
options.port = Number(port);
}
if (username || password) {
options.auth = `${decodeURIComponent(username)}:${decodeURIComponent(password)}`;
}
return options;
}
export { getRequestInfo };
//# sourceMappingURL=getRequestInfo.js.map