Skip to content

Commit

Permalink
Simplify the interface of URL.decode by only returning one possible…
Browse files Browse the repository at this point in the history
… `Exception`, and not any possible `Exception`
  • Loading branch information
guizmaii committed Aug 15, 2024
1 parent 8cfa0b8 commit b2c76b0
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ private[http] object UrlInterpolatorMacro {
c.prefix.tree match {
case Apply(_, List(Apply(_, Literal(Constant(p: String)) :: Nil))) =>
val result = URL.decode(p) match {
case Left(error) => c.abort(c.enclosingPosition, s"Invalid URL: ${error.getMessage}")
case Left(error) => c.abort(c.enclosingPosition, error.getMessage)
case Right(url) =>
val uri = url.encode
q"_root_.zio.http.URL.fromURI(new _root_.java.net.URI($uri)).get"
Expand Down Expand Up @@ -68,9 +68,8 @@ private[http] object UrlInterpolatorMacro {
val exampleParts = staticParts.zipAll(injectedPartExamples, "", "").flatMap { case (a, b) => List(a, b) }
val example = exampleParts.mkString
URL.decode(example) match {
case Left(error) =>
c.abort(c.enclosingPosition, s"Invalid URL: ${error.getMessage}")
case Right(url) =>
case Left(error) => c.abort(c.enclosingPosition, error.getMessage)
case Right(_) =>
val parts =
staticParts.map { s => Literal(Constant(s)) }
.zipAll(args.map(_.tree), Literal(Constant("")), Literal(Constant("")))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ object ConnectionPoolConfig {
URL
.decode(s)
.left
.map(error => Config.Error.InvalidData(message = s"Invalid URL: ${error.getMessage}"))
.map(error => Config.Error.InvalidData(message = error.getMessage))
.flatMap { url =>
url.kind match {
case url: URL.Location.Absolute => Right(url -> fixed)
Expand All @@ -67,7 +67,7 @@ object ConnectionPoolConfig {
URL
.decode(s)
.left
.map(error => Config.Error.InvalidData(message = s"Invalid URL: ${error.getMessage}"))
.map(error => Config.Error.InvalidData(message = error.getMessage))
.flatMap { url =>
url.kind match {
case url: URL.Location.Absolute => Right(url -> fixed)
Expand Down
2 changes: 1 addition & 1 deletion zio-http/shared/src/main/scala/zio/http/Request.scala
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ object Request {
*/
private def pathOrUrl(path: String): URL =
if (path.startsWith("http://") || path.startsWith("https://")) {
URL.decode(path).toOption.getOrElse(URL(Path(path)))
URL.decode(path).getOrElse(URL(Path(path)))
} else {
URL(Path(path))
}
Expand Down
30 changes: 21 additions & 9 deletions zio-http/shared/src/main/scala/zio/http/URL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package zio.http

import java.net.{MalformedURLException, URI}
import java.io.IOException
import java.net.URI

import scala.util.control.NonFatal

import zio.Config

Expand Down Expand Up @@ -279,26 +282,35 @@ final case class URL(
}

object URL {
def empty: URL = URL(Path.empty)
val empty: URL = URL(path = Path.empty)

/**
* Proper implementation of [[java.net.MalformedURLException]] which, unlike
* the Java version, can propagate the cause.
*/
final case class MalformedURLException private[http] (rawUrl: String, cause: Option[Throwable])
extends IOException(cause.orNull) {
override def getMessage: String = s"""Invalid URL: "$rawUrl""""
}

def decode(string: String): Either[Exception, URL] = {
def invalidURL(string: String) = Left(new MalformedURLException(s"""Invalid URL: "$string""""))
def decode(rawUrl: String): Either[MalformedURLException, URL] = {
def invalidURL(e: Option[Throwable]): Either[MalformedURLException, URL] =
Left(MalformedURLException(rawUrl = rawUrl, cause = e))

try {
val uri = new URI(string)
val uri = new URI(rawUrl)
val url = if (uri.isAbsolute) fromAbsoluteURI(uri) else fromRelativeURI(uri)

url match {
case None => invalidURL(string)
case None => invalidURL(None)
case Some(value) => Right(value)
}

} catch {
case e: Exception => Left(e)
case NonFatal(e) => invalidURL(Some(e))
}
}

def config: Config[URL] = Config.string.mapAttempt(decode(_).toTry.get)
def config: Config[URL] = Config.string.mapAttempt(decode(_).fold(throw _, identity))

def fromURI(uri: URI): Option[URL] = if (uri.isAbsolute) fromAbsoluteURI(uri) else fromRelativeURI(uri)

Expand Down

2 comments on commit b2c76b0

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 : Performance Benchmarks (SimpleEffectBenchmarkServer)

concurrency: 256
requests/sec: 339427

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 : Performance Benchmarks (PlainTextBenchmarkServer)

concurrency: 256
requests/sec: 330333

Please sign in to comment.