返回

从类层次剖析RequestInterceptor的设计与实现

IOS

上篇,我们梳理了Alamofire的工作流程。今天我们继续研究,这次主要梳理RequestInterceptor(拦截器)的相关内容。

public protocol RequestInterceptor {
    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
}

public protocol RequestAdapter: RequestInterceptor {
    func adapt(_ urlRequest: URLRequest) -> URLRequest
}

public protocol RequestRetrier: RequestInterceptor {
    func retry(_ request: Request, for session: Session, dueTo error: Error) -> Bool
}

public protocol RedirectHandler: RequestInterceptor {
    func urlRequest(_ urlRequest: URLRequest, for session: Session, redirectResponse: HTTPURLResponse, completion: @escaping (Result<URLRequest, Error>) -> Void)
}

public protocol EventMonitor: RequestInterceptor {
    func request<Value>(_ request: Request, didParseResponse response: HTTPURLResponse, data: Data?, error: Error?)
}

public protocol ServerTrustManager: RequestInterceptor {
    func serverTrustManager(for session: Session) -> ServerTrustManaging?
}

public protocol SessionDelegate: RequestInterceptor {
    func sessionDidReceiveChallenge(_ session: Session, challenge: URLAuthenticationChallenge, completion: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
}

extension RequestInterceptor {
    public func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        completion(.success(urlRequest))
    }

    public func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
        completion(.doNotRetry)
    }

    public func urlRequest(_ urlRequest: URLRequest, for session: Session, redirectResponse: HTTPURLResponse, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        completion(.success(urlRequest))
    }

    public func request<Value>(_ request: Request, didParseResponse response: HTTPURLResponse, data: Data?, error: Error?) { }

    public func serverTrustManager(for session: Session) -> ServerTrustManaging? {
        return nil
    }

    public func sessionDidReceiveChallenge(_ session: Session, challenge: URLAuthenticationChallenge, completion: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { }
}

RequestInterceptor 类层次结构定义了各种类型的拦截器,它们都可以用来修改请求、响应和任务。

  • RequestAdapter:这个协议允许你修改请求。
  • RequestRetrier:这个协议允许你在请求失败后重试请求。
  • RedirectHandler:这个协议允许你处理重定向请求。
  • EventMonitor:这个协议允许你在请求和响应过程中接收事件。
  • ServerTrustManager:这个协议允许你指定服务器信任管理器。
  • SessionDelegate:这个协议允许你处理会话委托方法。

你可以使用 SessionConfigurationrequestInterceptors 属性来指定要使用的拦截器。例如,下面的代码创建了一个 SessionConfiguration 对象,并指定了一个 RequestAdapter 类型的拦截器。

let configuration = URLSessionConfiguration.default
configuration.requestInterceptors = [MyRequestAdapter()]

你也可以使用 RequestrequestInterceptors 属性来指定要使用的拦截器。例如,下面的代码创建一个 Request 对象,并指定了一个 RequestAdapter 类型的拦截器。

let request = Request(url: "https://example.com")
request.requestInterceptors = [MyRequestAdapter()]

拦截器可以用于各种各样的场景,例如:

  • 添加身份验证标头到请求。
  • 修改请求的查询参数。
  • 重试失败的请求。
  • 处理重定向请求。
  • 监听请求和响应事件。
  • 指定服务器信任管理器。
  • 处理会话委托方法。

RequestInterceptor 类层次结构提供了各种类型的拦截器,它们都可以用来修改请求、响应和任务。你可以使用 SessionConfigurationrequestInterceptors 属性或 RequestrequestInterceptors 属性来指定要使用的拦截器。拦截器可以用于各种各样的场景,例如添加身份验证标头到请求、修改请求的查询参数、重试失败的请求、处理重定向请求、监听请求和响应事件、指定服务器信任管理器和处理会话委托方法。