@@ -16,17 +16,17 @@ public enum EventSourceState {
1616
1717public protocol EventSourceProtocol {
1818 var headers : [ String : String ] { get }
19-
19+
2020 /// RetryTime: This can be changed remotly if the server sends an event `retry:`
2121 var retryTime : Int { get }
22-
22+
2323 /// The last event id received from server. This id is neccesary to keep track of the last event-id received to avoid
2424 /// receiving duplicate events after a reconnection.
2525 var lastEventId : String ? { get }
26-
26+
2727 /// Current state of EventSource
2828 var readyState : EventSourceState { get }
29-
29+
3030 /// Method used to connect to server.
3131 ///
3232 /// It can receive an optional lastEventId indicating the Last-Event-ID.
@@ -37,39 +37,39 @@ public protocol EventSourceProtocol {
3737 /// - Parameter httpBody: http body to use for this connection.
3838 /// - Parameter lastEventId: optional value that is going to be added on the request header to server.
3939 func connect( url: URL , headers: [ String : String ] , httpMethod: String , httpBody: Data ? , lastEventId: String ? )
40-
40+
4141 /// Method used to disconnect from server.
4242 func disconnect( )
43-
43+
4444 /// Returns the list of event names that we are currently listening for.
4545 ///
4646 /// - Returns: List of event names.
4747 func events( ) -> [ String ]
48-
48+
4949 /// Callback called when EventSource has successfully connected to the server.
5050 ///
5151 /// - Parameter onOpenCallback: callback
5252 func onOpen( _ onOpenCallback: @escaping ( ( ) -> Void ) )
53-
53+
5454 /// Callback called once EventSource has disconnected from server. This can happen for multiple reasons.
5555 /// The server could have requested the disconnection or maybe a network layer error, wrong URL or any other
5656 /// error. The callback receives as parameters the status code of the disconnection, if we should reconnect or not
5757 /// following event source rules and finally the network layer error if any. All this information is more than
5858 /// enought for you to take a decition if you should reconnect or not.
5959 /// - Parameter onOpenCallback: callback
6060 func onComplete( _ onComplete: @escaping ( ( Int ? , Bool ? , NSError ? ) -> Void ) )
61-
61+
6262 /// This callback is called everytime an event with name "message" or no name is received.
6363 func onMessage( _ onMessageCallback: @escaping ( ( _ id: String ? , _ event: String ? , _ data: String ? ) -> Void ) )
64-
64+
6565 /// Add an event handler for an specific event name.
6666 ///
6767 /// - Parameters:
6868 /// - event: name of the event to receive
6969 /// - handler: this handler will be called everytime an event is received with this event-name
7070 func addEventListener( _ event: String ,
7171 handler: @escaping ( ( _ id: String ? , _ event: String ? , _ data: String ? ) -> Void ) )
72-
72+
7373 /// Remove an event handler for the event-name
7474 ///
7575 /// - Parameter event: name of the listener to be remove from event source.
@@ -78,31 +78,31 @@ public protocol EventSourceProtocol {
7878
7979open class EventSource : NSObject , EventSourceProtocol , URLSessionDataDelegate {
8080 static let DefaultRetryTime = 3000
81-
81+
8282 private( set) public var lastEventId : String ?
8383 private( set) public var retryTime = EventSource . DefaultRetryTime
8484 private( set) public var headers : [ String : String ]
8585 private( set) public var readyState : EventSourceState
86-
86+
8787 private var onOpenCallback : ( ( ) -> Void ) ?
8888 private var onComplete : ( ( Int ? , Bool ? , NSError ? ) -> Void ) ?
8989 private var onMessageCallback : ( ( _ id: String ? , _ event: String ? , _ data: String ? ) -> Void ) ?
9090 private var eventListeners : [ String : ( _ id: String ? , _ event: String ? , _ data: String ? ) -> Void ] = [ : ]
91-
91+
9292 private var eventStreamParser : EventStreamParser ?
9393 private var operationQueue : OperationQueue
9494 private var mainQueue = DispatchQueue . main
9595 private var urlSession : URLSession ?
96-
96+
9797 public override init ( ) {
9898 headers = [ : ]
9999 readyState = EventSourceState . closed
100100 operationQueue = OperationQueue ( )
101101 operationQueue. maxConcurrentOperationCount = 1
102-
102+
103103 super. init ( )
104104 }
105-
105+
106106 public func connect(
107107 url: URL ,
108108 headers: [ String : String ] = [ : ] ,
@@ -113,139 +113,139 @@ open class EventSource: NSObject, EventSourceProtocol, URLSessionDataDelegate {
113113 self . headers = headers
114114 eventStreamParser = EventStreamParser ( )
115115 readyState = . connecting
116-
116+
117117 let configuration = sessionConfiguration ( lastEventId: lastEventId)
118118 urlSession = URLSession ( configuration: configuration, delegate: self , delegateQueue: operationQueue)
119119 var request = URLRequest ( url: url)
120120 request. httpMethod = httpMethod
121121 request. httpBody = httpBody
122122 urlSession? . dataTask ( with: request) . resume ( )
123123 }
124-
124+
125125 public func disconnect( ) {
126126 readyState = . closed
127127 urlSession? . invalidateAndCancel ( )
128128 }
129-
129+
130130 public func onOpen( _ onOpenCallback: @escaping ( ( ) -> Void ) ) {
131131 self . onOpenCallback = onOpenCallback
132132 }
133-
133+
134134 public func onComplete( _ onComplete: @escaping ( ( Int ? , Bool ? , NSError ? ) -> Void ) ) {
135135 self . onComplete = onComplete
136136 }
137-
137+
138138 public func onMessage( _ onMessageCallback: @escaping ( ( _ id: String ? , _ event: String ? , _ data: String ? ) -> Void ) ) {
139139 self . onMessageCallback = onMessageCallback
140140 }
141-
141+
142142 public func addEventListener( _ event: String ,
143143 handler: @escaping ( ( _ id: String ? , _ event: String ? , _ data: String ? ) -> Void ) ) {
144144 eventListeners [ event] = handler
145145 }
146-
146+
147147 public func removeEventListener( _ event: String ) {
148148 eventListeners. removeValue ( forKey: event)
149149 }
150-
150+
151151 public func events( ) -> [ String ] {
152152 return Array ( eventListeners. keys)
153153 }
154-
154+
155155 open func urlSession( _ session: URLSession , dataTask: URLSessionDataTask , didReceive data: Data ) {
156-
156+
157157 if readyState != . open {
158158 return
159159 }
160-
160+
161161 if let events = eventStreamParser? . append ( data: data) {
162162 notifyReceivedEvents ( events)
163163 }
164164 }
165-
165+
166166 open func urlSession( _ session: URLSession ,
167167 dataTask: URLSessionDataTask ,
168168 didReceive response: URLResponse ,
169169 completionHandler: @escaping ( URLSession . ResponseDisposition ) -> Void ) {
170-
170+
171171 completionHandler ( URLSession . ResponseDisposition. allow)
172-
172+
173173 readyState = . open
174174 mainQueue. async { [ weak self] in self ? . onOpenCallback ? ( ) }
175175 }
176-
176+
177177 open func urlSession( _ session: URLSession ,
178178 task: URLSessionTask ,
179179 didCompleteWithError error: Error ? ) {
180-
180+
181181 guard let responseStatusCode = ( task. response as? HTTPURLResponse ) ? . statusCode else {
182182 mainQueue. async { [ weak self] in self ? . onComplete ? ( nil , nil , error as NSError ? ) }
183183 return
184184 }
185-
185+
186186 let reconnect = shouldReconnect ( statusCode: responseStatusCode)
187187 mainQueue. async { [ weak self] in self ? . onComplete ? ( responseStatusCode, reconnect, nil ) }
188188 }
189-
189+
190190 open func urlSession( _ session: URLSession ,
191191 task: URLSessionTask ,
192192 willPerformHTTPRedirection response: HTTPURLResponse ,
193193 newRequest request: URLRequest ,
194194 completionHandler: @escaping ( URLRequest ? ) -> Void ) {
195-
195+
196196 var newRequest = request
197197 self . headers. forEach { newRequest. setValue ( $1, forHTTPHeaderField: $0) }
198198 completionHandler ( newRequest)
199199 }
200200}
201201
202202internal extension EventSource {
203-
203+
204204 func sessionConfiguration( lastEventId: String ? ) -> URLSessionConfiguration {
205-
205+
206206 var additionalHeaders = headers
207207 if let eventID = lastEventId {
208208 additionalHeaders [ " Last-Event-Id " ] = eventID
209209 }
210-
210+
211211 additionalHeaders [ " Accept " ] = " text/event-stream "
212212 additionalHeaders [ " Cache-Control " ] = " no-cache "
213-
213+
214214 let sessionConfiguration = URLSessionConfiguration . default
215215 sessionConfiguration. timeoutIntervalForRequest = TimeInterval ( INT_MAX)
216216 sessionConfiguration. timeoutIntervalForResource = TimeInterval ( INT_MAX)
217217 sessionConfiguration. httpAdditionalHeaders = additionalHeaders
218-
218+
219219 return sessionConfiguration
220220 }
221-
221+
222222 func readyStateOpen( ) {
223223 readyState = . open
224224 }
225225}
226226
227227private extension EventSource {
228-
228+
229229 func notifyReceivedEvents( _ events: [ Event ] ) {
230-
230+
231231 for event in events {
232232 lastEventId = event. id
233233 retryTime = event. retryTime ?? EventSource . DefaultRetryTime
234-
234+
235235 if event. onlyRetryEvent == true {
236236 continue
237237 }
238-
238+
239239 if event. event == nil || event. event == " message " {
240240 mainQueue. async { [ weak self] in self ? . onMessageCallback ? ( event. id, " message " , event. data) }
241241 }
242-
242+
243243 if let eventName = event. event, let eventHandler = eventListeners [ eventName] {
244244 mainQueue. async { eventHandler ( event. id, event. event, event. data) }
245245 }
246246 }
247247 }
248-
248+
249249 // Following "5 Processing model" from:
250250 // https://www.w3.org/TR/2009/WD-eventsource-20090421/#handler-eventsource-onerror
251251 func shouldReconnect( statusCode: Int ) -> Bool {
0 commit comments