tus / TUSKit

The tus client for iOS.
https://tus.io/
MIT License
214 stars 115 forks source link

about supportedExtensions property automatic acquisition #153

Closed MartinLau7 closed 1 year ago

MartinLau7 commented 1 year ago

I think that could be obtained by the OPTIONS request server Extensions attribute, refer to TUS-Protocol-OPTIONS

add usServerInfo.swift


public struct TusServerInfo {
    public private(set) var version: String?

    public private(set) var maxSize: Int?

    public private(set) var extensions: [TUSProtocolExtension]?

    public private(set) var supportedVersions: [String]

    public private(set) var supportedChecksumAlgorithms: [String]?

    public var supportsDelete: Bool {
        extensions?.contains(.termination) ?? false
    }

    init(version: String, maxSize: Int?, extensions: [TUSProtocolExtension]?, supportedVersions: [String], supportedChecksumAlgorithms: [String]?) {
        self.version = version
        self.maxSize = maxSize
        self.extensions = extensions
        self.supportedVersions = supportedVersions
        self.supportedChecksumAlgorithms = supportedChecksumAlgorithms
    }
}

In TUSProtocolExtension.swift

/// Available [TUS protocol extensions](https://tus.io/protocols/resumable-upload.html#protocol-extensions) that
/// the client supports.
public enum TUSProtocolExtension: String, CaseIterable {
    case creation = "creation"
    case creationWithUpload = "creation-with-upload"
    case termination = "termination"
    case concatenation = "concatenation"
    case creationDeferLength = "creation-defer-length"
    case checksum = "checksum"
    case checksumTrailer = "checksum-trailer"
    case expiration = "expiration"
}

add functon In TUSAPI.swift

@discardableResult
    func serverInfo(server: URL, completion: @escaping (Result<TusServerInfo, TUSAPIError>) -> Void) -> URLSessionDataTask {
        let request = makeRequest(url: server, method: .options, headers: [:])
        let task = session.dataTask(request: request) { result in
            processResult(completion: completion) {
                let (_, response) =  try result.get()

                guard response.statusCode == 200 || response.statusCode == 204 else {
                    throw TUSAPIError.couldNotFetchServerInfo
                }

                var supportedAlgorithms: [String] = []
                if let algorithms = response.allHeaderFields[caseInsensitive: "tus-checksum-algorithm"] as? String {
                    supportedAlgorithms = algorithms.components(separatedBy: ",")
                }
                var supportedVersions: [String] = []
                if let tusVersions = response.allHeaderFields[caseInsensitive: "tus-version"] as? String {
                    supportedVersions = tusVersions.components(separatedBy: ",")
                }
                var maxSize: Int?
                if let maxSizeStr = response.allHeaderFields[caseInsensitive: "tus-max-size"] as? String {
                    maxSize = Int(maxSizeStr)
                }
                let version = response.allHeaderFields[caseInsensitive: "tus-resumable"] as? String ?? ""

                var extensions: [TUSProtocolExtension] = []
                if let tusExtension = response.allHeaderFields[caseInsensitive: "tus-extension"] as? String {
                    extensions = tusExtension.components(separatedBy: ",").map { TUSProtocolExtension(rawValue: $0) ?? .creation }
                }

                return TusServerInfo(version: version, maxSize: maxSize, extensions: extensions, supportedVersions: supportedVersions, supportedChecksumAlgorithms: supportedAlgorithms)
            }
        }
        task.resume()
        return task
    }
Acconut commented 1 year ago

Thank you for this proposal and the attached code. I think this is a nice addition and users could definitively benefit from this. As far as I can tell, this feature is also completely optional, which is really important because there are many situations where you want to avoid an additional OPTIONS request if you already know your server's capabilities.

Would you mind opening a PR for this?

MartinLau7 commented 1 year ago

Yes, I'll try opening a PR when I get back from my vacation

donnywals commented 1 year ago

Thanks! This looks like a very good idea indeed. Looking forward to the PR 👍🏼

Acconut commented 1 year ago

Added in #154.