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

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

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

1
2
3
4
5
6
7
8
9
10
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 来发送所有必需的参数并返回响应。

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

1
2
3
4
5
6
7
8
9
 func request< T >(type: TargetType, completion: (ResponseModel< T >) -> Void) {
              /// appending required default params
              moyaProvider.request(MultiTarget(type)) {  response in
                     /// parse it
              }              



         }

我可以简单地使用上面传递 TargetType 的函数,它会返回一个响应。我可以使用上述功能如下:

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

}

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

这似乎是我的设计问题。有没有解决上述问题的设计模式?或者我们是否在 Moya/Alamofire 中内置了默认情况下向每个请求发送一些参数的解决方案?


通常服务器 api\\'s get token 从 TTPHeaderFields 和 Moya 你可以很容易地改变你的 defaultEndpointMapping 在像 ApiGenerator 这样的一些类的一些方法:

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

    }

在这个方法里面:

1
2
3
4
5
6
7
8
9
10
11
12
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
                ]
            )
        }

并将其添加到:

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

然后做剩下的。但在您的情况下,我建议创建您的 ApiGenerator 类并在其中自定义您的 TargetApi.Task,如下所示:

1
2
3
4
5
6
switch defaultEndpoint.task {
   case .requestParameters(parameters: /*Append new params here*/ , encoding: JSONEncoding.default):
       ...
    default:
       ...
 }