All Downloads are FREE. Search and download functionalities are using the official Maven repository.

zhttp.http.headers.HeaderGetters.scala Maven / Gradle / Ivy

There is a newer version: 2.0.0-RC11
Show newest version
package zhttp.http.headers

import io.netty.handler.codec.http.HttpUtil
import io.netty.util.AsciiString.contentEqualsIgnoreCase
import zhttp.http.Headers.{BasicSchemeName, BearerSchemeName}
import zhttp.http._
import zhttp.http.middleware.Auth.Credentials
import zhttp.service.server.ServerTime

import java.nio.charset.Charset
import java.util.{Base64, Date}
import scala.util.control.NonFatal

/**
 * Maintains a list of operators that parse and extract data from the headers.
 *
 * NOTE: Add methods here if it performs some kind of processing on the header
 * and returns the result.
 */
trait HeaderGetters[+A] { self =>

  final def accept: Option[CharSequence] =
    headerValue(HeaderNames.accept)

  final def acceptCharset: Option[CharSequence] =
    headerValue(HeaderNames.acceptCharset)

  final def acceptEncoding: Option[CharSequence] =
    headerValue(HeaderNames.acceptEncoding)

  final def acceptLanguage: Option[CharSequence] =
    headerValue(HeaderNames.acceptLanguage)

  final def acceptPatch: Option[CharSequence] =
    headerValue(HeaderNames.acceptPatch)

  final def acceptRanges: Option[CharSequence] =
    headerValue(HeaderNames.acceptRanges)

  final def accessControlAllowCredentials: Option[Boolean] =
    headerValue(HeaderNames.accessControlAllowCredentials) match {
      case Some(string) =>
        try Some(string.toBoolean)
        catch { case _: Throwable => None }
      case None         => None
    }

  final def accessControlAllowHeaders: Option[CharSequence] =
    headerValue(HeaderNames.accessControlAllowHeaders)

  final def accessControlAllowMethods: Option[CharSequence] =
    headerValue(HeaderNames.accessControlAllowMethods)

  final def accessControlAllowOrigin: Option[CharSequence] =
    headerValue(HeaderNames.accessControlAllowOrigin)

  final def accessControlExposeHeaders: Option[CharSequence] =
    headerValue(HeaderNames.accessControlExposeHeaders)

  final def accessControlMaxAge: Option[CharSequence] =
    headerValue(HeaderNames.accessControlMaxAge)

  final def accessControlRequestHeaders: Option[CharSequence] =
    headerValue(HeaderNames.accessControlRequestHeaders)

  final def accessControlRequestMethod: Option[CharSequence] =
    headerValue(HeaderNames.accessControlRequestMethod)

  final def age: Option[CharSequence] =
    headerValue(HeaderNames.age)

  final def allow: Option[CharSequence] =
    headerValue(HeaderNames.allow)

  final def authorization: Option[CharSequence] =
    headerValue(HeaderNames.authorization)

  final def basicAuthorizationCredentials: Option[Credentials] = {
    authorization
      .map(_.toString)
      .flatMap(v => {
        val indexOfBasic = v.indexOf(BasicSchemeName)
        if (indexOfBasic != 0 || v.length == BasicSchemeName.length)
          None
        else {
          try {
            val encoded = v.substring(BasicSchemeName.length + 1)
            decodeHttpBasic(encoded)
          } catch {
            case NonFatal(_) => None
          }
        }
      })
  }

  final def bearerToken: Option[String] = authorization
    .map(_.toString)
    .flatMap(v => {
      val indexOfBearer = v.indexOf(BearerSchemeName)
      if (indexOfBearer != 0 || v.length == BearerSchemeName.length)
        None
      else
        Some(v.substring(BearerSchemeName.length + 1))
    })

  final def cacheControl: Option[CharSequence] =
    headerValue(HeaderNames.cacheControl)

  final def charset: Charset =
    headerValue(HeaderNames.contentType) match {
      case Some(value) => HttpUtil.getCharset(value, HTTP_CHARSET)
      case None        => HTTP_CHARSET
    }

