All files / worker/utils headers.ts

85.71% Statements 36/42
85% Branches 17/20
100% Functions 11/11
83.78% Lines 31/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94      36x   36x 40x     3x       42x 42x 4x   38x         44x   44x 39x     5x                   5x       15x                       7x 7x 12x   10x 6x   5x 5x 2x   3x                             10x 10x 10x 10x 7x   6x 6x     3x      
import { HeaderMissingError } from '../errors'
 
export function hasContentType(headers: Headers, ...expectedContentTypes: string[]) {
  const contentType = headers.get('Content-Type')?.toLowerCase()
 
  if (contentType) {
    return expectedContentTypes.some((expectedContentType) => contentType.startsWith(expectedContentType))
  }
 
  return false
}
 
export function getHeaderOrThrow(headers: Headers, name: string) {
  const value = headers.get(name)
  if (!value) {
    throw new HeaderMissingError(name)
  }
  return value
}
 
let localIp: string | undefined
export async function getIp(headers: Headers): Promise<string> {
  const ip = headers.get('cf-connecting-ip')
 
  if (ip) {
    return ip
  }
 
  Iif (import.meta.env.MODE == 'dev') {
    console.debug('Fetching local IP for dev mode')
    if (localIp === undefined) {
      const ipResponse = await fetch('https://checkip.amazonaws.com/')
      const ip = await ipResponse.text()
      localIp = ip.trim()
    }
    return localIp
  }
 
  throw new HeaderMissingError('cf-connecting-ip')
}
 
export function isDocumentDestination(headers: Headers) {
  return headers.get('Sec-Fetch-Dest')?.includes('document')
}
 
/**
 * Remove a header value from an HTTP header value that uses comma-separated lists to
 * separated individual values.
 *
 * @param headers the `Headers` to update
 * @param name the name of the header field to update
 * @param value the value to remove from the header field
 */
export function removeHeaderValue(headers: Headers, name: string, value: string) {
  const headerValue = headers.get(name)
  if (headerValue) {
    const headerValues = headerValue.split(',').map((s) => s.trim())
 
    const valueIndex = headerValues.findIndex((v) => v.toLowerCase() === value.toLowerCase())
    if (valueIndex !== -1) {
      // Only modify the header field when the value is present
      headerValues.splice(valueIndex, 1)
      if (headerValues.length === 0) {
        headers.delete(name)
      } else {
        headers.set(name, headerValues.join(','))
      }
    }
  }
}
 
/**
 * Append a value to the HTTP header, only if that value is not already in the value
 * for the header
 *
 * @param headers the `Headers` to update
 * @param name the name of the header field to update
 * @param value the value to add to the header field, if it is not already present
 */
export function appendHeaderValue(headers: Headers, name: string, value: string) {
  const headerValue = headers.get(name)
  if (headerValue) {
    const headerValues = headerValue.split(',').map((s) => s.trim())
    const valueIndex = headerValues.findIndex((v) => v.toLowerCase() === value.toLowerCase())
    if (valueIndex === -1) {
      // Only modify the header field when the value is already present
      headerValues.push(value)
      headers.set(name, headerValues.join(','))
    }
  } else {
    headers.set(name, value)
  }
}