美文网首页
Alamofire源码分析(2)——DataRequest

Alamofire源码分析(2)——DataRequest

作者: 无悔zero | 来源:发表于2020-12-08 02:20 被阅读0次

    上次分析了SessionManager层,这次往下走分析request层。先看例子:

    SessionManager.default  //直接跳过Alamofire层调用也可以
    .request(url, method: .get, parameters: parameters)
    .response { (result) in
        print(result)
    }
    
    1. 直接找到源码位置,可以看到这一层返回DataRequest,这个不是请求的URLRequest,但请求的URLRequest在里面创建了:
    open class SessionManager {
        ...
        @discardableResult
        open func request(
            _ url: URLConvertible,
            method: HTTPMethod = .get,  /*默认为get方法*/
            parameters: Parameters? = nil,
            encoding: ParameterEncoding = URLEncoding.default,
            headers: HTTPHeaders? = nil)
            -> DataRequest
        {
            var originalRequest: URLRequest?
            //创建URLRequest
            do {
                originalRequest = try URLRequest(url: url, method: method, headers: headers)
                let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
                return request(encodedURLRequest)
            } catch {
                return request(originalRequest, failedWith: error)
            }
        }
        ...
    }
    
    1. 下一步则是encoding.encode(originalRequest!, with: parameters)对参数进行处理,还会判别请求方法分开处理:
    public struct URLEncoding: ParameterEncoding {
        ...
        public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
            var urlRequest = try urlRequest.asURLRequest()//跟asURL一个意思
    
            guard let parameters = parameters else { return urlRequest }
            //判别请求方法分开处理
            if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) {
                ...//get
            } else {
                ...//post
            }
    
            return urlRequest
        }
        ...
    }
    
    1. 先看对get请求的处理:
    public struct URLEncoding: ParameterEncoding {
        ...
        public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
            var urlRequest = try urlRequest.asURLRequest()
    
            guard let parameters = parameters else { return urlRequest }
            //判别请求方法分开处理
            if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) {
                guard let url = urlRequest.url else {
                    throw AFError.parameterEncodingFailed(reason: .missingURL)
                }
                //拼接url后面的参数
                if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
                    let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
                    urlComponents.percentEncodedQuery = percentEncodedQuery
                    urlRequest.url = urlComponents.url
                }
            } else {
                ...//post
            }
    
            return urlRequest
        }
        ...
    }
    

    从不显眼的query函数发现,对请求参数进行了排序和符号拼接:

    public struct URLEncoding: ParameterEncoding {
        ...
        private func query(_ parameters: [String: Any]) -> String {
            var components: [(String, String)] = []
            //排序
            for key in parameters.keys.sorted(by: <) {
                let value = parameters[key]!
                components += queryComponents(fromKey: key, value: value)
            }
            return components.map { "\($0)=\($1)" }.joined(separator: "&")//符号拼接
        }
        ...
    }
    
    • 这里便是对get请求参数的主要处理。
    1. 回到第2步,另一种处理方式便是对post请求的处理,先对请求头做了处理,后面同样用query进行参数排序和符号拼接:
    public struct URLEncoding: ParameterEncoding {
        ...
        public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
            var urlRequest = try urlRequest.asURLRequest()
    
            guard let parameters = parameters else { return urlRequest }
            //判别请求方法分开处理
            if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) {
                ...//get
            } else {
                //请求头
                if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
                    urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
                }
                //请求体
                urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false)
            }
    
            return urlRequest
        }
        ...
    }
    
    1. 之后便回到第1步,创建DataRequest返回,到这里DataRequest这一层就完成了。

    这一层先到这里,下一层分析task
    不过下一篇是:链式函数

    相关文章

      网友评论

          本文标题:Alamofire源码分析(2)——DataRequest

          本文链接:https://www.haomeiwen.com/subject/huxawktx.html