Сиеста REST логин
Как перевести мой логин URLSession
код в коде системы Сиеста? Моя текущая попытка не работает.
Я посмотрел на пример в GithubBrowser, но API у меня не работает так.
Проблема в том, что структура пользователя в некоторой степени разделена тем, как работает конечная точка в API, который я использую. Конечная точка http://server.com/api/key
, Да, это действительно называется key
и не user
или же login
, Это назвали авторы, потому что вы публикуете пару пользователь / пароль и получаете ключ назад. Таким образом, он принимает (через почту) структуру json, такую как:
{"name": "bob", "password": "s3krit"}
и возвращает в качестве ответа:
{"token":"AEWasBDasd...AAsdga"}
у меня есть SessionUser
структура:
struct SessionUser: Codable
{
let name: String
let password: String
let token: String
}
... который инкапсулирует состояние ("S" в REST) для пользователя. Проблема в том, что имя и пароль публикуются, а токен - это ответ.
Когда это состояние меняется, я делаю свое:
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
}
}
Кстати, эта часть для инъекции токена уже работает хорошо. Уу, сиеста!
Версия URLSession
Это раздутый по сравнению с Сиестой, и я сейчас не использую это, но вот то, что было раньше:
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
,
Любая помощь приветствуется!
1 ответ
Основная проблема здесь в том, что вы запрашиваете, но не загружаете ресурс. Сиеста проводит различие между этими двумя вещами: первое, по сути, причудливый запрос URLSession; второе означает, что Сиеста держится за какой-то штат и уведомляет об этом наблюдателей.
Забавно, я только что ответил на другой, но связанный с этим вопрос несколько минут назад! Вы можете найти этот ответ полезной отправной точкой.
В вашем случае проблема здесь:
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-запрос, и сделает его (наблюдаемым) latestData
из ManifestCloud.shared.keys
, которая должна дать вам "систему уведомлений о состоянии входа", которую вы ищете.