@@ -21,6 +21,7 @@ open class Client {
2121 open var headers: [String: String] = [
2222 "content-type": "",
2323 "x-sdk-version": "{{spec .title | caseDash }}:{{ language .name | caseLower }}:{{ sdk .version }}"{% if spec .global .defaultHeaders | length > 0 %},{% endif %}
24+
2425{% for key ,header in spec .global .defaultHeaders %}
2526 "{{key }}": "{{header }}"{% if not loop .last %},{% endif %}
2627{% endfor %}
@@ -228,29 +229,17 @@ open class Client {
228229 headers: [String: String] = [:],
229230 params: [String: Any?] = [:],
230231 sink: ((ByteBuffer) -> Void)? = nil,
231- convert: (([String: Any]) -> T)? = nil,
232- completion: ((Result<T , {{ spec .title | caseUcfirst }}Error >) -> Void)? = nil
233- ) {
232+ convert: (([String: Any]) -> T)? = nil
233+ ) async throws -> T {
234234 let validParams = params.filter { $0.value != nil }
235235
236236 let queryParameters = method == "GET" && !validParams.isEmpty
237237 ? "?" + parametersToQueryString(params: validParams)
238238 : ""
239239
240- let targetURL = URL(string: endPoint + path + queryParameters)!
240+ var request = HTTPClientRequest(url: endPoint + path + queryParameters)
241+ request.method = .RAW(value: method)
241242
242- var request: HTTPClient.Request
243- do {
244- request = try HTTPClient.Request(
245- url: targetURL,
246- method: .RAW(value: method)
247- )
248- } catch {
249- completion?(Result.failure({{ spec .title | caseUcfirst }}Error(
250- message: error.localizedDescription
251- )))
252- return
253- }
254243
255244 for (key, value) in self.headers.merging(headers, uniquingKeysWith: { $1 }) {
256245 request.headers.add(name: key, value: value)
@@ -259,24 +248,16 @@ open class Client {
259248 request.addDomainCookies()
260249
261250 if "GET" == method {
262- execute(request, convert: convert, completion: completion)
263- return
251+ return try await execute(request, convert: convert)
264252 }
265253
266- do {
267- try buildBody(for: & request, with: validParams)
268- } catch let error {
269- completion?(Result.failure({{ spec .title | caseUcfirst }}Error(
270- message: error.localizedDescription
271- )))
272- return
273- }
254+ try buildBody(for: & request, with: validParams)
274255
275- execute(request, withSink: sink, convert: convert, completion: completion )
256+ return try await execute(request, withSink: sink, convert: convert)
276257 }
277258
278259 private func buildBody(
279- for request: inout HTTPClient.Request ,
260+ for request: inout HTTPClientRequest ,
280261 with params: [String: Any?]
281262 ) throws {
282263 if request.headers["content-type"][0] == "multipart/form-data" {
@@ -287,96 +268,62 @@ open class Client {
287268 }
288269
289270 private func execute<T >(
290- _ request: HTTPClient.Request ,
271+ _ request: HTTPClientRequest ,
291272 withSink bufferSink: ((ByteBuffer) -> Void)? = nil,
292- convert: (([String: Any]) -> T)? = nil,
293- completion: ((Result<T , {{ spec .title | caseUcfirst }}Error >) -> Void)? = nil
294- ) {
295- if bufferSink == nil {
296- http.execute(
297- request: request,
298- delegate: ResponseAccumulator(request: request)
299- ).futureResult.whenComplete( { result in
300- complete(with: result)
301- })
302- return
303- }
304-
305- http.execute(
306- request: request,
307- delegate: StreamingDelegate(request: request, sink: bufferSink)
308- ).futureResult.whenComplete { result in
309- complete(with: result)
310- }
311-
312- func complete(with result: Result<HTTPClient .Response , Swift .Error >) {
313- guard let completion = completion else {
314- return
315- }
316-
317- switch result {
318- case .failure(let error):
319- completion(.failure({{ spec .title | caseUcfirst }}Error(
320- message: error.localizedDescription
321- )))
322- case .success(var response):
323- switch response.status.code {
324- case 0..<400:
325- if response .cookies .count > 0 {
326- UserDefaults.standard.set(
327- try! response.cookies.toJson(),
328- forKey: "\(response.host)-cookies"
329- )
330- }
331- switch T.self {
332- case is Bool.Type:
333- completion(.success(true as! T))
334- case is ByteBuffer.Type:
335- completion(.success(response.body! as! T))
336- default:
337- if response.body == nil {
338- completion(.success(true as! T))
339- return
340- }
341- let dict = try! JSONSerialization
342- .jsonObject(with: response.body!) as? [String: Any]
343-
344- completion(.success(convert?(dict!) ?? dict! as! T))
345- }
346- default:
347- var message = ""
348- var type = ""
349-
350- if response.body == nil {
351- completion(.failure({{ spec .title | caseUcfirst }}Error(
352- message: "Unknown error with status code \(response.status.code)",
353- code: Int(response.status.code)
354- )))
355- return
356- }
357-
358- do {
359- let dict = try JSONSerialization
360- .jsonObject(with: response.body!) as? [String: Any]
361-
362- message = dict?["message"] as? String
363- ?? response.status.reasonPhrase
364-
365- type = dict?["type"] as? String ?? ""
366- } catch {
367- message = response.body!.readString(length: response.body!.readableBytes)!
368- }
369-
370- let error = {{ spec .title | caseUcfirst }}Error(
371- message: message,
372- code: Int(response.status.code),
373- type: type
273+ convert: (([String: Any]) -> T)? = nil
274+ ) async throws -> T {
275+ func complete(with response: HTTPClientResponse) async throws -> T {
276+ switch response.status.code {
277+ case 0..<400:
278+ if response .headers [" Set-Cookie" ].count > 0 {
279+ UserDefaults.standard.set(
280+ response.headers["Set-Cookie"],
281+ forKey: URL(string: request.url)!.host! + "-cookies"
374282 )
283+ }
284+ switch T.self {
285+ case is Bool.Type:
286+ return true as! T
287+ case is ByteBuffer.Type:
288+ return response.body as! T
289+ default:
290+ let data = try await response.body.collect(upTo: Int.max)
291+ let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]
375292
376- completion(.failure(error))
293+ return convert?(dict!) ?? dict! as! T
377294 }
295+ default:
296+ var message = ""
297+ var data = try await response.body.collect(upTo: Int.max)
298+
299+ do {
300+ let dict = try JSONSerialization.jsonObject(with: data) as? [String: Any]
301+
302+ message = dict?["message"] as? String ?? response.status.reasonPhrase
303+ } catch {
304+ message = data.readString(length: data.readableBytes)!
305+ }
306+
307+ throw {{ spec .title | caseUcfirst }}Error(
308+ message: message,
309+ code: Int(response.status.code)
310+ )
378311 }
379312 }
313+
314+ if bufferSink == nil {
315+ let response = try await http.execute(
316+ request,
317+ timeout: .seconds(30)
318+ )
319+ return try await complete(with: response)
320+ }
321+
322+ let response = try await http.execute(
323+ request,
324+ timeout: .seconds(30)
325+ )
326+ return try await complete(with: response)
380327 }
381328
382329 func chunkedUpload<T >(
@@ -385,60 +332,43 @@ open class Client {
385332 params: inout [String: Any?],
386333 paramName: String,
387334 convert: (([String: Any]) -> T)? = nil,
388- onProgress: ((UploadProgress) -> Void)? = nil,
389- completion: ((Result<T , {{ spec .title | caseUcfirst }}Error >) -> Void)? = nil
390- ) {
335+ onProgress: ((UploadProgress) -> Void)? = nil
336+ ) async throws -> T {
391337 let file = params[paramName] as! File
392338 let size = file.buffer.readableBytes
393339
394340 if size < Client.chunkSize {
395- call(
341+ return try await call(
396342 method: "POST",
397343 path: path,
398344 headers: headers,
399345 params: params,
400- convert: convert,
401- completion: completion
346+ convert: convert
402347 )
403- return
404348 }
405349
406350 var input = file.buffer
407351 var offset = 0
408352 var result = [String:Any]()
409- let group = DispatchGroup()
410353
411354 while offset < size {
412355 let slice = input.readSlice(length: Client.chunkSize)
413356 ?? input.readSlice(length: Int(size - offset))
414-
357+
415358 params[paramName] = File(
416359 name: file.name,
417360 buffer: slice!
418361 )
419-
420- headers["content-range"] = "bytes \(offset)-\(min((offset + Client.chunkSize) - 1, size))/\(size)"
421362
422- group.enter()
363+ headers["content-range"] = "bytes \(offset)-\(min((offset + Client.chunkSize) - 1, size))/\(size)"
423364
424- call(
365+ result = try await call(
425366 method: "POST",
426367 path: path,
427368 headers: headers,
428369 params: params,
429370 convert: { return $0 }
430- ) { response in
431- switch response {
432- case let .success(map):
433- result = map
434- group.leave()
435- case let .failure(error):
436- completion?(.failure(error))
437- return
438- }
439- }
440-
441- group.wait()
371+ )
442372
443373 offset += Client.chunkSize
444374 headers["x-{{ spec .title | caseLower }}-id"] = result["$id"] as? String
@@ -451,10 +381,9 @@ open class Client {
451381 ))
452382 }
453383
454- completion?(.success( convert!(result)) )
384+ return convert!(result)
455385 }
456386
457-
458387 private static func randomBoundary() -> String {
459388 var string = ""
460389 for _ in 0..<16 {
@@ -464,16 +393,16 @@ open class Client {
464393 }
465394
466395 private func buildJSON (
467- _ request: inout HTTPClient . Request ,
396+ _ request: inout HTTPClientRequest ,
468397 with params: [String: Any ?] = [:]
469398 ) throws {
470399 let json = try JSONSerialization .data (withJSONObject: params , options: [])
471400
472- request .body = .data (json )
401+ request .body = .bytes (json )
473402 }
474403
475404 private func buildMultipart (
476- _ request: inout HTTPClient . Request ,
405+ _ request: inout HTTPClientRequest ,
477406 with params: [String: Any ?] = [:],
478407 chunked: Bool = false
479408 ) {
@@ -528,7 +457,7 @@ open class Client {
528457 request .headers .add (name: " Content-Length" , value: bodyBuffer .readableBytes .description )
529458 }
530459 request .headers .add (name: " Content-Type" , value: " multipart/form-data;boundary=\" \(Client .boundary )\" " )
531- request .body = .byteBuffer (bodyBuffer )
460+ request .body = .bytes (bodyBuffer )
532461 }
533462
534463 private func addUserAgentHeader () {
0 commit comments