HEX
Server: nginx/1.24.0
System: Linux nowruzgan 6.8.0-57-generic #59-Ubuntu SMP PREEMPT_DYNAMIC Sat Mar 15 17:40:59 UTC 2025 x86_64
User: babak (1000)
PHP: 8.3.6
Disabled: NONE
Upload Files
File: //usr/share/opensearch-dashboards/node_modules/original-url/index.js
'use strict'

const parseUrl = require('url').parse
const parseForwarded = require('forwarded-parse')
const net = require('net')

module.exports = function (req) {
  const raw = req.originalUrl || req.url
  const url = parseUrl(raw || '')
  const secure = req.secure || (req.connection && req.connection.encrypted)
  const result = { raw: raw }
  let host

  if (req.headers.forwarded) {
    let forwarded = getFirstHeader(req, 'forwarded')
    try {
      // Always choose the original (first) Forwarded pair in case the request
      // passed through multiple proxies
      forwarded = parseForwarded(forwarded)[0]
      host = parsePartialURL(forwarded.host)
      if (forwarded.for) {
        const conn = forwarded.for.split(']') // in case of IPv6 addr: [2001:db8:cafe::17]:1337
        const port = conn[conn.length - 1].split(':')[1]
        if (port) host.port = Number(port)
      }
      if (forwarded.proto) host.protocol = forwarded.proto + ':'
    } catch (e) {}
  } else if (req.headers['x-forwarded-host']) {
    host = parsePartialURL(getFirstHeader(req, 'x-forwarded-host'))
  }

  if (!host) {
    if (typeof req.headers.host === 'string') {
      host = parsePartialURL(req.headers.host)
    } else {
      host = {}
    }
  }

  // protocol
  if (url.protocol) result.protocol = url.protocol
  else if (req.headers['x-forwarded-proto']) result.protocol = getFirstHeader(req, 'x-forwarded-proto') + ':'
  else if (req.headers['x-forwarded-protocol']) result.protocol = getFirstHeader(req, 'x-forwarded-protocol') + ':'
  else if (req.headers['x-url-scheme']) result.protocol = getFirstHeader(req, 'x-url-scheme') + ':'
  else if (req.headers['front-end-https']) result.protocol = getFirstHeader(req, 'front-end-https') === 'on' ? 'https:' : 'http:'
  else if (req.headers['x-forwarded-ssl']) result.protocol = getFirstHeader(req, 'x-forwarded-ssl') === 'on' ? 'https:' : 'http:'
  else if (host.protocol) result.protocol = host.protocol
  else if (secure) result.protocol = 'https:'
  else result.protocol = 'http:'

  // hostname
  if (url.hostname) result.hostname = url.hostname
  else if (host.hostname) result.hostname = host.hostname

  // fix for IPv6 literal bug in legacy url - see https://github.com/watson/original-url/issues/3
  if (net.isIPv6(result.hostname)) result.hostname = '[' + result.hostname + ']'

  // port
  if (url.port) result.port = Number(url.port)
  else if (req.headers['x-forwarded-port']) result.port = Number(getFirstHeader(req, 'x-forwarded-port'))
  else if (host.port) result.port = Number(host.port)

  // pathname
  if (url.pathname) result.pathname = url.pathname
  else if (host.pathname) result.pathname = host.pathname // TODO: Consider if this should take priority over url.pathname

  // search
  if (url.search) result.search = url.search
  else if (host.search) result.search = host.search // TODO: Consider if this shoudl take priority over uri.search

  // hash
  if (host.hash) result.hash = host.hash

  // full
  if (result.protocol && result.hostname) {
    result.full = result.protocol + '//' + result.hostname
    if (result.port) result.full += ':' + result.port
    if (result.pathname) result.full += result.pathname
    if (result.search) result.full += result.search
    if (result.hash) result.full += result.hash
  }

  return result
}

// In case there's more than one header of a given name, we want the first one
// as it should be the one that was added by the first proxy in the chain
function getFirstHeader (req, header) {
  const value = req.headers[header]
  return (Array.isArray(value) ? value[0] : value).split(', ')[0]
}

function parsePartialURL (url) {
  const containsProtocol = url.indexOf('://') !== -1
  const result = parseUrl(containsProtocol ? url : 'invalid://' + url)
  if (!containsProtocol) result.protocol = ''
  return result
}