<commit_before>/*
  This module exposes factory function to construct middleware
  This factory function accepts options has to configure behaviour
  of middleware.

  The most important part is `resolver` which is a function
    `boolean resolver(ctx : Ctx)` -- Java
    `resolver :: Ctx -> Bool`     -- Haskell

  This function is being called with ctx object of request
    - If `true` is returned connection is considered secure
    - If `false` is returned connection is considered not being secured
*/

const url = require('url');

/**
 * Default configuration
 */
const defaults = {
  resolver: httpsResolver,
  hostname: undefined,
  port: 443,
  skipDefaultPort: true,
  ignoreUrl: false,
  temporary: false,
  redirectMethods: ['GET', 'HEAD'],
  disallowStatus: 405
};


// Merge default options with overwrites and returns new object
function applyOptions(options) {
  const settings = {};
  options = options || {};
  Object.assign(settings, defaults, options);

  return settings;
}

// skip 443 ports in urls
function portToUrlString(options) {
  return (options.skipDefaultPort && options.port === 443) ? '' : ':' + options.port;
}


// middleware itself
function redirect(options, ctx) {
  // Check if method should be disallowed (and handle OPTIONS method)
  if (options.redirectMethods.indexOf(ctx.method) === -1) {
    ctx.response.status = options.disallowStatus;
    if (options.disallowStatus === 405) {
      ctx.response.set('Allow', options.redirectMethods.join(', '));
    }
    ctx.response.body = '';
    return;
  }

  // build redirect url
  const httpsHost = options.hostname || url.parse('http://' + ctx.request.header.host).hostname;
  let redirectTo = `https://${httpsHost}${portToUrlString(options)}`;

  if(!options.ignoreUrl) {
    redirectTo += ctx.request.url;
  }

  // redirect to secure
  ctx.response.status = options.temporary ? 302 : 301;
  ctx.response.redirect(redirectTo);
}


/**
 * enforceHTTPS
 *
 *   @param    {Hash}       options
 *   @param    {Function}   options[resolver]
 *   @param    {Integer}    options[port]
 *   @param    {String}     options[hostname]
 *   @param    {Boolean}    options[ignoreUrl]
 *   @param    {Boolean}    options[temporary]
 *   @param    {Array}      options[redirectMethods]
 *   @param    {Integer}    options[disallowStatus]
 *   @return   {Function}
 *   @api      public
 */
function factory(options) {
  options = applyOptions(options);

  return (ctx, next) => {

    // Next if secure
    if (options.resolver(ctx)) {
      next();
    }
    // Redirect to HTTPS
    else {
      redirect(options, ctx);
    }
  }
};

/*
  Resolvers
*/

// Default HTTPS resolver
// This works when using node.js TLS support
function httpsResolver(ctx) {
  return ctx.secure;
}

// x-forwarded-proto header resolver
// common for heroku gcp (ingress) etc
function xForwardedProtoResolver(ctx) {
  return ctx.request.header['x-forwarded-proto'] === 'https';
}


// Azure resolver
// Azure is using `x-att-ssl` header
function azureResolver(ctx) {
  return Boolean(ctx.request.header["x-arr-ssl"]);
}<commit_msg>return the next koa middleware<commit_after>/*
  This module exposes factory function to construct middleware
  This factory function accepts options has to configure behaviour
  of middleware.

  The most important part is `resolver` which is a function
    `boolean resolver(ctx : Ctx)` -- Java
    `resolver :: Ctx -> Bool`     -- Haskell

  This function is being called with ctx object of request
    - If `true` is returned connection is considered secure
    - If `false` is returned connection is considered not being secured
*/

const url = require('url');

/**
 * Default configuration
 */
const defaults = {
  resolver: httpsResolver,
  hostname: undefined,
  port: 443,
  skipDefaultPort: true,
  ignoreUrl: false,
  temporary: false,
  redirectMethods: ['GET', 'HEAD'],
  disallowStatus: 405
};


// Merge default options with overwrites and returns new object
function applyOptions(options) {
  const settings = {};
  options = options || {};
  Object.assign(settings, defaults, options);

  return settings;
}

// skip 443 ports in urls
function portToUrlString(options) {
  return (options.skipDefaultPort && options.port === 443) ? '' : ':' + options.port;
}


// middleware itself
function redirect(options, ctx) {
  // Check if method should be disallowed (and handle OPTIONS method)
  if (options.redirectMethods.indexOf(ctx.method) === -1) {
    ctx.response.status = options.disallowStatus;
    if (options.disallowStatus === 405) {
      ctx.response.set('Allow', options.redirectMethods.join(', '));
    }
    ctx.response.body = '';
    return;
  }

  // build redirect url
  const httpsHost = options.hostname || url.parse('http://' + ctx.request.header.host).hostname;
  let redirectTo = `https://${httpsHost}${portToUrlString(options)}`;

  if(!options.ignoreUrl) {
    redirectTo += ctx.request.url;
  }

  // redirect to secure
  ctx.response.status = options.temporary ? 302 : 301;
  ctx.response.redirect(redirectTo);
}


/**
 * enforceHTTPS
 *
 *   @param    {Hash}       options
 *   @param    {Function}   options[resolver]
 *   @param    {Integer}    options[port]
 *   @param    {String}     options[hostname]
 *   @param    {Boolean}    options[ignoreUrl]
 *   @param    {Boolean}    options[temporary]
 *   @param    {Array}      options[redirectMethods]
 *   @param    {Integer}    options[disallowStatus]
 *   @return   {Function}
 *   @api      public
 */
function factory(options) {
  options = applyOptions(options);

  return (ctx, next) => {

    // Next if secure
    if (options.resolver(ctx)) {
      return next();
    }
    // Redirect to HTTPS
    else {
      redirect(options, ctx);
    }
  }
};

/*
  Resolvers
*/

// Default HTTPS resolver
// This works when using node.js TLS support
function httpsResolver(ctx) {
  return ctx.secure;
}

// x-forwarded-proto header resolver
// common for heroku gcp (ingress) etc
function xForwardedProtoResolver(ctx) {
  return ctx.request.header['x-forwarded-proto'] === 'https';
}


// Azure resolver
// Azure is using `x-att-ssl` header
function azureResolver(ctx) {
  return Boolean(ctx.request.header["x-arr-ssl"]);
}
{'fraction_non_alphanumeric': 0.1273372018052869, 'fraction_numerical': 0.0070921985815602835, 'mean_word_length': 3.244186046511628, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1280929', 'n_tokens_mistral': 1924, 'n_tokens_neox': 1852, 'n_words': 523}