text: import * as tslib_1 from "tslib";
  import { Span } from '@sentry/apm';
  import { captureException, getCurrentHub, withScope } from '@sentry/core';
  import { forget, isPlainObject, isString, logger, normalize } from '@sentry/utils';
  import * as cookie from 'cookie';
  import * as domain from 'domain';
  import * as os from 'os';
  import * as url from 'url';
  import { flush } from './sdk';
  var DEFAULT_SHUTDOWN_TIMEOUT = 2000;
  /**
   * Express compatible tracing handler.
   * @see Exposed as `Handlers.tracingHandler`
   */
  export function tracingHandler() {
      return function sentryTracingMiddleware(req, res, next) {
          // TODO: At this point req.route.path we use in `extractTransaction` is not available
          // but `req.path` or `req.url` should do the job as well. We could unify this here.
          var reqMethod = (req.method || '').toUpperCase();
          var reqUrl = req.url;
          var hub = getCurrentHub();
          var transaction = hub.startSpan({
              op: 'http.server',
              transaction: reqMethod + " " + reqUrl,
          });
          hub.configureScope(function (scope) {
              scope.setSpan(transaction);
          });
          res.once('finish', function () {
              transaction.setHttpStatus(res.statusCode);
              transaction.finish();
          });
          next();
      };
  }
  /** JSDoc */
  function extractTransaction(req, type) {
      try {
          // Express.js shape
          var request = req;
          switch (type) {
              case 'path': {
                  return request.route.path;
              }
              case 'handler': {
                  return request.route.stack[0].name;
              }
              case 'methodPath':
              default: {
                  var method = request.method.toUpperCase();
                  var path = request.route.path;
                  return method + "|" + path;
              }
          }
      }
      catch (_oO) {
          return undefined;
      }
  }
  /** Default request keys that'll be used to extract data from the request */
  var DEFAULT_REQUEST_KEYS = ['cookies', 'data', 'headers', 'method', 'query_string', 'url'];
  /** JSDoc */
  function extractRequestData(req, keys) {
      var request = {};
      var attributes = Array.isArray(keys) ? keys : DEFAULT_REQUEST_KEYS;
      // headers:
      //   node, express: req.headers
      //   koa: req.header
      var headers = (req.headers || req.header || {});
      // method:
      //   node, express, koa: req.method
      var method = req.method;
      // host:
      //   express: req.hostname in > 4 and req.host in < 4
      //   koa: req.host
      //   node: req.headers.host
      var host = req.hostname || req.host || headers.host || '<no host>';
      // protocol:
      //   node: <n/a>
      //   express, koa: req.protocol
      var protocol = req.protocol === 'https' || req.secure || (req.socket || {}).encrypted
          ? 'https'
          : 'http';
      // url (including path and query string):
      //   node, express: req.originalUrl
      //   koa: req.url
      var originalUrl = (req.originalUrl || req.url);
      // absolute url
      var absoluteUrl = protocol + "://" + host + originalUrl;
      attributes.forEach(function (key) {
          switch (key) {
              case 'headers':
                  request.headers = headers;
                  break;
              case 'method':
                  request.method = method;
                  break;
              case 'url':
                  request.url = absoluteUrl;
                  break;
              case 'cookies':
                  // cookies:
                  //   node, express, koa: req.headers.cookie
                  request.cookies = cookie.parse(headers.cookie || '');
                  break;
              case 'query_string':
                  // query string:
                  //   node: req.url (raw)
                  //   express, koa: req.query
                  request.query_string = url.parse(originalUrl || '', false).query;
                  break;
              case 'data':
                  if (method === 'GET' || method === 'HEAD') {
                      break;
                  }
                  // body data:
                  //   node, express, koa: req.body
                  if (req.body !== undefined) {
                      request.data = isString(req.body) ? req.body : JSON.stringify(normalize(req.body));
                  }
                  break;
              default:
                  if ({}.hasOwnProperty.call(req, key)) {
                      request[key] = req[key];
                  }
          }
      });
      return request;
  }
  /** Default user keys that'll be used to extract data from the request */
  var DEFAULT_USER_KEYS = ['id', 'username', 'email'];
  /** JSDoc */
  function extractUserData(user, keys) {
      var extractedUser = {};
      var attributes = Array.isArray(keys) ? keys : DEFAULT_USER_KEYS;
      attributes.forEach(function (key) {
          if (user && key in user) {
              extractedUser[key] = user[key];
          }
      });
      return extractedUser;
  }
  /**
   * Enriches passed event with request data.
   *
   * @param event Will be mutated and enriched with req data
   * @param req Request object
   * @param options object containing flags to enable functionality
   * @hidden
   */
  export function parseRequest(event, req, options) {
      // tslint:disable-next-line:no-parameter-reassignment
      options = tslib_1.__assign({ ip: false, request: true, serverName: true, transaction: true, user: true, version: true }, options);
      if (options.version) {
          event.contexts = tslib_1.__assign({}, event.contexts, { runtime: {
                  name: 'node',
                  version: global.process.version,
              } });
      }
      if (options.request) {
          event.request = tslib_1.__assign({}, event.request, extractRequestData(req, options.request));
      }
      if (options.serverName && !event.server_name) {
          event.server_name = global.process.env.SENTRY_NAME || os.hostname();
      }
      if (options.user) {
          var extractedUser = req.user && isPlainObject(req.user) ? extractUserData(req.user, options.user) : {};
          if (Object.keys(extractedUser)) {
              event.user = tslib_1.__assign({}, event.user, extractedUser);
          }
      }
      // client ip:
      //   node: req.connection.remoteAddress
      //   express, koa: req.ip
      if (options.ip) {
          var ip = req.ip || (req.connection && req.connection.remoteAddress);
          if (ip) {
              event.user = tslib_1.__assign({}, event.user, { ip_address: ip });
          }
      }
      if (options.transaction && !event.transaction) {
          var transaction = extractTransaction(req, options.transaction);
          if (transaction) {
              event.transaction = transaction;
          }
      }
      return event;
  }
  /**
   * Express compatible request handler.
   * @see Exposed as `Handlers.requestHandler`
   */
  export function requestHandler(options) {
      return function sentryRequestMiddleware(req, res, next) {
          if (options && options.flushTimeout && options.flushTimeout > 0) {
              // tslint:disable-next-line: no-unbound-method
              var _end_1 = res.end;
              res.end = function (chunk, encoding, cb) {
                  var _this = this;
                  flush(options.flushTimeout)
                      .then(function () {
                      _end_1.call(_this, chunk, encoding, cb);
                  })
                      .then(null, function (e) {
                      logger.error(e);
                  });
              };
          }
          var local = domain.create();
          local.add(req);
          local.add(res);
          local.on('error', next);
          local.run(function () {
              getCurrentHub().configureScope(function (scope) {
                  return scope.addEventProcessor(function (event) { return parseRequest(event, req, options); });
              });
              next();
          });
      };
  }
  /** JSDoc */
  function getStatusCodeFromResponse(error) {
      var statusCode = error.status || error.statusCode || error.status_code || (error.output && error.output.statusCode);
      return statusCode ? parseInt(statusCode, 10) : 500;
  }
  /** Returns true if response code is internal server error */
  function defaultShouldHandleError(error) {
      var status = getStatusCodeFromResponse(error);
      return status >= 500;
  }
  /**
   * Express compatible error handler.
   * @see Exposed as `Handlers.errorHandler`
   */
  export function errorHandler(options) {
      return function sentryErrorMiddleware(error, req, res, next) {
          var shouldHandleError = (options && options.shouldHandleError) || defaultShouldHandleError;
          if (shouldHandleError(error)) {
              withScope(function (scope) {
                  if (req.headers && isString(req.headers['sentry-trace'])) {
                      var span = Span.fromTraceparent(req.headers['sentry-trace']);
                      scope.setSpan(span);
                  }
                  var eventId = captureException(error);
                  res.sentry = eventId;
                  next(error);
              });
              return;
          }
          next(error);
      };
  }
  /**
   * @hidden
   */
  export function logAndExitProcess(error) {
      console.error(error && error.stack ? error.stack : error);
      var client = getCurrentHub().getClient();
      if (client === undefined) {
          logger.warn('No NodeClient was defined, we are exiting the process now.');
          global.process.exit(1);
          return;
      }
      var options = client.getOptions();
      var timeout = (options && options.shutdownTimeout && options.shutdownTimeout > 0 && options.shutdownTimeout) ||
          DEFAULT_SHUTDOWN_TIMEOUT;
      forget(client.close(timeout).then(function (result) {
          if (!result) {
              logger.warn('We reached the timeout for emptying the request buffer, still exiting now!');
          }
          global.process.exit(1);
      }));
  }
  //# sourceMappingURL=handlers.js.map