Sources/OSS/Internal/ResponseHandler.swift (88 lines of code) (raw):

import Foundation protocol ResponseHandler { func onResponse(request: RequestMessage, response: ResponseMessage) throws } protocol ResponseHandlerAsync: ResponseHandler { func onResponseAsync(request: RequestMessage, response: ResponseMessage) async throws } extension ResponseHandlerAsync { func onResponse(request _: RequestMessage, response _: ResponseMessage) throws {} } extension AttributeKeys { static let responseHandler = AttributeKey<ResponseHandler>(name: "response-handler") } struct ServerResponseHandler: ResponseHandler { func onResponse(request: RequestMessage, response: ResponseMessage) throws { if response.statusCode / 100 == 2 { return } var errorFields: [String: String] = [:] var body: Data? body = try? response.content?.readData() // read from x-oss-error if body == nil || body!.count == 0 { if let str = response.headers[caseInsensitive: "x-oss-error"] { let base64EncodedData = str.data(using: .utf8)! body = Data(base64Encoded: base64EncodedData) } } /// try to parse error message if let bodyData = body, bodyData.count > 0 { do { let dict = try Dictionary<String, Any>.withXMLData(data: bodyData) if let error = dict["Error"], let fields = error as? [String: String] { for (key, value) in fields { errorFields[key] = value } } else { let bodyStr = String(data: bodyData, encoding: .utf8) ?? "" errorFields["Message"] = "Not found tag <Error>, part response body \(bodyStr.prefix(256))" } } catch { let bodyStr = String(data: bodyData, encoding: .utf8) ?? "" errorFields["Message"] = "Failed to parse xml from response body, part response body \(bodyStr.prefix(256))" } } throw ServerError( statusCode: response.statusCode, headers: response.headers, errorFields: errorFields, requestTarget: "\(request.method) \(request.requestUri.absoluteString)", snapshot: body ) } } struct ChekerUploadCrcResponseHandler: ResponseHandler { private let crc: UInt64? init(crc: UInt64? = nil) { self.crc = crc } func onResponse(request: RequestMessage, response: ResponseMessage) throws { if response.statusCode / 100 != 2 { return } if let scrc = response.headers[caseInsensitive: "x-oss-hash-crc64ecma"]?.toUInt64(), let ccrc = request.content?.hashCrc64ecma(crc: crc ?? 0) { if scrc != ccrc { throw ClientError.inconsistentError(clientCrc: ccrc, serverCrc: scrc) } } } } struct ChekerDownloadCrcResponseHandler: ResponseHandler { func onResponse(request _: RequestMessage, response: ResponseMessage) throws { guard response.statusCode / 100 == 2, response.statusCode != 206 else { return } if let scrc = response.headers[caseInsensitive: "x-oss-hash-crc64ecma"]?.toUInt64(), let ccrc = response.content?.hashCrc64ecma() { if scrc != ccrc { throw ClientError.inconsistentError(clientCrc: ccrc, serverCrc: scrc) } } } }