blob: 1a33931f317f0c5f08e7b45c42775808458f9b2d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
//
// RESTResponseHandler.swift
// MullvadREST
//
// Created by pronebird on 25/04/2022.
// Copyright © 2022 Mullvad VPN AB. All rights reserved.
//
import Foundation
protocol RESTResponseHandler {
associatedtype Success
func handleURLResponse(_ response: HTTPURLResponse, data: Data) -> REST
.ResponseHandlerResult<Success>
}
extension REST {
/// Responser handler result type.
enum ResponseHandlerResult<Success> {
/// Response handler succeeded and produced a value.
case success(Success)
/// Response handler succeeded and returned a block that decodes the value.
case decoding(_ decoderBlock: () throws -> Success)
/// Response handler received the response that it cannot handle.
/// Server error response is attached when available.
case unhandledResponse(ServerErrorResponse?)
}
final class AnyResponseHandler<Success>: RESTResponseHandler {
typealias HandlerBlock = (HTTPURLResponse, Data) -> REST.ResponseHandlerResult<Success>
private let handlerBlock: HandlerBlock
init(_ block: @escaping HandlerBlock) {
handlerBlock = block
}
func handleURLResponse(_ response: HTTPURLResponse, data: Data) -> REST
.ResponseHandlerResult<Success>
{
return handlerBlock(response, data)
}
}
/// Returns default response handler that parses JSON response into the
/// given `Decodable` type when it encounters HTTP `2xx` code, otherwise
/// attempts to decode the server error.
static func defaultResponseHandler<T: Decodable>(
decoding type: T.Type,
with decoder: JSONDecoder
) -> AnyResponseHandler<T> {
return AnyResponseHandler { response, data in
if HTTPStatus.isSuccess(response.statusCode) {
return .decoding {
try decoder.decode(type, from: data)
}
} else {
return .unhandledResponse(
try? decoder.decode(
ServerErrorResponse.self,
from: data
)
)
}
}
}
}
|