Skip to content

Commit e9daefa

Browse files
committed
feat(swift5): implement background upload
1 parent c58ac47 commit e9daefa

File tree

5 files changed

+68
-6
lines changed

5 files changed

+68
-6
lines changed

config/swift5-uploader.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ additionalProperties:
4646
podHomepage: https://docs.api.video
4747
podSocialMediaUrl: https://twitter.com/api_video
4848
podLicense: "{ :type => 'MIT' }"
49+
backgroundSupport: true
4950
defaultChunkSize: 50 * 1024 * 1024
5051
minChunkSize: 5 * 1024 * 1024
5152
maxChunkSize: 128 * 1024 * 1024

config/swift5.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ additionalProperties:
5151
podHomepage: https://docs.api.video
5252
podSocialMediaUrl: https://twitter.com/api_video
5353
podLicense: "{ :type => 'MIT' }"
54+
backgroundSupport: true
5455
defaultChunkSize: 50 * 1024 * 1024
5556
minChunkSize: 5 * 1024 * 1024
5657
maxChunkSize: 128 * 1024 * 1024

templates/swift5/APIs.mustache

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ public class {{projectName}} {
2828
internal static var requestBuilderFactory: RequestBuilderFactory = AlamofireRequestBuilderFactory(){{/useAlamofire}}{{#useURLSession}}
2929
internal static var requestBuilderFactory: RequestBuilderFactory = URLSessionRequestBuilderFactory(){{/useURLSession}}
3030
public static var apiResponseQueue: DispatchQueue = .main
31-
{{/useVapor}}
32-
public static var timeout: TimeInterval = 60
31+
{{/useVapor}}{{#backgroundSupport}}
32+
public static var backgroundIdentifier: String = "video.api.upload.background"
33+
{{/backgroundSupport}}public static var timeout: TimeInterval = 60
3334
internal static var customHeaders:[String: String] {
3435
var headers = defaultHeaders
3536
if let apiKey = apiKey {
@@ -150,5 +151,6 @@ public class {{projectName}} {
150151

151152
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} protocol RequestBuilderFactory {
152153
func getNonDecodableBuilder<T>() -> RequestBuilder<T>.Type
153-
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type
154-
}{{/useVapor}}
154+
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type{{#backgroundSupport}}
155+
func getBackgroundBuilder<T: Decodable>() -> RequestBuilder<T>.Type
156+
{{/backgroundSupport}}}{{/useVapor}}

templates/swift5/api.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ extension {{projectName}}API {
543543

544544
let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders)
545545

546-
let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}}
546+
let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}.requestBuilderFactory.{{#vendorExtensions.x-client-chunk-upload}}getBackgroundBuilder(){{/vendorExtensions.x-client-chunk-upload}}{{^vendorExtensions.x-client-chunk-upload}}{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}}{{/vendorExtensions.x-client-chunk-upload}}
547547

548548
return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters{{#vendorExtensions.x-client-chunk-upload}}, onProgressReady: onProgressReady{{/vendorExtensions.x-client-chunk-upload}})
549549
}
@@ -620,7 +620,7 @@ extension {{projectName}}API {
620620

621621
let localVariableHeaderParameters = APIHelper.rejectNilHeaders(localVariableNillableHeaders)
622622

623-
let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}.requestBuilderFactory.{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}}
623+
let localVariableRequestBuilder: RequestBuilder<{{{returnType}}}{{^returnType}}Void{{/returnType}}>.Type = {{projectName}}.requestBuilderFactory.{{#backgroundSupport}}{{#vendorExtensions.x-client-chunk-upload}}getBackgroundBuilder(){{/vendorExtensions.x-client-chunk-upload}}{{^vendorExtensions.x-client-chunk-upload}}{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}}{{/vendorExtensions.x-client-chunk-upload}}{{/backgroundSupport}}{{^backgroundSupport}}{{#returnType}}getBuilder(){{/returnType}}{{^returnType}}getNonDecodableBuilder(){{/returnType}}{{/backgroundSupport}}
624624

625625
return localVariableRequestBuilder.init(method: "{{httpMethod}}", URLString: (localVariableUrlComponents?.string ?? localVariableURLString), parameters: localVariableParameters, headers: localVariableHeaderParameters, onProgressReady: onProgressReady)
626626
}

templates/swift5/libraries/urlsession/URLSessionImplementations.mustache

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ class URLSessionRequestBuilderFactory: RequestBuilderFactory {
2222

2323
func getBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
2424
return URLSessionDecodableRequestBuilder<T>.self
25+
}{{#backgroundSupport}}
26+
27+
func getBackgroundBuilder<T: Decodable>() -> RequestBuilder<T>.Type {
28+
return URLSessionDecodableBackgroundUploadRequestBuilder<T>.self
2529
}
30+
{{/backgroundSupport}}
2631
}
2732

2833
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} typealias {{projectName}}ChallengeHandler = ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))
@@ -376,8 +381,61 @@ private var credentialStore = SynchronizedDictionary<Int, URLCredential>()
376381
}
377382
}
378383
}
384+
}{{#backgroundSupport}}
385+
386+
private class BackgroundUploadTaskURLSession<T>: NSObject, URLSessionProtocol, URLSessionDelegate, URLSessionDataDelegate {
387+
private let file: URL
388+
private lazy var urlSession: URLSession = {
389+
URLSession(configuration: .background(withIdentifier: ApiVideoClient.backgroundIdentifier), delegate: self, delegateQueue: nil)
390+
}()
391+
private var completion: ((Data?, URLResponse?, Error?) -> Void)? = nil
392+
393+
init(_ file: URL) {
394+
self.file = file
395+
}
396+
397+
func dataTask(with request: URLRequest, completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
398+
completion = completionHandler
399+
return urlSession.uploadTask(with: request, fromFile: file)
400+
}
401+
402+
func urlSession(_ session: URLSession, task: URLSessionTask, didBecomeInvalidWithError error: Error?) {
403+
guard let error = error else {
404+
return
405+
}
406+
completion?(nil, task.response, error)
407+
}
408+
409+
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
410+
completion?(data, dataTask.response, nil)
411+
}
412+
413+
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
414+
sessionDelegate.urlSession(session, task: task, didReceive: challenge, completionHandler: completionHandler)
415+
}
379416
}
380417

418+
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class URLSessionDecodableBackgroundUploadRequestBuilder<T: Decodable>: URLSessionDecodableRequestBuilder<T> {
419+
private var completion: ((Result<Response<T>, ErrorResponse>) -> Void)? = nil
420+
421+
override open func createURLSession() -> URLSessionProtocol {
422+
guard let parameters = parameters else { fatalError("No parameters found") }
423+
424+
// Find file URL
425+
var file: URL? = nil
426+
for (_, value) in parameters {
427+
if let fileURL = value as? URL {
428+
file = fileURL
429+
break
430+
}
431+
}
432+
guard let fileURL = file else {
433+
fatalError("No file URL found")
434+
}
435+
return BackgroundUploadTaskURLSession<T>(fileURL)
436+
}
437+
}{{/backgroundSupport}}
438+
381439
private class SessionDelegate: NSObject, URLSessionTaskDelegate {
382440
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
383441

0 commit comments

Comments
 (0)