-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathofrep_api.swift
79 lines (69 loc) · 2.98 KB
/
ofrep_api.swift
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
71
72
73
74
75
76
77
78
79
import Foundation
import OpenFeature
class OfrepAPI {
private let networkingService: NetworkingService
private var etag: String = ""
private let options: GoFeatureFlagProviderOptions
init(networkingService: NetworkingService, options: GoFeatureFlagProviderOptions) {
self.networkingService = networkingService
self.options = options
}
func postBulkEvaluateFlags(context: EvaluationContext?) async throws -> (OfrepEvaluationResponse, HTTPURLResponse) {
guard let context = context else {
throw OpenFeatureError.invalidContextError
}
try validateContext(context: context)
guard let url = URL(string: options.endpoint) else {
throw InvalidOptions.invalidEndpoint(message: "endpoint [" + options.endpoint + "] is not valid")
}
let ofrepURL = url.appendingPathComponent("ofrep/v1/evaluate/flags")
var request = URLRequest(url: ofrepURL)
request.httpMethod = "POST"
request.httpBody = try EvaluationRequest.convertEvaluationContext(context: context).asJSONData()
request.setValue(
"application/json",
forHTTPHeaderField: "Content-Type"
)
if etag != "" {
request.setValue(etag, forHTTPHeaderField: "If-None-Match")
}
let (data, response) = try await networkingService.doRequest(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
throw OfrepError.httpResponseCastError
}
if httpResponse.statusCode == 401 {
throw OfrepError.apiUnauthorizedError(response: httpResponse)
}
if httpResponse.statusCode == 403 {
throw OfrepError.forbiddenError(response: httpResponse)
}
if httpResponse.statusCode == 429 {
throw OfrepError.apiTooManyRequestsError(response: httpResponse)
}
if httpResponse.statusCode > 400 {
throw OfrepError.unexpectedResponseError(response: httpResponse)
}
if httpResponse.statusCode == 304 {
return (OfrepEvaluationResponse(flags: [], errorCode: nil, errorDetails: nil), httpResponse)
}
// Store ETag to use it in the next request
if let etagHeaderValue = httpResponse.value(forHTTPHeaderField: "ETag") {
if etagHeaderValue != "" && httpResponse.statusCode == 200 {
etag = etagHeaderValue
}
}
do {
let dto = try JSONDecoder().decode(EvaluationResponseDTO.self, from: data)
let evaluationResponse = OfrepEvaluationResponse.fromEvaluationResponseDTO(dto: dto)
return (evaluationResponse, httpResponse)
} catch {
throw OfrepError.unmarshallError(error: error)
}
}
private func validateContext(context: EvaluationContext) throws {
let targetingKey = context.getTargetingKey()
if targetingKey.isEmpty {
throw OpenFeatureError.targetingKeyMissingError
}
}
}