1
1
package org .scalasteward .core .client
2
2
3
- import org .http4s .client ._
4
- import org .http4s .headers .`User-Agent`
5
3
import cats .effect ._
6
4
import cats .implicits ._
7
- import org .http4s .implicits ._
8
- import org .typelevel .ci ._
9
5
import munit .CatsEffectSuite
10
6
import org .http4s .HttpRoutes
11
- import org .http4s .headers .Location
7
+ import org .http4s .client ._
8
+ import org .http4s .headers .{`Retry-After` , `User-Agent` , Location }
9
+ import org .http4s .implicits ._
10
+ import org .typelevel .ci ._
11
+ import eu .timepit .refined .auto ._
12
+ import eu .timepit .refined .types .numeric .PosInt
12
13
13
14
class ClientConfigurationTest extends CatsEffectSuite {
15
+
14
16
private val userAgentValue = " my-user-agent"
15
17
private val dummyUserAgent =
16
18
`User-Agent`.parse(userAgentValue).getOrElse(fail(" unable to create user agent" ))
@@ -35,12 +37,21 @@ class ClientConfigurationTest extends CatsEffectSuite {
35
37
36
38
case GET -> Root / " redirected" =>
37
39
BadRequest (" Got redirected" )
40
+
41
+ case req @ GET -> Root / " retry-after" =>
42
+ val maybeAttempt = req.headers.get(ci " X-Attempt " ).flatMap(_.head.value.toIntOption)
43
+ maybeAttempt match {
44
+ case Some (attempt) if attempt >= 2 =>
45
+ Ok ()
46
+ case _ =>
47
+ Forbidden ().map(_.putHeaders(`Retry-After`.fromLong(1 )))
48
+ }
38
49
}
39
50
}
40
51
41
52
test(" setUserAgent add a specific user agent to requests" ) {
42
- import org .http4s .client .dsl .io ._
43
53
import org .http4s .Method ._
54
+ import org .http4s .client .dsl .io ._
44
55
45
56
val initialClient = Client .fromHttpApp[IO ](routes.orNotFound)
46
57
val setUserAgent = ClientConfiguration .setUserAgent[IO ](dummyUserAgent)
@@ -59,9 +70,9 @@ class ClientConfigurationTest extends CatsEffectSuite {
59
70
}
60
71
61
72
test(" disableFollowRedirect does not follow redirect" ) {
73
+ import org .http4s .Method ._
62
74
import org .http4s .blaze .server ._
63
75
import org .http4s .client .dsl .io ._
64
- import org .http4s .Method ._
65
76
66
77
val regularClient = ClientConfiguration .build[IO ](
67
78
ClientConfiguration .BuilderMiddleware .default,
@@ -84,4 +95,27 @@ class ClientConfigurationTest extends CatsEffectSuite {
84
95
}
85
96
test.assertEquals((400 , 302 ))
86
97
}
98
+
99
+ test(" retries on retry-after response header" ) {
100
+ import org .http4s .Method ._
101
+ import org .http4s .client .dsl .io ._
102
+
103
+ def clientWithMaxAttempts (maxAttempts : PosInt ): Client [IO ] = {
104
+ val initialClient = Client .fromHttpApp[IO ](routes.orNotFound)
105
+ val retryAfter = ClientConfiguration .retryAfter[IO ](maxAttempts)
106
+ retryAfter(initialClient)
107
+ }
108
+
109
+ val notEnoughRetries = clientWithMaxAttempts(1 )
110
+ .run(GET (uri " /retry-after " ))
111
+ .use(r => r.status.code.pure[IO ])
112
+ .assertEquals(403 )
113
+
114
+ val exactlyEnoughRetries = clientWithMaxAttempts(2 )
115
+ .run(GET (uri " /retry-after " ))
116
+ .use(r => r.status.code.pure[IO ])
117
+ .assertEquals(200 )
118
+
119
+ notEnoughRetries.flatMap(_ => exactlyEnoughRetries)
120
+ }
87
121
}
0 commit comments