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



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

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请求。这是:

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

}

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

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

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

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

通常服务器api从TTPHeaderFields获取令牌,使用Moya,您可以很容易地在ApiGenerator等类中更改defaultEndpointMapping,方法如下:

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类,并在其中自定义TargetApi.Task,如下所示:

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

最新更新