Alamofire 响应为零

Alamofire response is nil

我遇到了 Alamofire 请求和拦截器的问题。

我的服务器有两种类型的响应 -> 成功响应是一种对象,错误响应始终是错误消息。 我创建了一个示例代码来创建一个非常自己的函数来解码两种似乎运行良好的响应类型。

调用 Alamofire adapt 函数后出现问题(adapt 为每个请求添加一个 cookie)-> 在我的 .responseTwoDecodable 中,我总是得到 nil 响应,但状态代码为 200,一切正常,服务器returns 对象,但 alamofire 忽略了它。

这是我对每个请求的代码:

func request<T: Decodable>(
    _ url: String,
    method: HTTPMethod = .get,
    parameters: Parameters? = nil,
    decoder: JSONDecoder = JSONDecoder(),
    headers: HTTPHeaders? = nil,
    interceptor: RequestInterceptor? = nil
) -> Future<T, ServerError> {
    return Future({ promise in
        AF.request(
            url,
            method: method,
            parameters: parameters,
            encoding: JSONEncoding.default,
            headers: headers
            interceptor: interceptor ?? self
        )
        .validate(statusCode: [200, 201, 204, 401]
        .responseTwoDecodable(of: T.self) { response in
            switch response {
            case .success(let value):
                promise(.success(value))
            case .failure(let error):
                promise(.failure(error))
            }
        }
    })
}

这里是适配函数:

func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, ServerError>) -> Void) {

        let request = urlRequest
        if let accessToken = UserDefaults.standard.string(forKey: Constants.accessToken), let refreshToken = UserDefaults.standard.string(forKey: Constants.refreshToken) {
            let access = [
                HTTPCookiePropertyKey.domain: Constants.cookieDomain,
                HTTPCookiePropertyKey.path: Constants.cookieAccessPath,
                HTTPCookiePropertyKey.name: Constants.accessToken,
                HTTPCookiePropertyKey.value: accessToken
               ]
            let refresh = [
                HTTPCookiePropertyKey.domain: Constants.cookieDomain,
                HTTPCookiePropertyKey.path: Constants.cookieRefreshPath,
                HTTPCookiePropertyKey.name: Constants.refreshToken,
                HTTPCookiePropertyKey.value: refreshToken
               ]
            if let accessCookie = HTTPCookie(properties: access), let refreshCookie = HTTPCookie(properties: refresh) {
                AF.session.configuration.httpCookieStorage?.setCookie(accessCookie)
                AF.session.configuration.httpCookieStorage?.setCookie(refreshCookie)
                completion(.success(request))
            }
        }
        completion(.success(request))
    }

这是我的两个解码器的解码代码:

struct ErrorMessage: Error, Decodable {
    let message: String
}

struct ServerError: Error {
    var message: String
    var code: ServerErrorCodes
    let args: [String]?
}

enum ServerErrorCodes: Int {
    case unauthorized = 401
    case forbidden = 403
    case internalServerError = 500
    case notFound = 404
    case conflict = 409
    case unknown
    case emptyResponse
    case unserialized
    case userInput
    case coreData
}

final class TwoDecodableResponseSerializer<T: Decodable>: ResponseSerializer {

lazy var decoder: JSONDecoder = {
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .iso8601
    return decoder
}()

private lazy var successSerializer = DecodableResponseSerializer<T>(decoder: decoder)
private lazy var errorSerializer = DecodableResponseSerializer<ErrorMessage>(decoder: decoder)

    public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Result<T, ServerError> {

        guard error == nil else { return .failure(ServerError(message: "Unknown error", code: .unknown, args: [])) }

        guard let response = response else { return .failure(ServerError(message: "Empty response", code: .emptyResponse, args: [])) } // HERE I AM GETTING A NIL AS A RESPONSE, BUT SERVER RESPONDED WITH CORRECT BODY AND 200 AS STATUS CODE

        do {
            print(response.debugDescription)
            if response.statusCode < 200 || response.statusCode >= 300 {
                let serverMessage = try errorSerializer.serialize(request: request, response: response, data: data, error: nil)
                let responseCode: ServerErrorCodes
            
                if let code = ServerErrorCodes(rawValue: response.statusCode) {
                    responseCode = code
                } else {
                    responseCode = .unknown
                } 
       
                let result = ServerError(message: serverMessage.message, code: responseCode, args: nil)
                return .failure(result)
            } else {
                let result = try successSerializer.serialize(request: request, response: response, data: data, error: nil)
                return .success(result)
            } 
        } catch(let err) {
            return .failure(ServerError(message: "Could not serialize body", code: .unserialized, args: [String(data: data!, encoding: .utf8)!, err.localizedDescription]))
        }
    }
}

extension DataRequest {
    @discardableResult func responseTwoDecodable<T: Decodable>(queue: DispatchQueue = DispatchQueue.global(qos: .userInitiated), of t: T.Type, completionHandler: @escaping (Result<T, ServerError>) -> Void) -> Self {
        return response(queue: .main, responseSerializer: TwoDecodableResponseSerializer<T>()) { response in
            switch response.result {
            case .success(let result):
                completionHandler(result)
            case .failure(let error):
                completionHandler(.failure(ServerError(message: "Other error", code: .unknown, args: [error.localizedDescription])))
            }
        }
    }
}

我是 Alamofire 的新手,所以如果可以用更好的方式完成某些事情,我将感谢您的帮助或分享您的想法!有谁知道为什么会发生这种情况?谢谢!

已解决:我完全删除了实现 .responseTwoDecodable 的代码并编写了自己的解决方案:

func createError(response: HTTPURLResponse?, error: AFError, data: Data?) -> ServerError {
    guard let serverResponse = response else {
        return .init(message: "Unknown error", code: .unknown, args: [error.localizedDescription])
    }
    
    guard let serverData = data else {
        return .init(message: "Empty response", code: .emptyResponse, args: [error.localizedDescription])
    }
    
    let responseCode: ServerErrorCodes
    
    if let code = ServerErrorCodes(rawValue: serverResponse.statusCode) {
        responseCode = code
    } else {
        responseCode = .unknown
    }
    
    do {
        let serverMessage = try JSONDecoder().decode(ErrorMessage.self, from: serverData)
        
        return .init(message: serverMessage.message, code: responseCode, args: [])
        
    } catch (let error) {
        return .init(message: "Body not serializable", code: .unserialized, args: [String(data: serverData, encoding: .utf8) ?? "", error.localizedDescription])
    }
}

并这样称呼它:

.responseDecodable(completionHandler: { (response: DataResponse<T, AFError>) in
            switch response.result {
            case .success(let value):
                promise(.success(value))
            case .failure(let error):
                promise(.failure(self.createError(response: response.response, error: error, data: response.data)))
            }
        })

使用此代码,我能够按预期解码来自服务器的所有错误。