  final def connection: Option[CharSequence] =
    headerValue(HeaderNames.connection)

  final def contentBase: Option[CharSequence] =
    headerValue(HeaderNames.contentBase)

  final def contentDisposition: Option[CharSequence] =
    headerValue(HeaderNames.contentDisposition)

  final def contentEncoding: Option[CharSequence] =
    headerValue(HeaderNames.contentEncoding)

  final def contentLanguage: Option[CharSequence] =
    headerValue(HeaderNames.contentLanguage)

  final def contentLength: Option[Long] =
    headerValue(HeaderNames.contentLength) match {
      case Some(str) =>
        try Some(str.toString.toLong)
        catch {
          case _: Throwable => None
        }
      case None      => None
    }

  final def contentLocation: Option[CharSequence] =
    headerValue(HeaderNames.contentLocation)

  final def contentMd5: Option[CharSequence] =
    headerValue(HeaderNames.contentMd5)

  final def contentRange: Option[CharSequence] =
    headerValue(HeaderNames.contentRange)

  final def contentSecurityPolicy: Option[CharSequence] =
    headerValue(HeaderNames.contentSecurityPolicy)

  final def contentTransferEncoding: Option[CharSequence] =
    headerValue(HeaderNames.contentTransferEncoding)

  final def contentType: Option[CharSequence] =
    headerValue(HeaderNames.contentType)

  final def cookie: Option[CharSequence] =
    headerValue(HeaderNames.cookie)

  final def cookieValue(name: CharSequence): Option[CharSequence] =
    cookiesDecoded.find(_.name == name).map(_.content)

  final def cookiesDecoded: List[Cookie] =
    headerValues(HeaderNames.cookie).flatMap { header =>
      Cookie.decodeRequestCookie(header) match {
        case None       => Nil
        case Some(list) => list
      }
    }

  final def date: Option[CharSequence] =
    headerValue(HeaderNames.date)

  final def dnt: Option[CharSequence] =
    headerValue(HeaderNames.dnt)

  final def etag: Option[CharSequence] =
    headerValue(HeaderNames.etag)

  final def expect: Option[CharSequence] =
    headerValue(HeaderNames.expect)

  final def expires: Option[CharSequence] =
    headerValue(HeaderNames.expires)

  final def from: Option[CharSequence] =
    headerValue(HeaderNames.from)

  final def header(headerName: CharSequence): Option[Header] =
    headers.toList
      .find(h => contentEqualsIgnoreCase(h._1, headerName))

  final def headerValue(headerName: CharSequence): Option[String] =
    header(headerName).map(_._2.toString)

  final def headerValues(headerName: CharSequence): List[String] =
    headers.toList.collect { case h if contentEqualsIgnoreCase(h._1, headerName) => h._2.toString }

  /**
   * Returns the Headers object on the current type A
   */
  def headers: Headers

  final def headersAsList: List[(String, String)] = self.headers.toList

  final def host: Option[CharSequence] =
    headerValue(HeaderNames.host)

  final def ifMatch: Option[CharSequence] =
    headerValue(HeaderNames.ifMatch)

  final def ifModifiedSince: Option[CharSequence] =
    headerValue(HeaderNames.ifModifiedSince)

  final def ifModifiedSinceDecoded: Option[Date] =
    ifModifiedSince.map(date => ServerTime.parse(date.toString))

  final def ifNoneMatch: Option[CharSequence] =
    headerValue(HeaderNames.ifNoneMatch)

  final def ifRange: Option[CharSequence] =
    headerValue(HeaderNames.ifRange)

  final def ifUnmodifiedSince: Option[CharSequence] =
    headerValue(HeaderNames.ifUnmodifiedSince)

  final def lastModified: Option[CharSequence] =
    headerValue(HeaderNames.lastModified)

  final def location: Option[CharSequence] =
    headerValue(HeaderNames.location)

  final def maxForwards: Option[CharSequence] =
    headerValue(HeaderNames.maxForwards)

