我有这个 api,其中登录通过发布工作,而大多数其他请求使用 get。现在我正在使用午睡将登录 URL 定义为资源。
func login(username: String, password: String) -> Resource {
return self.resource("login").withParam("username", username).withParam("password", password);
}
问题是,当我在这个资源上使用 .loadIfNeed() 时,它会做一个 get 请求,但这不起作用,因为它需要是一个 post 请求。
现在我知道 .decorateRequest 的存在,但我不确定如何使用它让我的登录资源使用 post 作为请求方法。
提前感谢,
彼得
Siesta 的load()
和loadIfNeeded()
仅用于 GET 请求。
为什么?这些 Siesta 方法建立在以下假设之上:它们没有副作用,它们的结果可以被缓存,并且可以安全地调用零次、一次或多次。在HTTP中,这是GET的合约。但是,POST、PUT 等不作任何此类承诺;每个请求都可以产生单独的效果,因此重复或可选调用它们都很危险。
要使用 POST、PUT 和 DELETE 发出请求,请使用Resource.request(…)
:
loginResource.request(.post)
(有关request(…)
与load(…)
有何不同的更多信息,请参阅 Siesta 用户指南中有关请求的部分。
例如,为什么没有单独的设置来使资源成为"POST 资源"?因为 REST 方法是/foo
是逻辑事物(资源)的名称,GET /foo
和PUT /foo
是对其的不同操作,一个检索其状态,另一个更改它。这不仅仅是一个美学纯洁性的问题;GET的强烈承诺与它密切相关。
如果你的API是完全非REST形状的,Siesta可能不适合它。但是,您也可以编写一个NetworkProvider
,将 REST 形状的请求转换为 API 自己的结构,让 Siesta基本上将其视为 REST API。
API 通常不会在查询字符串中获取密码(withParam(…)
这样做),而是在帖子正文中获取密码。
(旁白:如果您的 API 确实在查询字符串中采用密码,您可能不希望它这样做。查询字符串中的密码很容易泄漏到不安全的地方,例如日志文件。但是你知道你的API,我意识到你经常必须使用你所拥有的东西!
如果您的 API 确实在 POST 正文中获取密码而不是查询字符串,您可以执行以下操作:
// If it’s a JSON request
loginResource.request(.post, json: ["user": user, "password": pass])
// If it an HTML form encoded request
loginResource.request(.post, urlEncoded: ["user": user, "password": pass])
如果你真的希望Siesta缓存你的身份验证调用的结果,就好像它是一个GET请求一样,你可以使用Resource.load(using:)
:
authResource.load(using:
authResource.request(
.post, json: ["user": user, "password": pass]))
例如,如果要使用ResourceObserver
在应用中发布身份验证凭据,这将非常有用。更常见的方法是使用onSuccess
挂钩获取凭据一次并更新服务配置,但在某些情况下,load(using:)
可能是一种有用的替代方法。