mirror of
https://github.com/MarSeventh/CloudFlare-ImgBed.git
synced 2026-04-26 23:25:11 +00:00
init
This commit is contained in:
379
node_modules/@sentry/utils/cjs/requestdata.js
generated
vendored
Normal file
379
node_modules/@sentry/utils/cjs/requestdata.js
generated
vendored
Normal file
@@ -0,0 +1,379 @@
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
const cookie = require('./cookie.js');
|
||||
const debugBuild = require('./debug-build.js');
|
||||
const is = require('./is.js');
|
||||
const logger = require('./logger.js');
|
||||
const normalize = require('./normalize.js');
|
||||
const url = require('./url.js');
|
||||
|
||||
const DEFAULT_INCLUDES = {
|
||||
ip: false,
|
||||
request: true,
|
||||
transaction: true,
|
||||
user: true,
|
||||
};
|
||||
const DEFAULT_REQUEST_INCLUDES = ['cookies', 'data', 'headers', 'method', 'query_string', 'url'];
|
||||
const DEFAULT_USER_INCLUDES = ['id', 'username', 'email'];
|
||||
|
||||
/**
|
||||
* Sets parameterized route as transaction name e.g.: `GET /users/:id`
|
||||
* Also adds more context data on the transaction from the request.
|
||||
*
|
||||
* @deprecated This utility will be removed in v8.
|
||||
*/
|
||||
function addRequestDataToTransaction(
|
||||
transaction,
|
||||
req,
|
||||
deps,
|
||||
) {
|
||||
if (!transaction) return;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (!transaction.metadata.source || transaction.metadata.source === 'url') {
|
||||
// Attempt to grab a parameterized route off of the request
|
||||
const [name, source] = extractPathForTransaction(req, { path: true, method: true });
|
||||
transaction.updateName(name);
|
||||
// TODO: SEMANTIC_ATTRIBUTE_SENTRY_SOURCE is in core, align this once we merge utils & core
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.setMetadata({ source });
|
||||
}
|
||||
transaction.setAttribute('url', req.originalUrl || req.url);
|
||||
if (req.baseUrl) {
|
||||
transaction.setAttribute('baseUrl', req.baseUrl);
|
||||
}
|
||||
// TODO: We need to rewrite this to a flat format?
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.setData('query', extractQueryParams(req, deps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a complete and parameterized path from the request object and uses it to construct transaction name.
|
||||
* If the parameterized transaction name cannot be extracted, we fall back to the raw URL.
|
||||
*
|
||||
* Additionally, this function determines and returns the transaction name source
|
||||
*
|
||||
* eg. GET /mountpoint/user/:id
|
||||
*
|
||||
* @param req A request object
|
||||
* @param options What to include in the transaction name (method, path, or a custom route name to be
|
||||
* used instead of the request's route)
|
||||
*
|
||||
* @returns A tuple of the fully constructed transaction name [0] and its source [1] (can be either 'route' or 'url')
|
||||
*/
|
||||
function extractPathForTransaction(
|
||||
req,
|
||||
options = {},
|
||||
) {
|
||||
const method = req.method && req.method.toUpperCase();
|
||||
|
||||
let path = '';
|
||||
let source = 'url';
|
||||
|
||||
// Check to see if there's a parameterized route we can use (as there is in Express)
|
||||
if (options.customRoute || req.route) {
|
||||
path = options.customRoute || `${req.baseUrl || ''}${req.route && req.route.path}`;
|
||||
source = 'route';
|
||||
}
|
||||
|
||||
// Otherwise, just take the original URL
|
||||
else if (req.originalUrl || req.url) {
|
||||
path = url.stripUrlQueryAndFragment(req.originalUrl || req.url || '');
|
||||
}
|
||||
|
||||
let name = '';
|
||||
if (options.method && method) {
|
||||
name += method;
|
||||
}
|
||||
if (options.method && options.path) {
|
||||
name += ' ';
|
||||
}
|
||||
if (options.path && path) {
|
||||
name += path;
|
||||
}
|
||||
|
||||
return [name, source];
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function extractTransaction(req, type) {
|
||||
switch (type) {
|
||||
case 'path': {
|
||||
return extractPathForTransaction(req, { path: true })[0];
|
||||
}
|
||||
case 'handler': {
|
||||
return (req.route && req.route.stack && req.route.stack[0] && req.route.stack[0].name) || '<anonymous>';
|
||||
}
|
||||
case 'methodPath':
|
||||
default: {
|
||||
// if exist _reconstructedRoute return that path instead of route.path
|
||||
const customRoute = req._reconstructedRoute ? req._reconstructedRoute : undefined;
|
||||
return extractPathForTransaction(req, { path: true, method: true, customRoute })[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
function extractUserData(
|
||||
user
|
||||
|
||||
,
|
||||
keys,
|
||||
) {
|
||||
const extractedUser = {};
|
||||
const attributes = Array.isArray(keys) ? keys : DEFAULT_USER_INCLUDES;
|
||||
|
||||
attributes.forEach(key => {
|
||||
if (user && key in user) {
|
||||
extractedUser[key] = user[key];
|
||||
}
|
||||
});
|
||||
|
||||
return extractedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize data from the request object, accounting for framework differences.
|
||||
*
|
||||
* @param req The request object from which to extract data
|
||||
* @param options.include An optional array of keys to include in the normalized data. Defaults to
|
||||
* DEFAULT_REQUEST_INCLUDES if not provided.
|
||||
* @param options.deps Injected, platform-specific dependencies
|
||||
* @returns An object containing normalized request data
|
||||
*/
|
||||
function extractRequestData(
|
||||
req,
|
||||
options
|
||||
|
||||
,
|
||||
) {
|
||||
const { include = DEFAULT_REQUEST_INCLUDES, deps } = options || {};
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const requestData = {};
|
||||
|
||||
// headers:
|
||||
// node, express, koa, nextjs: req.headers
|
||||
const headers = (req.headers || {})
|
||||
|
||||
;
|
||||
// method:
|
||||
// node, express, koa, nextjs: req.method
|
||||
const method = req.method;
|
||||
// host:
|
||||
// express: req.hostname in > 4 and req.host in < 4
|
||||
// koa: req.host
|
||||
// node, nextjs: req.headers.host
|
||||
// Express 4 mistakenly strips off port number from req.host / req.hostname so we can't rely on them
|
||||
// See: https://github.com/expressjs/express/issues/3047#issuecomment-236653223
|
||||
// Also: https://github.com/getsentry/sentry-javascript/issues/1917
|
||||
const host = headers.host || req.hostname || req.host || '<no host>';
|
||||
// protocol:
|
||||
// node, nextjs: <n/a>
|
||||
// express, koa: req.protocol
|
||||
const protocol = req.protocol === 'https' || (req.socket && req.socket.encrypted) ? 'https' : 'http';
|
||||
// url (including path and query string):
|
||||
// node, express: req.originalUrl
|
||||
// koa, nextjs: req.url
|
||||
const originalUrl = req.originalUrl || req.url || '';
|
||||
// absolute url
|
||||
const absoluteUrl = originalUrl.startsWith(protocol) ? originalUrl : `${protocol}://${host}${originalUrl}`;
|
||||
include.forEach(key => {
|
||||
switch (key) {
|
||||
case 'headers': {
|
||||
requestData.headers = headers;
|
||||
|
||||
// Remove the Cookie header in case cookie data should not be included in the event
|
||||
if (!include.includes('cookies')) {
|
||||
delete (requestData.headers ).cookie;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'method': {
|
||||
requestData.method = method;
|
||||
break;
|
||||
}
|
||||
case 'url': {
|
||||
requestData.url = absoluteUrl;
|
||||
break;
|
||||
}
|
||||
case 'cookies': {
|
||||
// cookies:
|
||||
// node, express, koa: req.headers.cookie
|
||||
// vercel, sails.js, express (w/ cookie middleware), nextjs: req.cookies
|
||||
requestData.cookies =
|
||||
// TODO (v8 / #5257): We're only sending the empty object for backwards compatibility, so the last bit can
|
||||
// come off in v8
|
||||
req.cookies || (headers.cookie && cookie.parseCookie(headers.cookie)) || {};
|
||||
break;
|
||||
}
|
||||
case 'query_string': {
|
||||
// query string:
|
||||
// node: req.url (raw)
|
||||
// express, koa, nextjs: req.query
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
requestData.query_string = extractQueryParams(req, deps);
|
||||
break;
|
||||
}
|
||||
case 'data': {
|
||||
if (method === 'GET' || method === 'HEAD') {
|
||||
break;
|
||||
}
|
||||
// body data:
|
||||
// express, koa, nextjs: req.body
|
||||
//
|
||||
// when using node by itself, you have to read the incoming stream(see
|
||||
// https://nodejs.dev/learn/get-http-request-body-data-using-nodejs); if a user is doing that, we can't know
|
||||
// where they're going to store the final result, so they'll have to capture this data themselves
|
||||
if (req.body !== undefined) {
|
||||
requestData.data = is.isString(req.body) ? req.body : JSON.stringify(normalize.normalize(req.body));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if ({}.hasOwnProperty.call(req, key)) {
|
||||
requestData[key] = (req )[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return requestData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data from the given request to the given event
|
||||
*
|
||||
* @param event The event to which the request data will be added
|
||||
* @param req Request object
|
||||
* @param options.include Flags to control what data is included
|
||||
* @param options.deps Injected platform-specific dependencies
|
||||
* @returns The mutated `Event` object
|
||||
*/
|
||||
function addRequestDataToEvent(
|
||||
event,
|
||||
req,
|
||||
options,
|
||||
) {
|
||||
const include = {
|
||||
...DEFAULT_INCLUDES,
|
||||
...(options && options.include),
|
||||
};
|
||||
|
||||
if (include.request) {
|
||||
const extractedRequestData = Array.isArray(include.request)
|
||||
? extractRequestData(req, { include: include.request, deps: options && options.deps })
|
||||
: extractRequestData(req, { deps: options && options.deps });
|
||||
|
||||
event.request = {
|
||||
...event.request,
|
||||
...extractedRequestData,
|
||||
};
|
||||
}
|
||||
|
||||
if (include.user) {
|
||||
const extractedUser = req.user && is.isPlainObject(req.user) ? extractUserData(req.user, include.user) : {};
|
||||
|
||||
if (Object.keys(extractedUser).length) {
|
||||
event.user = {
|
||||
...event.user,
|
||||
...extractedUser,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// client ip:
|
||||
// node, nextjs: req.socket.remoteAddress
|
||||
// express, koa: req.ip
|
||||
if (include.ip) {
|
||||
const ip = req.ip || (req.socket && req.socket.remoteAddress);
|
||||
if (ip) {
|
||||
event.user = {
|
||||
...event.user,
|
||||
ip_address: ip,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (include.transaction && !event.transaction) {
|
||||
// TODO do we even need this anymore?
|
||||
// TODO make this work for nextjs
|
||||
event.transaction = extractTransaction(req, include.transaction);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
function extractQueryParams(
|
||||
req,
|
||||
deps,
|
||||
) {
|
||||
// url (including path and query string):
|
||||
// node, express: req.originalUrl
|
||||
// koa, nextjs: req.url
|
||||
let originalUrl = req.originalUrl || req.url || '';
|
||||
|
||||
if (!originalUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The `URL` constructor can't handle internal URLs of the form `/some/path/here`, so stick a dummy protocol and
|
||||
// hostname on the beginning. Since the point here is just to grab the query string, it doesn't matter what we use.
|
||||
if (originalUrl.startsWith('/')) {
|
||||
originalUrl = `http://dogs.are.great${originalUrl}`;
|
||||
}
|
||||
|
||||
try {
|
||||
return (
|
||||
req.query ||
|
||||
(typeof URL !== 'undefined' && new URL(originalUrl).search.slice(1)) ||
|
||||
// In Node 8, `URL` isn't in the global scope, so we have to use the built-in module from Node
|
||||
(deps && deps.url && deps.url.parse(originalUrl).query) ||
|
||||
undefined
|
||||
);
|
||||
} catch (e2) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a `Headers` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into a simple key-value dict.
|
||||
* The header keys will be lower case: e.g. A "Content-Type" header will be stored as "content-type".
|
||||
*/
|
||||
// TODO(v8): Make this function return undefined when the extraction fails.
|
||||
function winterCGHeadersToDict(winterCGHeaders) {
|
||||
const headers = {};
|
||||
try {
|
||||
winterCGHeaders.forEach((value, key) => {
|
||||
if (typeof value === 'string') {
|
||||
// We check that value is a string even though it might be redundant to make sure prototype pollution is not possible.
|
||||
headers[key] = value;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
debugBuild.DEBUG_BUILD &&
|
||||
logger.logger.warn('Sentry failed extracting headers from a request object. If you see this, please file an issue.');
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `Request` object that implements the `Web Fetch API` (https://developer.mozilla.org/en-US/docs/Web/API/Headers) into the format that the `RequestData` integration understands.
|
||||
*/
|
||||
function winterCGRequestToRequestData(req) {
|
||||
const headers = winterCGHeadersToDict(req.headers);
|
||||
return {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
headers,
|
||||
};
|
||||
}
|
||||
|
||||
exports.DEFAULT_USER_INCLUDES = DEFAULT_USER_INCLUDES;
|
||||
exports.addRequestDataToEvent = addRequestDataToEvent;
|
||||
exports.addRequestDataToTransaction = addRequestDataToTransaction;
|
||||
exports.extractPathForTransaction = extractPathForTransaction;
|
||||
exports.extractRequestData = extractRequestData;
|
||||
exports.winterCGHeadersToDict = winterCGHeadersToDict;
|
||||
exports.winterCGRequestToRequestData = winterCGRequestToRequestData;
|
||||
//# sourceMappingURL=requestdata.js.map
|
||||
Reference in New Issue
Block a user