Skip to content

Instantly share code, notes, and snippets.

@yannick-cw
Created February 26, 2018 14:19
Show Gist options
  • Save yannick-cw/959e93117e1c7c8f1733bca2d96ae94c to your computer and use it in GitHub Desktop.
Save yannick-cw/959e93117e1c7c8f1733bca2d96ae94c to your computer and use it in GitHub Desktop.
package com.holidaycheck.userflow
import scala.util.Try
object UrlKata {
case class Protocol(value: String) extends AnyVal
case class Domain(value: String) extends AnyVal
case class Params(params: List[(String, String)]) extends AnyVal
case class Path(value: String) extends AnyVal
case class Url(protocol: Protocol, domain: Domain, params: Params, path: Option[Path] = None)
def parse(str: String): Either[String, Url] = str match {
case proto :|| domain / path ? params => Right(Url(proto, domain, params, path))
case _ => Left(s"Failed parsing $str")
}
object :|| {
val ProtocolR = """(https?)://(.+)""".r
def unapply(url: String): Option[(Protocol, String)] = url match {
case ProtocolR(prot, rest) => Some((Protocol(prot), rest))
case _ => None
}
}
object / {
val DomainR = """www\.(.+\..+)/(.*)""".r
def unapply(url: String): Option[(Domain, String)] = url match {
case DomainR(domain, rest) => Some((Domain(domain), rest))
case _ => None
}
}
object ? {
val PathR = """([^\?]*)\??(.*)""".r
private def pathParams(params: String) =
Params(
params
.drop(1)
.split("&")
.flatMap { keyValue =>
Try {
val Array(key, value) = keyValue.split("=")
(key, value)
}.toOption
}
.toList)
def unapply(path: String): Option[(Option[Path], Params)] = path match {
case PathR(p, params) if p.nonEmpty => Some((Some(Path(p)), pathParams(params)))
case PathR(_, params) => Some((None, pathParams(params)))
}
}
}
package com.holidaycheck.userflow
import com.holidaycheck.userflow.UrlKata._
import org.scalatest.{FlatSpec, Matchers}
class UrlKataSpec extends FlatSpec with Matchers {
val emptyParams = Params(List.empty)
it should "parse an url" in {
UrlKata.parse("http://www.holidaycheck.com/") shouldBe Right(
Url(Protocol("http"), Domain("holidaycheck.com"), emptyParams))
}
it should "parse an https protocol url" in {
UrlKata.parse("https://www.holidaycheck.com/") shouldBe Right(
Url(Protocol("https"), Domain("holidaycheck.com"), emptyParams))
}
it should "also parse query parameter and path" in {
UrlKata.parse("https://www.holidaycheck.com/passion?search=xx&test=ab") shouldBe Right(
Url(Protocol("https"),
Domain("holidaycheck.com"),
Params(List(("search", "xx"), ("test", "ab"))),
Some(Path("passion"))))
}
// it should "work with more complicated urls" in {
// UrlKata.parse("https://images.cdn.holidaycheck.com/passions?q=yoga&hotel=fun%20stuff#a=1&b=2") shouldBe Right(
// Url(Protocol("https"), Domain("images.cdn.holidaycheck.com"), Params(List(("search", "xx"), ("test", "ab")))))
// )
// }
it should "filter out broken parameter" in {
UrlKata.parse("https://www.holidaycheck.com/?watdasIs") shouldBe Right(
Url(Protocol("https"), Domain("holidaycheck.com"), emptyParams))
}
it should "fail parsing an invalid url" in {
UrlKata.parse("http//www.holidaycheck.com/").isLeft shouldBe true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment