杨锴
2025-03-11 90dc3329d1973fda691e357cf4523d5c7c67fa1d
Pods/Alamofire/Source/Features/Validation.swift
@@ -30,7 +30,7 @@
    fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason
    /// Used to represent whether a validation succeeded or failed.
    public typealias ValidationResult = Result<Void, Error>
    public typealias ValidationResult = Result<Void, any(Error & Sendable)>
    fileprivate struct MIMEType {
        let type: String
@@ -57,9 +57,9 @@
        func matches(_ mime: MIMEType) -> Bool {
            switch (type, subtype) {
            case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"):
                return true
                true
            default:
                return false
                false
            }
        }
    }
@@ -94,10 +94,10 @@
    fileprivate func validate<S: Sequence>(contentType acceptableContentTypes: S,
                                           response: HTTPURLResponse,
                                           data: Data?)
                                           isEmpty: Bool)
        -> ValidationResult
        where S.Iterator.Element == String {
        guard let data, !data.isEmpty else { return .success(()) }
        guard !isEmpty else { return .success(()) }
        return validate(contentType: acceptableContentTypes, response: response)
    }
@@ -146,7 +146,7 @@
extension DataRequest {
    /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the
    /// request was valid.
    public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
    public typealias Validation = @Sendable (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
    /// Validates that the response has a status code in the specified sequence.
    ///
@@ -155,8 +155,9 @@
    /// - Parameter acceptableStatusCodes: `Sequence` of acceptable response status codes.
    ///
    /// - Returns:                         The instance.
    @preconcurrency
    @discardableResult
    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int, S: Sendable {
        validate { [unowned self] _, response, _ in
            self.validate(statusCode: acceptableStatusCodes, response: response)
        }
@@ -169,10 +170,11 @@
    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
    ///
    /// - returns: The request.
    @preconcurrency
    @discardableResult
    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @Sendable @autoclosure () -> S) -> Self where S.Iterator.Element == String, S: Sendable {
        validate { [unowned self] _, response, data in
            self.validate(contentType: acceptableContentTypes(), response: response, data: data)
            self.validate(contentType: acceptableContentTypes(), response: response, isEmpty: (data == nil || data?.isEmpty == true))
        }
    }
@@ -184,7 +186,7 @@
    /// - returns: The request.
    @discardableResult
    public func validate() -> Self {
        let contentTypes: () -> [String] = { [unowned self] in
        let contentTypes: @Sendable () -> [String] = { [unowned self] in
            acceptableContentTypes
        }
        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
@@ -194,7 +196,7 @@
extension DataStreamRequest {
    /// A closure used to validate a request that takes a `URLRequest` and `HTTPURLResponse` and returns whether the
    /// request was valid.
    public typealias Validation = (_ request: URLRequest?, _ response: HTTPURLResponse) -> ValidationResult
    public typealias Validation = @Sendable (_ request: URLRequest?, _ response: HTTPURLResponse) -> ValidationResult
    /// Validates that the response has a status code in the specified sequence.
    ///
@@ -203,8 +205,9 @@
    /// - Parameter acceptableStatusCodes: `Sequence` of acceptable response status codes.
    ///
    /// - Returns:                         The instance.
    @preconcurrency
    @discardableResult
    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int, S: Sendable {
        validate { [unowned self] _, response in
            self.validate(statusCode: acceptableStatusCodes, response: response)
        }
@@ -217,8 +220,9 @@
    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
    ///
    /// - returns: The request.
    @preconcurrency
    @discardableResult
    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @Sendable @autoclosure () -> S) -> Self where S.Iterator.Element == String, S: Sendable {
        validate { [unowned self] _, response in
            self.validate(contentType: acceptableContentTypes(), response: response)
        }
@@ -232,7 +236,7 @@
    /// - Returns: The instance.
    @discardableResult
    public func validate() -> Self {
        let contentTypes: () -> [String] = { [unowned self] in
        let contentTypes: @Sendable () -> [String] = { [unowned self] in
            acceptableContentTypes
        }
        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())
@@ -244,9 +248,9 @@
extension DownloadRequest {
    /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a
    /// destination URL, and returns whether the request was valid.
    public typealias Validation = (_ request: URLRequest?,
                                   _ response: HTTPURLResponse,
                                   _ fileURL: URL?)
    public typealias Validation = @Sendable (_ request: URLRequest?,
                                             _ response: HTTPURLResponse,
                                             _ fileURL: URL?)
        -> ValidationResult
    /// Validates that the response has a status code in the specified sequence.
@@ -256,32 +260,34 @@
    /// - Parameter acceptableStatusCodes: `Sequence` of acceptable response status codes.
    ///
    /// - Returns:                         The instance.
    @preconcurrency
    @discardableResult
    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int, S: Sendable {
        validate { [unowned self] _, response, _ in
            self.validate(statusCode: acceptableStatusCodes, response: response)
        }
    }
    /// Validates that the response has a content type in the specified sequence.
    /// Validates that the response has a `Content-Type` in the specified sequence.
    ///
    /// If validation fails, subsequent calls to response handlers will have an associated error.
    ///
    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
    ///
    /// - returns: The request.
    @preconcurrency
    @discardableResult
    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @autoclosure () -> S) -> Self where S.Iterator.Element == String {
    public func validate<S: Sequence>(contentType acceptableContentTypes: @escaping @Sendable @autoclosure () -> S) -> Self where S.Iterator.Element == String, S: Sendable {
        validate { [unowned self] _, response, fileURL in
            guard let validFileURL = fileURL else {
            guard let fileURL else {
                return .failure(AFError.responseValidationFailed(reason: .dataFileNil))
            }
            do {
                let data = try Data(contentsOf: validFileURL)
                return self.validate(contentType: acceptableContentTypes(), response: response, data: data)
                let isEmpty = try (fileURL.resourceValues(forKeys: [.fileSizeKey]).fileSize ?? 0) == 0
                return self.validate(contentType: acceptableContentTypes(), response: response, isEmpty: isEmpty)
            } catch {
                return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL)))
                return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: fileURL)))
            }
        }
    }
@@ -294,7 +300,7 @@
    /// - returns: The request.
    @discardableResult
    public func validate() -> Self {
        let contentTypes = { [unowned self] in
        let contentTypes: @Sendable () -> [String] = { [unowned self] in
            acceptableContentTypes
        }
        return validate(statusCode: acceptableStatusCodes).validate(contentType: contentTypes())