@@ -8,69 +8,83 @@ public enum HttpRequestResult {
8
8
}
9
9
10
10
public protocol HttpClientType {
11
- var httpUtilities : HttpUtilitiesType { get }
12
- func loadData( request: NSMutableURLRequestType ) -> Observable < HttpRequestResult >
13
- func loadStreamData( request: NSMutableURLRequestType , cacheProvider: CacheProviderType ? ) -> Observable < StreamTaskResult >
11
+ func createUrlRequest( url: NSURL ) -> NSMutableURLRequestType
12
+ func createUrlRequest( url: NSURL , headers: [ String : String ] ? ) -> NSMutableURLRequestType
13
+ func loadData( request: NSURLRequestType ) -> Observable < HttpRequestResult >
14
+ func loadStreamData( request: NSURLRequestType , cacheProvider: CacheProviderType ? ) -> Observable < StreamTaskResult >
15
+ func createStreamDataTask( request: NSURLRequestType , cacheProvider: CacheProviderType ? ) -> StreamDataTaskType
14
16
}
15
17
16
18
public class HttpClient {
17
- public let httpUtilities : HttpUtilitiesType
19
+ internal let httpUtilities : HttpUtilitiesType
18
20
internal let scheduler = SerialDispatchQueueScheduler ( globalConcurrentQueueQOS: DispatchQueueSchedulerQOS . Utility)
21
+ internal let sessionConfiguration : NSURLSessionConfiguration
22
+ internal let shouldInvalidateSession : Bool
19
23
20
- public init ( httpUtilities: HttpUtilitiesType = HttpUtilities ( ) ) {
21
-
24
+ internal lazy var urlSession : NSURLSessionType = {
25
+ return self . httpUtilities. createUrlSession ( self . sessionConfiguration, delegate: self . sessionObserver as? NSURLSessionDataDelegate , queue: nil )
26
+ } ( )
27
+
28
+ internal lazy var sessionObserver : NSURLSessionDataEventsObserverType = {
29
+ return self . httpUtilities. createUrlSessionStreamObserver ( )
30
+ } ( )
31
+
32
+ internal init ( sessionConfiguration: NSURLSessionConfiguration , httpUtilities: HttpUtilitiesType ) {
33
+ self . httpUtilities = httpUtilities
34
+ self . sessionConfiguration = sessionConfiguration
35
+ shouldInvalidateSession = true
36
+ }
37
+
38
+ internal init ( urlSession: NSURLSessionType , httpUtilities: HttpUtilitiesType ) {
22
39
self . httpUtilities = httpUtilities
40
+ shouldInvalidateSession = false
41
+ self . sessionConfiguration = urlSession. configuration
42
+ self . urlSession = urlSession
43
+ }
44
+
45
+ public convenience init ( urlSession: NSURLSessionType ) {
46
+ self . init ( urlSession: urlSession, httpUtilities: HttpUtilities ( ) )
47
+ }
48
+
49
+ public convenience init ( sessionConfiguration: NSURLSessionConfiguration = NSURLSessionConfiguration . defaultSessionConfiguration ( ) ) {
50
+ self . init ( sessionConfiguration: sessionConfiguration, httpUtilities: HttpUtilities ( ) )
51
+ }
52
+
53
+ deinit {
54
+ guard shouldInvalidateSession else { return }
55
+ urlSession. invalidateAndCancel ( )
23
56
}
24
57
}
25
58
26
59
extension HttpClient : HttpClientType {
27
- public func loadData( request: NSMutableURLRequestType )
28
- -> Observable < HttpRequestResult > {
29
- return Observable . create { [ weak self] observer in
30
- guard let object = self else { observer. onCompleted ( ) ; return NopDisposable . instance }
31
-
32
- let task = object. httpUtilities. createStreamDataTask ( NSUUID ( ) . UUIDString,
33
- request: request, sessionConfiguration: NSURLSession . defaultConfig, cacheProvider: nil )
34
-
35
- let receivedData = NSMutableData ( )
36
-
37
- let disposable = task. taskProgress. catchError { error in
38
- observer. onNext ( . error( error) )
39
- observer. onCompleted ( )
40
- return Observable . empty ( )
41
- } . doOnCompleted { observer. onCompleted ( ) } . bindNext { result in
42
- if case Result . success( let box) = result {
43
- if case StreamTaskEvents . ReceiveData( let data) = box. value {
44
- receivedData. appendData ( data)
45
- } else if case StreamTaskEvents . Success = box. value {
46
- if receivedData. length > 0 {
47
- observer. onNext ( . successData( receivedData) )
48
- } else {
49
- observer. onNext ( . success)
50
- }
51
- }
52
- } else if case Result . error( let error) = result {
53
- observer. onNext ( . error( error) )
54
- }
55
- }
56
-
57
- task. resume ( )
60
+ public func createUrlRequest( url: NSURL , headers: [ String : String ] ? ) -> NSMutableURLRequestType {
61
+ return httpUtilities. createUrlRequest ( url, headers: headers)
62
+ }
63
+
64
+ public func createUrlRequest( url: NSURL ) -> NSMutableURLRequestType {
65
+ return createUrlRequest ( url, headers: nil )
66
+ }
67
+
68
+ public func loadData( request: NSURLRequestType ) -> Observable < HttpRequestResult > {
69
+ return loadStreamData ( request, cacheProvider: MemoryCacheProvider ( uid: NSUUID ( ) . UUIDString) ) . flatMapLatest { result -> Observable < HttpRequestResult > in
70
+ switch result {
71
+ case Result . error( let error) : return Observable . just ( . error( error) )
72
+ case Result . success( let box) :
73
+ guard case StreamTaskEvents . Success( let cache) = box. value else { return Observable . empty ( ) }
58
74
59
- return AnonymousDisposable {
60
- task . cancel ( )
61
- disposable . dispose ( )
62
- }
63
- } . observeOn ( scheduler) . shareReplay ( 0 )
75
+ guard let cacheProvider = cache where cacheProvider . currentDataLength > 0 else { return Observable . just ( . success ) }
76
+
77
+ return Observable . just ( . successData ( cacheProvider . getCurrentData ( ) ) )
78
+ }
79
+ } . observeOn ( scheduler) . shareReplay ( 0 )
64
80
}
65
81
66
- public func loadStreamData( request: NSMutableURLRequestType , cacheProvider: CacheProviderType ? )
67
- -> Observable < StreamTaskResult > {
82
+ public func loadStreamData( request: NSURLRequestType , cacheProvider: CacheProviderType ? ) -> Observable < StreamTaskResult > {
68
83
return Observable . create { [ weak self] observer in
69
84
guard let object = self else { observer. onCompleted ( ) ; return NopDisposable . instance }
70
85
71
- let task = object. httpUtilities. createStreamDataTask ( NSUUID ( ) . UUIDString, request: request, sessionConfiguration: NSURLSession . defaultConfig,
72
- cacheProvider: cacheProvider)
73
-
86
+ let task = object. createStreamDataTask ( request, cacheProvider: cacheProvider)
87
+
74
88
let disposable = task. taskProgress. catchError { error in
75
89
observer. onNext ( Result . error ( error) )
76
90
observer. onCompleted ( )
@@ -91,4 +105,13 @@ extension HttpClient : HttpClientType {
91
105
}
92
106
} . observeOn ( scheduler) . shareReplay ( 0 )
93
107
}
108
+
109
+ public func createStreamDataTask( request: NSURLRequestType , cacheProvider: CacheProviderType ? ) -> StreamDataTaskType {
110
+ let dataTask = urlSession. dataTaskWithRequest ( request)
111
+ return httpUtilities. createStreamDataTask ( NSUUID ( ) . UUIDString,
112
+ dataTask: dataTask,
113
+ httpClient: self ,
114
+ sessionEvents: sessionObserver. sessionEvents,
115
+ cacheProvider: cacheProvider)
116
+ }
94
117
}
0 commit comments