最近在写电商的功能,后台是 PHP 语言开发的。基于 Moya 强大的功能,不等 UI 做出图来我先把接口定义好,到时候直接调用,没想到事情没有想像的那么顺利。。。。
第一个接口是登录,文档是这样的
域名:https://www.xxxx.com
Path: /index.php?store_id=2&r=api/sso/login
Method: POST
Header
参数名称 | 参数值 | 是否必须 |
---|---|---|
Content-Type | application/x-www-form-urlencoded | 是 |
body
参数名称 | 参数类型 | 是否必须 |
---|---|---|
username | text | 是 |
nickname | text | 是 |
avatar_url | text | 是 |
很简单嘛,一通操作就写好了
enum YKStoreApi {
case login(username: String, nickname: String, avatar_url: String)
}
extension YKStoreApi: TargetType {
var baseURL: URL {
return URL(string: "https://www.xxxx.com")!
}
var path: String {
switch self {
case .login(_, _, _):
return "/index.php?store_id=2&r=api/sso/login"
}
}
var task: Task {
switch self {
case .login(let username, let nickname, let avatar_url):
return .requestParameters(parameters: ["username": username, "nickname": nickname, "avatar_url": avatar_url], encoding: URLEncoding.httpBody)
}
}
。。。。。。 无关紧要的就不贴了 。。。。。。
}
看着没啥毛病,来吧,没病走两步。请求结果是这样的
Response: <NSHTTPURLResponse: 0x600003c22480> { URL: https://www.xxxx.com/index.php%3Fstore_id=2&r=api/sso/login } { Status Code: 404, Headers
打印出的链接与想像中的好像不太一样,看看 Moya 源码是怎么拼接的吧
public extension URL {
/// Initialize URL from Moya's `TargetType`.
init<T: TargetType>(target: T) {
// When a TargetType's path is empty, URL.appendingPathComponent may introduce trailing /, which may not be wanted in some cases
// See: https://github.com/Moya/Moya/pull/1053
// And: https://github.com/Moya/Moya/issues/1049
if target.path.isEmpty {
self = target.baseURL
} else {
self = target.baseURL.appendingPathComponent(target.path)
}
}
}
这可怎么办,难道要修改源码吗?稍安勿躁,我大 Moya 如此牛逼应该不会有这么 low 的问题吧
分析一下这个链接发现,它是同时拥有编码参数( body 里面的)和 url 参数(Path 中问号后面的部分)。查看 Moya 中 Task 类型发现有这样一个类型的任务,看注释的意思应该正是我需要的
/// A requests body set with encoded parameters combined with url parameters.
case requestCompositeParameters(bodyParameters: [String: Any], bodyEncoding: ParameterEncoding, urlParameters: [String: Any])
大胆假设,小心验证。就按照这个思路修改一下原来的代码
enum YKStoreApi {
case login(username: String, nickname: String, avatar_url: String)
}
extension YKStoreApi: TargetType {
var baseURL: URL {
return URL(string: "https://www.xxxx.com")!
}
var path: String {
switch self {
case .login(_, _, _):
return "/index.php"
}
}
var task: Task {
switch self {
case .login(let username, let nickname, let avatar_url):
return .requestCompositeParameters(bodyParameters: ["username": username, "nickname": nickname, "avatar_url": avatar_url], bodyEncoding: URLEncoding.httpBody, urlParameters: ["store_id": "2", "r": "api/sso/login"])
}
}
。。。。。。 无关紧要的就不贴了 。。。。。。
}
改成这样之后重新请求一次,OK 成功了!
Response: <NSHTTPURLResponse: 0x600003c22480> { URL: https://www.xxxx.com/index.php?store_id=2&r=api/sso/login } { Status Code: 200, Headers
总结
- 平时 Moya 使用最多的 Task 类型是 requestParameters(parameters: [String: Any], encoding: ParameterEncoding),甚至不知道另外那个是干什么用的,但是人家的注释写的是一清二楚的。
2.读开源项目的源码,要读精读通,不能似懂非懂。好的开源项目是最好的学习资料。