@@ -54,8 +54,11 @@ public protocol ServiceClient {
5454 func send< T: Codable > ( intoResponse: T , request: NSMutableURLRequest ) throws -> T
5555 func sendAsync< T: Codable > ( intoResponse: T , request: NSMutableURLRequest ) -> Promise < T >
5656
57- func getData( _ url: String ) throws -> Data
58- func getDataAsync( _ url: String ) -> Promise < Data >
57+ func getData( url: String ) throws -> ( Data , HTTPURLResponse )
58+ func getDataAsync( url: String ) -> Promise < ( Data , HTTPURLResponse ) >
59+ func getData( request: URLRequest , retryIf: ( ( HTTPURLResponse ) -> Bool ) ? ) throws -> ( Data , HTTPURLResponse )
60+ func getDataAsync( request: URLRequest , retryIf: ( ( HTTPURLResponse ) -> Promise < Bool > ) ? ) -> Promise < ( Data , HTTPURLResponse ) >
61+
5962 func getCookies( ) -> [ String : String ]
6063 func getTokenCookie( ) -> String ?
6164 func getRefreshTokenCookie( ) -> String ?
@@ -274,58 +277,161 @@ open class JsonServiceClient: NSObject, ServiceClient, IHasBearerToken, IHasSess
274277
275278 return req
276279 }
280+
281+ func retryAfterReauth( response: HTTPURLResponse ) -> Bool {
282+ if response. statusCode == 401 {
283+ let hasRefreshTokenCookie = self . getRefreshTokenCookie ( ) != nil
284+ if self . refreshToken != nil || hasRefreshTokenCookie {
285+ return self . fetchNewAccessToken ( )
286+ }
287+ }
288+ return false
289+ }
290+
291+ func retryAfterReauthAsync( response: HTTPURLResponse ) -> Promise < Bool > {
292+ if response. statusCode == 401 {
293+ let hasRefreshTokenCookie = self . getRefreshTokenCookie ( ) != nil
294+ if self . refreshToken != nil || hasRefreshTokenCookie {
295+ return self . fetchNewAccessTokenAsync ( )
296+ }
297+ }
298+ return Promise< Bool> { seal in seal. fulfill ( false ) }
299+ }
277300
278301 @discardableResult
279302 open func send< T: Codable > ( intoResponse: T , request: NSMutableURLRequest ) throws -> T {
303+ let ( data, response) = try getData ( request: request as URLRequest , retryIf: retryAfterReauth)
304+ if data. isEmpty {
305+ return Factory< T> . create( )
306+ }
307+ let dto = try handleResponse ( intoResponse: intoResponse, data: data, response: response)
308+ return dto
309+ }
310+
311+ open func getData( url: String ) throws -> ( Data , HTTPURLResponse ) {
312+ let urlRequest = createRequest ( url: resolveUrl ( url) , httpMethod: HttpMethods . Get)
313+ return try getData ( request: urlRequest as URLRequest )
314+ }
315+
316+ open func getData( request: URLRequest , retryIf: ( ( HTTPURLResponse ) -> Bool ) ? = nil ) throws -> ( Data , HTTPURLResponse ) {
280317 let dataTaskSync = createSession ( ) . dataTaskSync ( request: request as URLRequest )
281318 lastTask = dataTaskSync. task
319+ let cb = dataTaskSync. callback
282320
283- if dataTaskSync . callback ? . response == nil {
284- if let error = dataTaskSync . callback ? . error {
321+ if cb ? . response == nil {
322+ if let error = cb ? . error {
285323 throw error
286324 }
287- return Factory < T > . create ( )
325+ return ( Data ( ) , HTTPURLResponse ( ) )
288326 }
289327
290328 var error : NSError ? = NSError ( domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil )
291- if let data = dataTaskSync. callback? . data,
292- let response = dataTaskSync. callback? . response {
293- let dto = try self . handleResponse ( intoResponse: intoResponse, data: data, response: response, error: & error)
294- return dto
329+ if let data = cb? . data, let response = cb? . response as? HTTPURLResponse {
330+ if let ex = self . createIfError ( response, data, error: & error) {
331+ if let fn = retryIf {
332+ let success = fn ( response)
333+ if success {
334+ return try getData ( request: request)
335+ }
336+ }
337+ throw ex
338+ }
339+ return ( data, response)
295340 }
296341
297- return Factory< T> . create( )
342+ return ( Data ( ) , HTTPURLResponse ( ) )
343+ }
344+
345+ open func fetchNewAccessToken( ) -> Bool {
346+ let jwtRequest = GetAccessToken ( )
347+ jwtRequest. refreshToken = self . refreshToken
348+ let request = self . createRequestDto (
349+ url: self . replyUrl. combinePath ( Reflect< GetAccessToken> . typeName) ,
350+ httpMethod: HttpMethods . Post,
351+ request: jwtRequest)
352+ do {
353+ let ( data, response) = try getData ( request: request as URLRequest )
354+ let dto = try handleResponse ( intoResponse: GetAccessTokenResponse ( ) , data: data, response: response)
355+ self . bearerToken = dto. accessToken
356+ return true
357+ } catch let e {
358+ Log . debug ( " \( e) " )
359+ return false
360+ }
298361 }
299362
300363 @discardableResult
301364 open func sendAsync< T: Codable > ( intoResponse: T , request: NSMutableURLRequest ) -> Promise < T > {
302- let pendingPromise = Promise< T> . pending( )
303- let task = createSession ( ) . dataTask ( with: request as URLRequest ) { data, response, error in
304- if error != nil {
305- pendingPromise. resolver. reject ( self . handleError ( nsError: error! as NSError ) )
306- } else {
307- var error : NSError ? = NSError ( domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil )
308- do {
309- if let data = data,
310- let response = response {
311-
312- let nsResponse = response as! HTTPURLResponse
313- if let ex = self . createIfError ( nsResponse, data, error: & error) {
314- pendingPromise. resolver. reject ( ex)
365+ return getDataAsync ( request: request as URLRequest , retryIf: retryAfterReauthAsync)
366+ . map { ( data, response) in
367+ let dto = try self . handleResponse ( intoResponse: intoResponse, data: data, response: response)
368+ return dto
369+ }
370+ }
371+
372+ open func getDataAsync( request: URLRequest , retryIf: ( ( HTTPURLResponse ) -> Promise < Bool > ) ? = nil ) -> Promise < ( Data , HTTPURLResponse ) > {
373+ return Promise { seal in
374+ let task = createSession ( ) . dataTask ( with: request as URLRequest ) { data, response, error in
375+ if let error = error {
376+ seal. reject ( self . handleError ( nsError: error as NSError ) )
377+ } else if let response = response as? HTTPURLResponse , let data = data {
378+ var error : NSError ? = NSError ( domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil )
379+ if let ex = self . createIfError ( response, data, error: & error) {
380+ if let fn = retryIf {
381+ _ = fn ( response) . done { success in
382+ if success {
383+ self . getDataAsync ( request: request)
384+ . done { ( response, data) in
385+ seal. fulfill ( ( response, data) )
386+ } . catch { retryEx in
387+ seal. reject ( retryEx)
388+ }
389+ } else {
390+ seal. reject ( ex)
391+ }
392+ }
315393 } else {
316- let dto = try self . handleResponse ( intoResponse: intoResponse, data: data, response: response)
317- pendingPromise. resolver. fulfill ( dto)
394+ seal. reject ( ex)
318395 }
396+ } else {
397+ seal. fulfill ( ( data, response) )
319398 }
320- } catch let e {
321- pendingPromise . resolver . reject ( e )
399+ } else {
400+ seal . fulfill ( ( Data ( ) , response as? HTTPURLResponse ?? HTTPURLResponse ( ) ) )
322401 }
323402 }
403+ lastTask = task
404+ task. resume ( )
324405 }
406+ }
407+
408+ open func getDataAsync( url: String ) -> Promise < ( Data , HTTPURLResponse ) > {
409+ let urlRequest = createRequest ( url: resolveUrl ( url) , httpMethod: HttpMethods . Get)
410+ return getDataAsync ( request: urlRequest as URLRequest )
411+ }
412+
413+ open func fetchNewAccessTokenAsync( ) -> Promise < Bool > {
414+ return Promise< Bool> { seal in
415+ let jwtRequest = GetAccessToken ( )
416+ jwtRequest. refreshToken = self . refreshToken
417+ let request = self . createRequestDto (
418+ url: self . replyUrl. combinePath ( Reflect< GetAccessToken> . typeName) ,
419+ httpMethod: HttpMethods . Post,
420+ request: jwtRequest)
421+
422+ getDataAsync ( request: request as URLRequest )
423+ . done { ( data, response) in
424+ let dto = try self . handleResponse ( intoResponse: GetAccessTokenResponse ( ) , data: data, response: response)
425+ self . bearerToken = dto. accessToken
426+ seal. fulfill ( true )
427+ }
428+ . catch { e in
429+ Log . debug ( " \( e) " )
430+ seal. fulfill ( false )
431+ }
432+ }
433+ }
325434
326- task. resume ( )
327- lastTask = task
328- return pendingPromise. promise
329435 open func getCookies( ) -> [ String : String ] {
330436 let ret = urlCookies ( URL ( string: baseUrl) !)
331437 return ret
@@ -570,48 +676,6 @@ open class JsonServiceClient: NSObject, ServiceClient, IHasBearerToken, IHasSess
570676 }
571677}
572678
573- extension JsonServiceClient {
574- open func getData( _ url: String ) throws -> Data {
575- let urlRequest = createRequest ( url: resolveUrl ( url) , httpMethod: HttpMethods . Get)
576- let dataTaskSync = createSession ( ) . dataTaskSync ( request: urlRequest as URLRequest )
577- lastTask = dataTaskSync. task
578-
579- if let data = dataTaskSync. callback? . data {
580- return data
581- }
582-
583- if let error = dataTaskSync. callback? . error {
584- throw error
585- }
586-
587- return Data ( )
588- }
589-
590- open func getDataAsync( _ url: String ) -> Promise < Data > {
591- let urlRequest = createRequest ( url: resolveUrl ( url) , httpMethod: HttpMethods . Get)
592- let pendingPromise = Promise< Data> . pending( )
593-
594- let task = createSession ( ) . dataTask ( with: urlRequest as URLRequest ) { data, _, error in
595- if let error = error {
596- pendingPromise. resolver. reject ( self . handleError ( nsError: error as NSError ) )
597- return
598- }
599-
600- if let data = data {
601- pendingPromise. resolver. fulfill ( data)
602- return
603- }
604-
605- pendingPromise. resolver. fulfill ( Data ( ) )
606- }
607-
608- task. resume ( )
609- lastTask = task
610-
611- return pendingPromise. promise
612- }
613- }
614-
615679extension JsonServiceClient : URLSessionDelegate {
616680 public static func toHostsMap( _ urls: [ String ] ) -> [ String : Int ] {
617681 var to : [ String : Int ] = [ : ]
0 commit comments