As a brief note today, here’s an example of making an HTTP GET
request using ZIO 2 and the Scala sttp library. I also let the user specify a “timeout” value, so the request will timeout, rather than hanging.
As a very important note, this is a blocking approach, not a non-blocking approach.
ZIO 2 HTTP GET request with a timeout example
Here’s the source code and Scala 3 + ZIO 2 + sttp function:
package com.alvinalexander.utils
import zio.*
import sttp.client3.*
import scala.concurrent.TimeoutException
object WebUtils:
/**
* NOTES:
*
* - `attempt` returns `ZIO[Any, Throwable, A]`
* - `timeout` doesn’t make something an exception, it just returns a None
* - an empty `url` creates a `java.lang.IllegalArgumentException`
* - this is a blocking approach
*
* @see See [[https://zio.dev/reference/error-management/recovering/timing-out/]]
* for timeout information.
* @param url The URL to access.
* @param timeoutInMs How long to wait before timing-out the request.
* @return If everything goes well, the HTML body is in the `String`, otherwise
* the failure information is in the `Throwable`.
*/
def getUrlContents(url: String, timeoutInMs: Int = 15_000): ZIO[Any, Throwable, String] =
ZIO.attempt {
val backend = HttpURLConnectionBackend()
val response: Response[Either[String, String]] = basicRequest
.get(uri"$url")
.send(backend)
// might be able to use `ZIO.fromEither(Right(body))`,
// but i want to control the exception text:
response.body match
case Left(body) => throw new Exception(s"Non-2xx response to GET with code ${response.code}")
case Right(body) => body
}.timeoutFail(new TimeoutException)(timeoutInMs.milliseconds)
One thing I do in this code is throw exceptions with the error messages I want. That way (a) I can work with those later, and (b) those exceptions end up in the ZIO “error channel,” i.e., the Throwable
value. If you handle things as shown, the function’s return type signature is:
ZIO[Any, Throwable, String]
If you don’t handle the possible errors as shown, you can end up with other undesirable type signatures, something like these:
ZIO[Any, Any, Throwable |String]
ZIO[Any, Option[Throwable], String]
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
Related
If you’re interested in creating ZIO applications, see my free “Introduction to ZIO 2 applications” video.