如何处理Alamofire请求返回200状态码但无响应体的情况
问题场景
使用Alamofire向S3服务器上传文件,上传完成后返回200状态码但无响应体,触发错误:Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength。尝试设置.request(emptyResponseCodes:[200, 204, 205])和自定义fetchWithEmptyResponse方法均未解决,需要通过@escaping completionHandler正确传递空响应的成功结果。
解决方案
1. 自定义兼容空响应的序列化器
默认JSON响应序列化器会拒绝空数据,我们需要自定义序列化器,允许200状态码下的空响应,同时保留正常JSON数据的解析能力:
import Alamofire class EmptyResponseCompatibleSerializer: ResponseSerializer { func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> Data? { // 优先处理错误 if let error = error { throw error } guard let response = response else { throw AFError.responseValidationFailed(reason: .missingResponse) } // 200状态码+空数据视为成功,返回nil作为空标识 if response.statusCode == 200 && (data == nil || data?.count == 0) { return nil } // 其他场景沿用默认JSON序列化逻辑 return try JSONResponseSerializer().serialize(request: request, response: response, data: data, error: error) } }
2. 调整请求调用逻辑
结合你的TargetType协议,修改请求发送代码,应用自定义序列化器,通过@escaping completionHandler传递结果:
func performRequest<T: TargetType>(target: T, completion: @escaping (Result<Void, Error>) -> Void) { AF.request(target) .validate(statusCode: 200..<300) .response(using: EmptyResponseCompatibleSerializer()) { response in switch response.result { case .success: // 200状态码无论是否有数据都判定为上传成功 completion(.success(())) case .failure(let error): completion(.failure(error)) } } }
3. 针对S3上传的补充优化
如果上传请求使用.imageDataWithoutPath参数类型,可在TargetType扩展中补充设置Accept头,明确告知服务器接受空响应:
extension TargetType { public func asURLRequest() throws -> URLRequest { // 保留原有代码逻辑... // 新增:图片上传场景设置Accept头 if case .imageDataWithoutPath(_) = parameters { urlRequest.setValue("*/*", forHTTPHeaderField: HTTPHeaderField.acceptType.rawValue) } return urlRequest } }
关于emptyResponseCodes失效的说明
Alamofire的emptyResponseCodes仅对默认DataResponseSerializer生效,若请求默认使用JSON序列化器,该配置不会起作用——因为JSON序列化器本身会校验数据非空。因此必须通过自定义序列化器来兼容200状态码下的空响应场景。
内容的提问来源于stack exchange,提问作者hosejose
相关产品推荐
相关产品推荐

