@@ -3,93 +3,6 @@ import Foundation
33import FoundationNetworking
44#endif
55
6- public enum AsposeBarcodeCloudClientError : Error , CustomStringConvertible , @unchecked Sendable {
7- case missingCredentials
8- case invalidTokenURL( String )
9- case invalidTokenResponse
10- case tokenRequestFailed( statusCode: Int , body: String ? )
11- case transportError( Error )
12-
13- public var description : String {
14- switch self {
15- case . missingCredentials:
16- return " Access token or clientId/clientSecret are required "
17- case let . invalidTokenURL( url) :
18- return " Invalid token URL: \( url) "
19- case . invalidTokenResponse:
20- return " Token response does not contain access_token "
21- case let . tokenRequestFailed( statusCode, body) :
22- if let body = body, !body. isEmpty {
23- return " Token request failed with status \( statusCode) : \( body) "
24- }
25- return " Token request failed with status \( statusCode) "
26- case let . transportError( error) :
27- return error. localizedDescription
28- }
29- }
30- }
31-
32- public final class AsposeBarcodeCloudConfiguration : @unchecked Sendable {
33- public static let defaultHost = " https://api.aspose.cloud/v4.0 "
34- public static let defaultTokenURL = " https://id.aspose.cloud/connect/token "
35- public static let defaultSdkName = " swift sdk "
36- public static let defaultSdkVersion = " 26.4.0 "
37-
38- public var host : String
39- public var tokenURL : String
40- public var accessToken : String ?
41- public var clientId : String ?
42- public var clientSecret : String ?
43- public var sdkName : String
44- public var sdkVersion : String
45- public var timeoutInterval : TimeInterval
46-
47- public init (
48- accessToken: String ? = nil ,
49- clientId: String ? = nil ,
50- clientSecret: String ? = nil ,
51- host: String = AsposeBarcodeCloudConfiguration . defaultHost,
52- tokenURL: String = AsposeBarcodeCloudConfiguration . defaultTokenURL,
53- sdkName: String = AsposeBarcodeCloudConfiguration . defaultSdkName,
54- sdkVersion: String = AsposeBarcodeCloudConfiguration . defaultSdkVersion,
55- timeoutInterval: TimeInterval = 300
56- ) {
57- self . accessToken = accessToken
58- self . clientId = clientId
59- self . clientSecret = clientSecret
60- self . host = host
61- self . tokenURL = tokenURL
62- self . sdkName = sdkName
63- self . sdkVersion = sdkVersion
64- self . timeoutInterval = timeoutInterval
65- }
66-
67- public func makeTokenRequest( ) throws -> URLRequest {
68- guard let clientId = clientId, !clientId. isEmpty,
69- let clientSecret = clientSecret, !clientSecret. isEmpty else {
70- throw AsposeBarcodeCloudClientError . missingCredentials
71- }
72-
73- guard let url = URL ( string: tokenURL) else {
74- throw AsposeBarcodeCloudClientError . invalidTokenURL ( tokenURL)
75- }
76-
77- var components = URLComponents ( )
78- components. queryItems = [
79- URLQueryItem ( name: " grant_type " , value: " client_credentials " ) ,
80- URLQueryItem ( name: " client_id " , value: clientId) ,
81- URLQueryItem ( name: " client_secret " , value: clientSecret) ,
82- ]
83-
84- var request = URLRequest ( url: url)
85- request. httpMethod = " POST "
86- request. timeoutInterval = timeoutInterval
87- request. setValue ( " application/x-www-form-urlencoded " , forHTTPHeaderField: " Content-Type " )
88- request. httpBody = components. percentEncodedQuery? . data ( using: . utf8)
89- return request
90- }
91- }
92-
936public typealias AsposeBarcodeCloudTokenFetcher = @Sendable (
947 AsposeBarcodeCloudConfiguration ,
958 @escaping @Sendable ( Result < String , AsposeBarcodeCloudClientError > ) -> Void
@@ -218,114 +131,3 @@ public final class AsposeBarcodeCloudClient: @unchecked Sendable {
218131 } . resume ( )
219132 }
220133}
221-
222- final class BarcodeAuthInterceptor : OpenAPIInterceptor , @unchecked Sendable {
223- private let configuration : AsposeBarcodeCloudConfiguration
224- private let tokenFetcher : AsposeBarcodeCloudTokenFetcher
225- private let state : OpenAPIMutex < State >
226-
227- private struct State {
228- var token : String ?
229- var inFlightFetch : Bool
230- var pendingWaiters : [ @Sendable ( Result < String , AsposeBarcodeCloudClientError > ) -> Void ]
231- }
232-
233- init (
234- configuration: AsposeBarcodeCloudConfiguration ,
235- tokenFetcher: @escaping AsposeBarcodeCloudTokenFetcher
236- ) {
237- self . configuration = configuration
238- self . tokenFetcher = tokenFetcher
239- let initialToken = configuration. accessToken. flatMap { $0. isEmpty ? nil : $0 }
240- self . state = OpenAPIMutex ( State (
241- token: initialToken,
242- inFlightFetch: false ,
243- pendingWaiters: [ ]
244- ) )
245- }
246-
247- func intercept< T> (
248- urlRequest: URLRequest ,
249- urlSession: URLSessionProtocol ,
250- requestBuilder: RequestBuilder < T > ,
251- completion: @Sendable @escaping ( Result < URLRequest , any Error > ) -> Void
252- ) {
253- guard requestBuilder. requiresAuthentication else {
254- completion ( . success( urlRequest) )
255- return
256- }
257-
258- ensureToken { result in
259- switch result {
260- case let . success( token) :
261- var modified = urlRequest
262- modified. setValue ( " Bearer \( token) " , forHTTPHeaderField: " Authorization " )
263- completion ( . success( modified) )
264- case let . failure( error) :
265- completion ( . failure( error) )
266- }
267- }
268- }
269-
270- func retry< T> (
271- urlRequest: URLRequest ,
272- urlSession: URLSessionProtocol ,
273- requestBuilder: RequestBuilder < T > ,
274- data: Data ? ,
275- response: URLResponse ? ,
276- error: any Error ,
277- completion: @Sendable @escaping ( OpenAPIInterceptorRetry ) -> Void
278- ) {
279- completion ( . dontRetry)
280- }
281-
282- func ensureToken( completion: @escaping @Sendable ( Result < String , AsposeBarcodeCloudClientError > ) -> Void ) {
283- enum Action {
284- case immediate( Result < String , AsposeBarcodeCloudClientError > )
285- case wait
286- case startFetch
287- }
288-
289- var action : Action = . wait
290- state. withValue { state in
291- if let token = state. token, !token. isEmpty {
292- action = . immediate( . success( token) )
293- return
294- }
295- state. pendingWaiters. append ( completion)
296- if state. inFlightFetch {
297- action = . wait
298- } else {
299- state. inFlightFetch = true
300- action = . startFetch
301- }
302- }
303-
304- switch action {
305- case let . immediate( result) :
306- completion ( result)
307- case . wait:
308- break
309- case . startFetch:
310- tokenFetcher ( configuration) { [ weak self] result in
311- self ? . deliverToken ( result)
312- }
313- }
314- }
315-
316- private func deliverToken( _ result: Result < String , AsposeBarcodeCloudClientError > ) {
317- var waiters : [ @Sendable ( Result < String , AsposeBarcodeCloudClientError > ) -> Void ] = [ ]
318- state. withValue { state in
319- state. inFlightFetch = false
320- if case let . success( token) = result {
321- state. token = token
322- self . configuration. accessToken = token
323- }
324- waiters = state. pendingWaiters
325- state. pendingWaiters. removeAll ( )
326- }
327- for waiter in waiters {
328- waiter ( result)
329- }
330- }
331- }
0 commit comments