@@ -92,10 +92,33 @@ class _TCPSocket {
92
92
_ = try attempt ( " read " , valid: isNotNegative, CInt ( read ( connectionSocket, & buffer, 4096 ) ) )
93
93
return String ( cString: & buffer)
94
94
}
95
+
96
+ func split( _ str: String , _ count: Int ) -> [ String ] {
97
+ return stride ( from: 0 , to: str. characters. count, by: count) . map { i -> String in
98
+ let startIndex = str. index ( str. startIndex, offsetBy: i)
99
+ let endIndex = str. index ( startIndex, offsetBy: count, limitedBy: str. endIndex) ?? str. endIndex
100
+ return str [ startIndex..< endIndex]
101
+ }
102
+ }
95
103
96
- func writeData( data: String ) throws {
97
- var bytes = Array ( data. utf8)
98
- _ = try attempt ( " write " , valid: isNotNegative, CInt ( write ( connectionSocket, & bytes, data. utf8. count) ) )
104
+ func writeData( header: String , body: String , sendDelay: TimeInterval ? = nil , bodyChunks: Int ? = nil ) throws {
105
+ var header = Array ( header. utf8)
106
+ _ = try attempt ( " write " , valid: isNotNegative, CInt ( write ( connectionSocket, & header, header. count) ) )
107
+
108
+ if let sendDelay = sendDelay, let bodyChunks = bodyChunks {
109
+ let count = max ( 1 , Int ( Double ( body. utf8. count) / Double( bodyChunks) ) )
110
+ let texts = split ( body, count)
111
+
112
+ for item in texts {
113
+ sleep ( UInt32 ( sendDelay) )
114
+ var bytes = Array ( item. utf8)
115
+ print ( item)
116
+ _ = try attempt ( " write " , valid: isNotNegative, CInt ( write ( connectionSocket, & bytes, bytes. count) ) )
117
+ }
118
+ } else {
119
+ var bytes = Array ( body. utf8)
120
+ _ = try attempt ( " write " , valid: isNotNegative, CInt ( write ( connectionSocket, & bytes, bytes. count) ) )
121
+ }
99
122
}
100
123
101
124
func shutdown( ) {
@@ -128,8 +151,24 @@ class _HTTPServer {
128
151
return _HTTPRequest ( request: try socket. readData ( ) )
129
152
}
130
153
131
- public func respond( with response: _HTTPResponse ) throws {
132
- try socket. writeData ( data: response. description)
154
+ public func respond( with response: _HTTPResponse , startDelay: TimeInterval ? = nil , sendDelay: TimeInterval ? = nil , bodyChunks: Int ? = nil ) throws {
155
+ let semaphore = DispatchSemaphore ( value: 0 )
156
+ let deadlineTime : DispatchTime
157
+
158
+ if let startDelay = startDelay {
159
+ deadlineTime = . now( ) + . seconds( Int ( startDelay) )
160
+ } else {
161
+ deadlineTime = . now( )
162
+ }
163
+
164
+ DispatchQueue . main. asyncAfter ( deadline: deadlineTime) {
165
+ do {
166
+ try self . socket. writeData ( header: response. header, body: response. body, sendDelay: sendDelay, bodyChunks: bodyChunks)
167
+ semaphore. signal ( )
168
+ } catch { }
169
+ }
170
+ semaphore. wait ( )
171
+
133
172
}
134
173
}
135
174
@@ -160,17 +199,17 @@ struct _HTTPResponse {
160
199
}
161
200
private let responseCode : Response
162
201
private let headers : String
163
- private let body : String
202
+ public let body : String
164
203
165
204
public init ( response: Response , headers: String = _HTTPUtils. EMPTY, body: String ) {
166
205
self . responseCode = response
167
206
self . headers = headers
168
207
self . body = body
169
208
}
170
209
171
- public var description : String {
210
+ public var header : String {
172
211
let statusLine = _HTTPUtils. VERSION + _HTTPUtils. SPACE + " \( responseCode. rawValue) " + _HTTPUtils. SPACE + " \( responseCode) "
173
- return statusLine + ( headers != _HTTPUtils. EMPTY ? _HTTPUtils. CRLF + headers : _HTTPUtils. EMPTY) + _HTTPUtils. CRLF2 + body
212
+ return statusLine + ( headers != _HTTPUtils. EMPTY ? _HTTPUtils. CRLF + headers : _HTTPUtils. EMPTY) + _HTTPUtils. CRLF2
174
213
}
175
214
}
176
215
@@ -181,18 +220,24 @@ public class TestURLSessionServer {
181
220
" USA " : " Washington, D.C. " ,
182
221
" country.txt " : " A country is a region that is identified as a distinct national entity in political geography " ]
183
222
let httpServer : _HTTPServer
223
+ let startDelay : TimeInterval ?
224
+ let sendDelay : TimeInterval ?
225
+ let bodyChunks : Int ?
184
226
185
- public init ( port: UInt16 ) throws {
227
+ public init ( port: UInt16 , startDelay : TimeInterval ? = nil , sendDelay : TimeInterval ? = nil , bodyChunks : Int ? = nil ) throws {
186
228
httpServer = try _HTTPServer. create ( port: port)
229
+ self . startDelay = startDelay
230
+ self . sendDelay = sendDelay
231
+ self . bodyChunks = bodyChunks
187
232
}
188
233
public func start( started: ServerSemaphore ) throws {
189
234
started. signal ( )
190
235
try httpServer. listen ( notify: started)
191
236
}
192
237
193
238
public func readAndRespond( ) throws {
194
- try httpServer. respond ( with: process ( request: httpServer. request ( ) ) )
195
- }
239
+ try httpServer. respond ( with: process ( request: httpServer. request ( ) ) , startDelay : self . startDelay , sendDelay : self . sendDelay , bodyChunks : self . bodyChunks )
240
+ }
196
241
197
242
func process( request: _HTTPRequest ) -> _HTTPResponse {
198
243
if request. method == . GET {
0 commit comments