如何始终使用 Moya/Alamofire 在 HTTP 请求中发送默认参数?

How to always send default parameters in HTTP request using Moya/Alamofire?

我的服务器端总是需要客户端发送令牌。作为开发人员,我可以忘记它。现在,我想提出一些解决方案,迫使我不要忘记发送这样一个必需的参数(它们可以在未来增长,例如,服务器可以需要设备的语言)。解决方案似乎很简单:我应该有一些 ServerManager 获取参数(例如,["user": "John"])和 URL 路径。并且它还应该附加必需的参数,例如 ["token": "abscsdcds"]。伪代码如下所示:

struct ServerManager {
     func request(params: [String: Any], path: String, completion: (ResponseModel) -> Void) {
          /// appending required default params 
          var paramsToSend = params
          paramsToSend["token"] = Token.token 

          /// making request here               

     }
}

每当我进行网络调用时,我都可以毫无疑问地使用 ServerManager 发送所有必需的参数和 return 响应。

但事情变得复杂,因为我使用 Moya 进行联网。它由 enumerations 制作,应该实现 TargetType 协议。我可以有几十个 enums,比如 RateAPIMovieAPI 等等......这意味着我的 ServerManager 应该接受 TargetType 和使用 [=24 的 HTTP 请求=].这是:

 func request<T>(type: TargetType, completion: (ResponseModel<T>) -> Void) {
              /// appending required default params 
              moyaProvider.request(MultiTarget(type)) {  response in 
                     /// parse it 
              }              



         }

我可以简单地使用上面的函数传递 TargetType,它 return 是我的回应。我可以使用上面的函数如下:

ServerManager.shared.request(target: MovieApi.list(params)) { (response) in

}

但是params上面的变量应该总是包含token。这意味着每当我发出网络请求时,我都应该写 params["token"] = "myToken" 。是代码重复。我想创建一些包含我所需参数的基础 RequestModel。然后我可以拥有 RequestModel 的不同子 classes,将其字段附加到所需的参数。但是这个解决方案很容易被误导(例如,subclass 可以发送自己的参数而忘记父 class 参数)。

看来是我设计的问题。是否有解决上述问题的设计模式?或者我们是否在 Moya/Alamofire 中内置了默认发送一些参数给每个请求的解决方案?

通常服务器 api 从 TTPHeaderFields 获取令牌,使用 Moya,您可以轻松地在一些 class 中更改您的 defaultEndpointMapping,例如 ApiGenerator 一些方法如:

static func request<T : Decodable, E: TargetType>(targetApi : E, responseModel : T.Type, success successCallBack: @escaping (Response<T>) -> Void, error errorCallBack: @escaping (Error) -> Void) -> Disposable {
    ...

    }

在这个方法中:

let endpointClosure = { (target: E ) -> Endpoint in
            let defaultEndpoint = MoyaProvider.defaultEndpointMapping(for: target)
            let cookie = String(format: "JSESSIONID=%@;SPRING_SECURITY_REMEMBER_ME_COOKIE=%@", AppSettings.shared.setting.sessionId, AppSettings.shared.setting.rememberMeCookie )


            return defaultEndpoint.adding(newHTTPHeaderFields:
                [
                    "X-Client": "ios",
                    "Cookie" : cookie
                ]
            )
        }

并将其添加到:

let provider = MoyaProvider<E>(endpointClosure: endpointClosure, plugins: [
            NetworkLoggerPlugin(configuration: .init(logOptions: .verbose))])

然后完成剩下的工作。但在你的情况下,我建议创建你的 ApiGenerator class 并在其中自定义你的 TargetApi.Task ,如下所示:

switch defaultEndpoint.task {
   case .requestParameters(parameters: /*Append new params here*/ , encoding: JSONEncoding.default):
       ...
    default:
       ...
 }