URLSession Combine 正确处理 307 重定向

问题描述

我目前正在使用 URLSession 和 Combine 开发 API。只要 T 符合可解码,我就有一个通用的 fetch 方法类型 T。 API 要么返回 200 并返回带有 Meeting 对象的会议结果,要么返回 307,后者返回没有 Meeting 的 redirectUrl。在映射 FindResult 以获取 findMeeting 中的 MeetingResult 之后,我想检查是否有一个 redirectUrl,如果有然后存储该 redirectUrl 并执行另一个 findMeeting,它应该返回一个 200 和一个 Meeting 对象,然后我可以通过接收器.

A 307,可能会也可能不会发生,很明显,redirectURL 被存储并重用于未来的请求。我想知道当我获得带有重定向 URL 的结果时,如何最好地重新运行提取请求。

final class PostLoader {
    func findMeeting(email: String,passcode: String) -> AnyPublisher<Meeting,APIError> {
        let request = Endpoint.findMeeting(email: email,passcode: passcode).request
        
        return fetch(request)
            .map { (findResult: FindResult) in
                findResult.meetingResult
            }
            .compactMap(\.meeting)
            .erasetoAnyPublisher()
    }
    
    private func fetch<T: Decodable>(_ request: URLRequest) -> AnyPublisher<T,APIError> {
        URLSession.shared.dataTaskPublisher(for: request)
            .retry(1)
            .tryMap { output in
                guard let httpResponse = output.response as? HTTPURLResponse else {
                    throw APIError.unkNown
                }
                
                switch httpResponse.statusCode {
                case 200...399:
                    return output.data
                case 400...499:
                    throw APIError.unauthorized(code: httpResponse.statusCode)
                case 500...599:
                    throw APIError.server(code: httpResponse.statusCode)
                default:
                    throw APIError.unkNown
                }
            }
            .decode(type: T.self,decoder: JSONDecoder())
            .mapError { error in
                if let error = error as? APIError {
                    return error
                } else if error is DecodingError {
                    return APIError.decoding(message: "\(error)")
                } else {
                    return APIError.unkNown
                }
            }
            .receive(on: dispatchQueue.main)
            .erasetoAnyPublisher()
    }
}

A 307 给出的响应为(200 相同的响应,但会议不是 nil 并且 redirectUrl 为 nil):

MeetingResult
  - txnid : "abc123"
  ▿ redirectUrl : Optional<URL>
    ▿ some : https://redirect-url.com
      - _url : https://redirect-url.com
  - meeting : nil

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)