Skip to content

Commit

Permalink
Add more examples
Browse files Browse the repository at this point in the history
  • Loading branch information
adamw committed Feb 6, 2025
1 parent e5fc9dc commit 59f250a
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// {cat=Error handling; effects=Direct; backend=HttpClient}: HTTP error handling, adjusting the response description

//> using dep com.softwaremill.sttp.client4::core:4.0.0-M26

package sttp.client4.examples

import sttp.client4.*

@main def httpErrorHandlingAdjustResponse(): Unit =
val backend = DefaultSyncBackend()

// by default the response is read into an Either[String, String], to indicate HTTP success or error
def httpErrorDefault(): Unit =
val response = basicRequest.get(uri"https://httpbin.org/status/400").send(backend)
val body: Either[String, String] = response.body
println(s"HTTP error, response code ${response.code}, body: ${body}")

// using asStringOrFail, any HTTP-level errors (successful connection, but a non-2xx status code)
// are translated into exceptions
def httpErrorOrFail(): Unit =
try
val _ = basicRequest.get(uri"https://httpbin.org/status/400").response(asStringOrFail).send(backend)
catch case e: SttpClientException.ReadException => println(s"Connection exception: $e")

httpErrorDefault()
httpErrorOrFail()
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// {cat=Error handling; effects=Direct; backend=HttpClient}: Parsing the response as JSON, with parsing failures and HTTP errors

//> using dep com.softwaremill.sttp.client4::jsoniter:4.0.0-M26
//> using dep com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:2.33.0

package sttp.client4.examples

import sttp.client4.*
import sttp.client4.jsoniter.*
import com.github.plokhotnyuk.jsoniter_scala.macros.ConfiguredJsonValueCodec

@main def httpErrorHandlingJson(): Unit =
val backend = DefaultSyncBackend()

case class HttpBinIpResponse(origin: String) derives ConfiguredJsonValueCodec
case class HttpBinIpInvalidResponse(myIp: String) derives ConfiguredJsonValueCodec

// the class to which we want to parse (HttpBinIpResponse) matches the response's format - we'll get the result as a Right(...)
def jsonSuccess(): Unit =
val response = basicRequest.get(uri"https://httpbin.org/ip").response(asJson[HttpBinIpResponse]).send(backend)
val body: Either[ResponseException[String], HttpBinIpResponse] = response.body
println(s"JSON success, response code ${response.code}, body: $body")

// the class to which we want to parse (HttpBinIpInvalidResponse) does not match the response's format - we'll get a Left(DeserializationException)
def jsonParsingFailure(): Unit =
val response =
basicRequest.get(uri"https://httpbin.org/ip").response(asJson[HttpBinIpInvalidResponse]).send(backend)
val body: Either[ResponseException[String], HttpBinIpInvalidResponse] = response.body
println(s"JSON parsing failure, response code ${response.code}, body: $body")

// http error - status code 400 - we'll get Left(HttpError)
def httpError(): Unit =
val response =
basicRequest.get(uri"https://httpbin.org/status/400").response(asJson[HttpBinIpResponse]).send(backend)
val body: Either[ResponseException[String], HttpBinIpResponse] = response.body
println(s"HTTP error, response code ${response.code}, body: $body")

// when using asJsonOrFail response description, any parsing failures are thrown as exceptions
def jsonParsingFailureThrowingException(): Unit =
try
val response =
basicRequest.get(uri"https://httpbin.org/ip").response(asJsonOrFail[HttpBinIpInvalidResponse]).send(backend)
val body: HttpBinIpInvalidResponse = response.body
println(s"We should never get here! Body: $body")
catch
case e: SttpClientException.ReadException =>
println(s"Got exception: $e")

jsonSuccess()
jsonParsingFailure()
httpError()
jsonParsingFailureThrowingException()
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// {cat=Error handling; effects=Direct; backend=HttpClient}: HTTP error handling using basicRequest

//> using dep com.softwaremill.sttp.client4::core:4.0.0-M26

package sttp.client4.examples

import sttp.client4.*

@main def httpErrorHandlingUsingBasicRequest(): Unit =
val backend = DefaultSyncBackend()

// using basicRequest, the response is read into an Either[String, String], to
// indicate HTTP success or error
def httpSuccess(): Unit =
val response = basicRequest.get(uri"https://httpbin.org/ip").send(backend)
val body: Either[String, String] = response.body
println(s"HTTP success, response code ${response.code}, body: $body")

def httpError(): Unit =
val response = basicRequest.get(uri"https://httpbin.org/status/400").send(backend)
val body: Either[String, String] = response.body
println(s"HTTP error, response code ${response.code}, body: ${body}")

def connectionException(): Unit =
try println(basicRequest.get(uri"http://does.not.exist").send(backend))
catch case e: SttpClientException.ConnectException => println(s"Connection exception: $e")

httpSuccess()
httpError()
connectionException()
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ private val backend: SyncBackend = DefaultSyncBackend()
private val path: os.Path = os.Path("/tmp/example-file.txt")

@main def cmdOutputStreamingWithOsLib(): Unit = {
os.remove(path)
val _ = os.remove(path)
os.write(path, "CONTENT OF THE SIMPLE FILE USED IN THIS EXAMPLE")
val process = os.proc("cat", path.toString).spawn()
val request = basicRequest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ private val dest: os.Path = os.Path(s"/tmp/file-example-$fileSize-bytes")
private val backend: SyncBackend = DefaultSyncBackend()

@main def downloadFileWithOsLib(): Unit = {
os.remove(dest)
val _ = os.remove(dest)
val request = basicRequest
.get(uri"https://httpbin.org/bytes/$fileSize")
.response(asInputStream(i => os.write(dest, i)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ private val path: os.Path = os.Path("/tmp/example-file.txt")
private val backend: SyncBackend = DefaultSyncBackend()

@main def uploadFileWithOsLib(): Unit = {
os.remove(path)
val _ = os.remove(path)
os.write(path, "THIS IS CONTENT OF TEST FILE")
val request = basicRequest
.post(uri"http://httpbin.org/post")
Expand Down

0 comments on commit 59f250a

Please sign in to comment.