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

com.malliina.http.FullUrl.scala Maven / Gradle / Ivy

There is a newer version: 3.7.3
Show newest version
package com.malliina.http

import java.net.URLEncoder
import java.util.regex.Pattern
import com.malliina.values.{ErrorMessage, ValidatingCompanion}

import java.nio.charset.StandardCharsets

case class FullUrl(proto: String, hostAndPort: String, uri: String) {
  val host = hostAndPort.takeWhile(_ != ':')
  val protoAndHost = s"$proto://$hostAndPort"
  val url = s"$protoAndHost$uri"

  def /(more: String): FullUrl = {
    if (uri.endsWith("/")) append(more.dropWhile(_ == '/'))
    else append(if (more.startsWith("/")) more else s"/$more")
  }

  def +(more: String) = append(more)

  def append(more: String): FullUrl = FullUrl(proto, hostAndPort, s"$uri$more")

  def withUri(uri: String) = FullUrl(proto, hostAndPort, uri)

  /** URL encodes the values in `map`, and adds them to the query string.
    *
    * @param map query string values
    * @return a new URL with the query strings applied
    */
  def query(map: Map[String, String]): FullUrl = {
    val encoded = map.mapValues(v => URLEncoder.encode(v, StandardCharsets.UTF_8.name()))
    withQuery(encoded.toSeq: _*)
  }

  def withQuery(qs: (String, String)*): FullUrl = {
    val asString = qs.map { case (k, v) => s"$k=$v" }.mkString("&")
    val firstChar = if (uri.contains("?")) "&" else "?"
    append(s"$firstChar$asString")
  }

  override def toString: String = url
}

object FullUrl extends ValidatingCompanion[String, FullUrl] {
  val urlPattern = Pattern compile """(.+)://([^/]+)(/?.*)"""

  def https(domain: String, uri: String): FullUrl =
    FullUrl("https", dropHttps(domain), uri)

  def host(domain: String): FullUrl =
    FullUrl("https", dropHttps(domain), "")

  def ws(domain: String, uri: String): FullUrl =
    FullUrl("ws", domain, uri)

  def wss(domain: String, uri: String): FullUrl =
    FullUrl("wss", domain, uri)

  private def dropHttps(domain: String) = {
    val prefix = "https://"
    if (domain.startsWith(prefix)) domain.drop(prefix.length) else domain
  }

  override def write(t: FullUrl) = t.url

  override def build(input: String): Either[ErrorMessage, FullUrl] = {
    val m = urlPattern.matcher(input)
    if (m.find() && m.groupCount() == 3) {
      Right(FullUrl(m group 1, m group 2, m group 3))
    } else {
      Left(ErrorMessage(s"Invalid URL: '$input'."))
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy