午睡休息登录

Siesta REST login

如何将我的登录用户 URLSession 代码转换为 Siesta framework 代码?我目前的尝试没有奏效。

我查看了 GithubBrowser 中的示例,但我的 API 不是那样工作的。

问题是用户结构在某种程度上 分裂 取决于我正在使用的 API 端点的工作方式。终点是 http://server.com/api/key。是的,它确实被称为 key 而不是 userlogin。作者这样称呼它是因为你 post 一对 user/pass 并得到一个密钥。所以它 接受 (通过 post)一个 json 结构,如:

{"name": "bob", "password": "s3krit"}

和returns 作为回应:

{"token":"AEWasBDasd...AAsdga"}

我有一个 SessionUser 结构:

struct SessionUser: Codable
{
    let name: String
    let password: String
    let token: String
}

...为用户封装了状态(REST中的"S")。问题是名称和密码得到 posted 并且令牌是 response

当这个状态改变时,我会做我的:

service.invalidateConfiguration()  // So requests get config change
service.wipeResources()            // Scrub all unauthenticated data

一个实例存储在一个单例中,它被配置块拾取,以便来自 API 的令牌被放入 header 以用于所有其他 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
        {
            [=14=].headers["Authorization"] = haveToken
        }
    }

顺便说一句,令牌注入部分已经运行良好。耶,午睡!

URLSession 版本

与 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 object 缓存在本地,如果需要,我可以使用它来获取新令牌,使用缓存的凭据。目前我有一个 jury-rigged 系统使用 UserDefaults.

感谢任何帮助!

这里的基本问题是您正在请求但没有加载资源。 Siesta draws a distinction between those two things:第一个本质上是一个fancied-up URLSession 请求;第二个意味着 Siesta 挂在某个状态上并通知观察者。

有趣的是,几分钟前我刚刚回答了一个 问题!您可能会发现该答案是一个有用的起点。

你的情况,问题出在这里:

let req = ManifestCloud.shared.keys.request(.post, json: json)

.request(…) 意味着只有您的请求挂钩(onSuccess 等)在您的 POST 请求完成时收到通知,而 Siesta 不会为其他人保留状态观察。

您通常可以使用 .load() 来完成此操作;但是,这会创建一个 GET 请求,您需要一个 POST。你可能想 promote your POST to be a full-fledge load request 这样:

let keysResource = ManifestCloud.shared.keys
let req = keysResource.load(using:
    keysResource.request(.post, json: json))

这将接受 POST 请求 returns 的任何内容,并使其成为 ManifestCloud.shared.keys 的(可观察的)latestData,这应该会给你“登录通知系统”状态”,你正在寻找。