如何将我的登录用户URLSession
代码转换为Siesta框架代码? 我目前的尝试不起作用。
我已经在 GithubBrowser 中查看了该示例,但我拥有的 API 不是那样工作的。
问题是用户结构被我正在使用的 API 中的端点的工作方式所分割。 端点http://server.com/api/key
。 是的,它真的被称为key
而不是user
或login
. 作者之所以这样称呼它,是因为您发布了一个用户/通行证对并取回了密钥。 所以它(通过 post)接受一个 json 结构,如下所示:
{"name": "bob", "password": "s3krit"}
并作为响应返回:
{"token":"AEWasBDasd...AAsdga"}
我有一个SessionUser
结构:
struct SessionUser: Codable
{
let name: String
let password: String
let token: String
}
。它封装了用户的状态(REST中的"S")。 问题是名称和密码被发布,令牌是响应。
当此状态发生变化时,我会执行我的操作:
service.invalidateConfiguration() // So requests get config change
service.wipeResources() // Scrub all unauthenticated data
实例存储在单一实例中,该实例由配置块拾取,以便将来自 API 的令牌放入所有其他 API 请求的标头中:
configure("**") {
// This block ^ is run AGAIN when the configuration is invalidated
// even if loadManifest is not called again.
if let haveToken = SessionManager.shared.currentUser?.token
{
$0.headers["Authorization"] = haveToken
}
}
顺便说一下,该令牌注入部分已经运行良好。 耶,午睡!
网址解析版本
与Siesta相比,这很臃肿,我现在不使用它,但这是它曾经的样子:
func login(user: SessionUser, endpoint: URL)
{
DDLogInfo("Logging in: (user.name) with (user.password)")
let json: [String: Any] = ["name": user.name, "password": user.password]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
var request = URLRequest(url: endpoint)
request.httpMethod = "POST"
request.httpBody = jsonData
_currentStatus = .Unknown
weak var welf = self
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
handleLogin(error: error, message: "No data from login attempt")
return
}
let jsonData:Any
do {
jsonData = try JSONSerialization.jsonObject(with: data, options: [])
}
catch let jsonDecodeError {
handleLogin(error: jsonDecodeError, message: "Could not get JSON from login response data")
return
}
guard let jsonDecoded = jsonData as? [String: Any] else {
handleLogin(error: error, message: "Could not decode JSON as dictionary")
return
}
guard let token = jsonDecoded["token"] as? String else {
handleLogin(error: error, message: "No auth token in login response")
return
}
let newUser = SessionUser(name: user.name, password: "", token: token)
welf?.currentUser = newUser
welf?.saveCurrentSession()
welf?._currentStatus = .LoggedIn
DDLogInfo("User (newUser.name) logged in")
loginUpdate(user: newUser, status: .LoggedIn, message: nil, error: nil)
}
task.resume()
}
午睡版
这是我现在的尝试:
func login(user: String, pass: String, status: @escaping (String?) -> ())
{
let json = [ "name": user, "password": pass]
let req = ManifestCloud.shared.keys.request(.post, json: json)
req.onSuccess { (tokenInfo) in
if let token = tokenInfo.jsonDict["token"] as? String
{
let newUser = SessionUser(name: user, password: pass, token: token)
self.currentUser = newUser
}
status("success")
}
req.onFailure { (error) in
status(error.userMessage)
}
req.onCompletion { (response) in
status(nil)
}
}
它有点工作,但是Siesta没有保存登录凭据,我不得不为登录状态安装一个新的通知系统,我希望Siesta能为我做。
我想使用 Siesta 的缓存,以便在本地缓存 SessionUser 对象,如果需要,我可以使用它来获取新令牌,使用缓存的凭据。 目前我有一个使用UserDefaults
的陪审团操纵系统。
任何帮助表示赞赏!
这里的基本问题是您正在请求但不加载资源。Siesta 区分了这两件事:第一件事本质上是一个幻想的 URL 请求;第二种意味着午睡会挂在某个状态上,并通知观察者。
有趣的是,几分钟前我刚刚回答了一个不同但相关的问题!您可能会发现这个答案是一个有用的起点。
在您的情况下,问题就在这里:
let req = ManifestCloud.shared.keys.request(.post, json: json)
该.request(…)
意味着只有您的请求钩子(onSuccess
等)在您的 POST 请求完成时会收到通知,并且 Siesta不会保持状态供其他人观察。
您通常使用.load()
来完成此操作;但是,这会创建一个 GET 请求,并且您需要一个 POST。您可能希望将您的 POST 提升为一个成熟的加载请求,如下所示:
let keysResource = ManifestCloud.shared.keys
let req = keysResource.load(using:
keysResource.request(.post, json: json))
这将获取 POST 请求返回的任何内容,并使其成为ManifestCloud.shared.keys
的(可观察)latestData
,这应该为您提供您正在寻找的"登录状态通知系统"。