  final def mediaType: Option[MediaType] =
    contentType.flatMap(ct => MediaType.forContentType(ct.toString))

  final def origin: Option[CharSequence] =
    headerValue(HeaderNames.origin)

  final def pragma: Option[CharSequence] =
    headerValue(HeaderNames.pragma)

  final def proxyAuthenticate: Option[CharSequence] =
    headerValue(HeaderNames.proxyAuthenticate)

  final def proxyAuthorization: Option[CharSequence] =
    headerValue(HeaderNames.proxyAuthorization)

  final def range: Option[CharSequence] =
    headerValue(HeaderNames.range)

  final def referer: Option[CharSequence] =
    headerValue(HeaderNames.referer)

  final def retryAfter: Option[CharSequence] =
    headerValue(HeaderNames.retryAfter)

  final def secWebSocketAccept: Option[CharSequence] =
    headerValue(HeaderNames.secWebSocketAccept)

  final def secWebSocketExtensions: Option[CharSequence] =
    headerValue(HeaderNames.secWebSocketExtensions)

  final def secWebSocketKey: Option[CharSequence] =
    headerValue(HeaderNames.secWebSocketKey)

  final def secWebSocketLocation: Option[CharSequence] =
    headerValue(HeaderNames.secWebSocketLocation)

  final def secWebSocketOrigin: Option[CharSequence] =
    headerValue(HeaderNames.secWebSocketOrigin)

  final def secWebSocketProtocol: Option[CharSequence] =
    headerValue(HeaderNames.secWebSocketProtocol)

  final def secWebSocketVersion: Option[CharSequence] =
    headerValue(HeaderNames.secWebSocketVersion)

  final def server: Option[CharSequence] =
    headerValue(HeaderNames.server)

  final def setCookie: Option[CharSequence] =
    headerValue(HeaderNames.setCookie)

  final def setCookiesDecoded(secret: Option[String] = None): List[Cookie] =
    headerValues(HeaderNames.setCookie)
      .map(Cookie.decodeResponseCookie(_, secret))
      .collect { case Some(cookie) => cookie }

  final def te: Option[CharSequence] =
    headerValue(HeaderNames.te)

  final def trailer: Option[CharSequence] =
    headerValue(HeaderNames.trailer)

  final def transferEncoding: Option[CharSequence] =
    headerValue(HeaderNames.transferEncoding)

  final def upgrade: Option[CharSequence] =
    headerValue(HeaderNames.upgrade)

  final def upgradeInsecureRequests: Option[CharSequence] =
    headerValue(HeaderNames.upgradeInsecureRequests)

  final def userAgent: Option[CharSequence] =
    headerValue(HeaderNames.userAgent)

  final def vary: Option[CharSequence] =
    headerValue(HeaderNames.vary)

  final def via: Option[CharSequence] =
    headerValue(HeaderNames.via)

  final def warning: Option[CharSequence] =
    headerValue(HeaderNames.warning)

  final def webSocketLocation: Option[CharSequence] =
    headerValue(HeaderNames.webSocketLocation)

  final def webSocketOrigin: Option[CharSequence] =
    headerValue(HeaderNames.webSocketOrigin)

  final def webSocketProtocol: Option[CharSequence] =
    headerValue(HeaderNames.webSocketProtocol)

  final def wwwAuthenticate: Option[CharSequence] =
    headerValue(HeaderNames.wwwAuthenticate)

  final def xFrameOptions: Option[CharSequence] =
    headerValue(HeaderNames.xFrameOptions)

  final def xRequestedWith: Option[CharSequence] =
    headerValue(HeaderNames.xRequestedWith)

  private def decodeHttpBasic(encoded: String): Option[Credentials] = {
    val decoded    = new String(Base64.getDecoder.decode(encoded))
    val colonIndex = decoded.indexOf(":")
    if (colonIndex == -1)
      None
    else {
      val username = decoded.substring(0, colonIndex)
      val password =
        if (colonIndex == decoded.length - 1)
          ""
        else
          decoded.substring(colonIndex + 1)
      Some(Credentials(username, password))
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy