1
1
package sttp .client4
2
2
3
- import sttp .capabilities .{Effect , Streams , WebSockets }
3
+ import sttp .capabilities .Effect
4
+ import sttp .capabilities .Streams
5
+ import sttp .capabilities .WebSockets
6
+ import sttp .client4 .ResponseException .DeserializationException
7
+ import sttp .client4 .ResponseException .UnexpectedStatusCode
4
8
import sttp .client4 .internal .SttpFile
5
9
import sttp .model .ResponseMetadata
6
10
import sttp .model .internal .Rfc3986
7
- import sttp .ws .{WebSocket , WebSocketFrame }
11
+ import sttp .ws .WebSocket
12
+ import sttp .ws .WebSocketFrame
8
13
9
14
import java .io .InputStream
10
15
import scala .collection .immutable .Seq
11
- import scala .util .{Failure , Success , Try }
16
+ import scala .util .Failure
17
+ import scala .util .Success
18
+ import scala .util .Try
12
19
13
20
/** Describes how the response body of a request should be handled. A number of `as<Type>` helper methods are available
14
21
* as part of [[SttpApi ]] and when importing `sttp.client4._`. These methods yield specific implementations of this
@@ -77,30 +84,30 @@ case class ResponseAs[+T](delegate: GenericResponseAs[T, Any]) extends ResponseA
77
84
)
78
85
79
86
/** If the type to which the response body should be deserialized is an `Either[A, B]`:
80
- * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[HttpError ]] if `A` is not
81
- * yet an exception)
87
+ * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[UnexpectedStatusCode ]] if
88
+ * `A` is not yet an exception)
82
89
* - in case of `B`, returns the value directly
83
90
*/
84
91
def orFail [A , B ](implicit tIsEither : T <:< Either [A , B ]): ResponseAs [B ] =
85
92
mapWithMetadata { case (t, meta) =>
86
93
(t : Either [A , B ]) match {
87
94
case Left (a : Exception ) => throw a
88
- case Left (a) => throw HttpError (a, meta.code )
95
+ case Left (a) => throw UnexpectedStatusCode (a, meta)
89
96
case Right (b) => b
90
97
}
91
98
}
92
99
93
- /** If the type to which the response body should be deserialized is an `Either[ResponseException[HE, DE ], B]`, either
100
+ /** If the type to which the response body should be deserialized is an `Either[ResponseException[HE], B]`, either
94
101
* throws / returns a failed effect with the [[DeserializationException ]], returns the deserialized body from the
95
- * [[HttpError ]], or the deserialized successful body `B`.
102
+ * [[UnexpectedStatusCode ]], or the deserialized successful body `B`.
96
103
*/
97
- def orFailDeserialization [HE , DE , B ](implicit
98
- tIsEither : T <:< Either [ResponseException [HE , DE ], B ]
104
+ def orFailDeserialization [HE , B ](implicit
105
+ tIsEither : T <:< Either [ResponseException [HE ], B ]
99
106
): ResponseAs [Either [HE , B ]] = map { t =>
100
- (t : Either [ResponseException [HE , DE ], B ]) match {
101
- case Left (HttpError (he, _)) => Left (he)
102
- case Left (d : DeserializationException [_] ) => throw d
103
- case Right (b) => Right (b)
107
+ (t : Either [ResponseException [HE ], B ]) match {
108
+ case Left (UnexpectedStatusCode (he, _)) => Left (he)
109
+ case Left (d : DeserializationException ) => throw d
110
+ case Right (b) => Right (b)
104
111
}
105
112
}
106
113
@@ -109,22 +116,22 @@ case class ResponseAs[+T](delegate: GenericResponseAs[T, Any]) extends ResponseA
109
116
110
117
object ResponseAs {
111
118
112
- /** Returns a function, which maps `Left` values to [[HttpError ]] s, and attempts to deserialize `Right` values using
113
- * the given function, catching any exceptions and representing them as [[DeserializationException ]] s.
119
+ /** Returns a function, which maps `Left` values to [[UnexpectedStatusCode ]] s, and attempts to deserialize `Right`
120
+ * values using the given function, catching any exceptions and representing them as [[DeserializationException ]] s.
114
121
*/
115
122
def deserializeRightCatchingExceptions [T ](
116
123
doDeserialize : String => T
117
- ): (Either [String , String ], ResponseMetadata ) => Either [ResponseException [String , Exception ], T ] = {
118
- case (Left (s), meta) => Left (HttpError (s, meta.code ))
119
- case (Right (s), _) => deserializeCatchingExceptions(doDeserialize)(s)
124
+ ): (Either [String , String ], ResponseMetadata ) => Either [ResponseException [String ], T ] = {
125
+ case (Left (s), meta) => Left (UnexpectedStatusCode (s, meta))
126
+ case (Right (s), meta) => deserializeCatchingExceptions(doDeserialize)(s, meta )
120
127
}
121
128
122
129
/** Returns a function, which attempts to deserialize `Right` values using the given function, catching any exceptions
123
130
* and representing them as [[DeserializationException ]] s.
124
131
*/
125
132
def deserializeCatchingExceptions [T ](
126
133
doDeserialize : String => T
127
- ): String => Either [DeserializationException [ Exception ] , T ] =
134
+ ): ( String , ResponseMetadata ) => Either [DeserializationException , T ] =
128
135
deserializeWithError((s : String ) =>
129
136
Try (doDeserialize(s)) match {
130
137
case Failure (e : Exception ) => Left (e)
@@ -133,63 +140,65 @@ object ResponseAs {
133
140
}
134
141
)
135
142
136
- /** Returns a function, which maps `Left` values to [[HttpError ]] s, and attempts to deserialize `Right` values using
137
- * the given function.
143
+ /** Returns a function, which maps `Left` values to [[UnexpectedStatusCode ]] s, and attempts to deserialize `Right`
144
+ * values using the given function.
138
145
*/
139
- def deserializeRightWithError [E : ShowError , T ](
140
- doDeserialize : String => Either [E , T ]
141
- ): (Either [String , String ], ResponseMetadata ) => Either [ResponseException [String , E ], T ] = {
142
- case (Left (s), meta) => Left (HttpError (s, meta.code ))
143
- case (Right (s), _) => deserializeWithError(doDeserialize)(implicitly[ ShowError [ E ]])(s )
146
+ def deserializeRightWithError [T ](
147
+ doDeserialize : String => Either [Exception , T ]
148
+ ): (Either [String , String ], ResponseMetadata ) => Either [ResponseException [String ], T ] = {
149
+ case (Left (s), meta) => Left (UnexpectedStatusCode (s, meta))
150
+ case (Right (s), meta) => deserializeWithError(doDeserialize)(s, meta )
144
151
}
145
152
146
153
/** Returns a function, which keeps `Left` unchanged, and attempts to deserialize `Right` values using the given
147
154
* function. If deserialization fails, an exception is thrown
148
155
*/
149
- def deserializeRightOrThrow [E : ShowError , T ](
150
- doDeserialize : String => Either [E , T ]
151
- ): Either [String , String ] => Either [String , T ] = {
152
- case Left (s) => Left (s)
153
- case Right (s) => Right (deserializeOrThrow(doDeserialize)(implicitly[ ShowError [ E ]])(s ))
156
+ def deserializeRightOrThrow [T ](
157
+ doDeserialize : String => Either [Exception , T ]
158
+ ): ( Either [String , String ], ResponseMetadata ) => Either [String , T ] = {
159
+ case ( Left (s), _ ) => Left (s)
160
+ case ( Right (s), m) => Right (deserializeOrThrow(doDeserialize)(s, m ))
154
161
}
155
162
156
163
/** Converts a deserialization function, which returns errors of type `E`, into a function where errors are wrapped
157
164
* using [[DeserializationException ]].
158
165
*/
159
- def deserializeWithError [E : ShowError , T ](
160
- doDeserialize : String => Either [E , T ]
161
- ): String => Either [DeserializationException [ E ] , T ] =
162
- s =>
166
+ def deserializeWithError [T ](
167
+ doDeserialize : String => Either [Exception , T ]
168
+ ): ( String , ResponseMetadata ) => Either [DeserializationException , T ] =
169
+ (s, meta) =>
163
170
doDeserialize(s) match {
164
- case Left (e) => Left (DeserializationException (s, e))
171
+ case Left (e) => Left (DeserializationException (s, e, meta ))
165
172
case Right (b) => Right (b)
166
173
}
167
174
168
175
/** Converts a deserialization function, which returns errors of type `E`, into a function where errors are thrown as
169
176
* exceptions, and results are returned unwrapped.
170
177
*/
171
- def deserializeOrThrow [E : ShowError , T ](doDeserialize : String => Either [E , T ]): String => T =
172
- s =>
178
+ def deserializeOrThrow [T ](
179
+ doDeserialize : String => Either [Exception , T ]
180
+ ): (String , ResponseMetadata ) => T =
181
+ (s, meta) =>
173
182
doDeserialize(s) match {
174
- case Left (e) => throw DeserializationException (s, e)
183
+ case Left (e) => throw DeserializationException (s, e, meta )
175
184
case Right (b) => b
176
185
}
177
186
178
187
/** Converts deserialization functions, which both return errors of type `E`, into a function where errors are thrown
179
- * as exceptions, and results are parsed using either of the functions, depending if the response was successfull , or
188
+ * as exceptions, and results are parsed using either of the functions, depending if the response was successful , or
180
189
* not.
181
190
*/
182
- def deserializeEitherWithErrorOrThrow [E : ShowError , T , T2 ](
183
- doDeserializeHttpError : String => Either [E , T ],
184
- doDeserializeHttpSuccess : String => Either [E , T2 ]
191
+ def deserializeEitherWithErrorOrThrow [T , T2 ](
192
+ doDeserializeHttpError : String => Either [Exception , T ],
193
+ doDeserializeHttpSuccess : String => Either [Exception , T2 ]
185
194
): (String , ResponseMetadata ) => Either [T , T2 ] =
186
195
(s, m) =>
187
- if (m.isSuccess) Right (deserializeOrThrow(doDeserializeHttpSuccess).apply(s))
188
- else Left (deserializeOrThrow(doDeserializeHttpError).apply(s))
196
+ if (m.isSuccess) Right (deserializeOrThrow(doDeserializeHttpSuccess).apply(s, m ))
197
+ else Left (deserializeOrThrow(doDeserializeHttpError).apply(s, m ))
189
198
190
199
/** Converts deserialization functions, which both throw exceptions upon errors, into a function where errors still
191
200
* thrown as exceptions, and results are parsed using either of the functions, depending if the response was
192
- * successfull , or not.
201
+ * successful , or not.
193
202
*/
194
203
def deserializeEitherOrThrow [T , T2 ](
195
204
doDeserializeHttpError : String => T ,
@@ -226,15 +235,15 @@ case class StreamResponseAs[+T, S](delegate: GenericResponseAs[T, S]) extends Re
226
235
StreamResponseAs (delegate.mapWithMetadata(f))
227
236
228
237
/** If the type to which the response body should be deserialized is an `Either[A, B]`:
229
- * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[HttpError ]] if `A` is not
230
- * yet an exception)
238
+ * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[UnexpectedStatusCode ]] if
239
+ * `A` is not yet an exception)
231
240
* - in case of `B`, returns the value directly
232
241
*/
233
242
def orFail [A , B ](implicit tIsEither : T <:< Either [A , B ]): StreamResponseAs [B , S ] =
234
243
mapWithMetadata { case (t, meta) =>
235
244
(t : Either [A , B ]) match {
236
245
case Left (a : Exception ) => throw a
237
- case Left (a) => throw HttpError (a, meta.code )
246
+ case Left (a) => throw UnexpectedStatusCode (a, meta)
238
247
case Right (b) => b
239
248
}
240
249
}
@@ -267,15 +276,15 @@ case class WebSocketResponseAs[F[_], +T](delegate: GenericResponseAs[T, Effect[F
267
276
WebSocketResponseAs (delegate.mapWithMetadata(f))
268
277
269
278
/** If the type to which the response body should be deserialized is an `Either[A, B]`:
270
- * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[HttpError ]] if `A` is not
271
- * yet an exception)
279
+ * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[UnexpectedStatusCode ]] if
280
+ * `A` is not yet an exception)
272
281
* - in case of `B`, returns the value directly
273
282
*/
274
283
def orFail [A , B ](implicit tIsEither : T <:< Either [A , B ]): WebSocketResponseAs [F , B ] =
275
284
mapWithMetadata { case (t, meta) =>
276
285
(t : Either [A , B ]) match {
277
286
case Left (a : Exception ) => throw a
278
- case Left (a) => throw HttpError (a, meta.code )
287
+ case Left (a) => throw UnexpectedStatusCode (a, meta)
279
288
case Right (b) => b
280
289
}
281
290
}
@@ -308,15 +317,15 @@ case class WebSocketStreamResponseAs[+T, S](delegate: GenericResponseAs[T, S wit
308
317
WebSocketStreamResponseAs [T2 , S ](delegate.mapWithMetadata(f))
309
318
310
319
/** If the type to which the response body should be deserialized is an `Either[A, B]`:
311
- * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[HttpError ]] if `A` is not
312
- * yet an exception)
320
+ * - in case of `A`, throws as an exception / returns a failed effect (wrapped with an [[UnexpectedStatusCode ]] if
321
+ * `A` is not yet an exception)
313
322
* - in case of `B`, returns the value directly
314
323
*/
315
324
def orFail [A , B ](implicit tIsEither : T <:< Either [A , B ]): WebSocketStreamResponseAs [B , S ] =
316
325
mapWithMetadata { case (t, meta) =>
317
326
(t : Either [A , B ]) match {
318
327
case Left (a : Exception ) => throw a
319
- case Left (a) => throw HttpError (a, meta.code )
328
+ case Left (a) => throw UnexpectedStatusCode (a, meta)
320
329
case Right (b) => b
321
330
}
322
331
}
0 commit comments