我在Flask中创建一个新的RESTful API,它应该接受给定对象的GET(用于请求资源)和PATCH(用于执行各种增量,非幂等更新)。问题是,某些已修补的数据必须经过身份验证,有些数据不应该是。
为了澄清一个例子,让我们说我正在构建一个应用程序,让每个人都可以查询资源被点击的次数以及查看该页面的次数。它还让人们在javascript中对资源进行更新,说资源再次被点击(未经身份验证,因为它来自前端)。它还允许经过身份验证的后端增加页面被查看的次数。
所以,遵循RESTful原则,我认为所有三个动作都应该在同一条路径上完成 - 类似于/pages/some_page_name
,它应该同时接受GET和PATCH,并且应该接受两种不同类型的数据。补丁。问题是在Flask中,看起来身份验证始终是围绕一个方法使用装饰器进行的,所以如果我有一个类似@app.route('/pages/<page_id>', methods=['GET', 'PATCH'])
的方法,我的身份验证将通过像@auth.login_required
这样的装饰器完成。整个方法,这将迫使不需要身份验证的方法进行身份验证。
所以,我的问题有三个:
答案 0 :(得分:1)
我发现你的设计存在一些问题。
假设我正在构建一个应用程序,让每个人都可以查询资源被点击的次数以及查看其页面的次数
嗯。这不是一个好的REST设计。您不能让客户端查询选择资源的“属性”,只选择资源本身。如果您的资源是“页面”,那么对/pages/some_page_name
的GET请求应该返回类似这样的内容(在JSON中):
{
'url': 'http://example.com/api/pages/some_page_name',
'clicks': 35,
'page_views': 102,
<any other properties of a page resource here>
}
它还允许人们在javascript中对资源进行更新,说明资源再次被点击
“点击内容”是一个动作,因此它不是一个好的REST模型。我对你的项目了解不够,所以我错了,但我认为最好的解决办法就是让用户点击这个东西,然后服务器会收到某种请求(也许是GET来获取资源)被点击了?)。然后,服务器可以自行增加资源的clicks
属性。
(未经验证,因为它来自前端)。
这可能很危险。如果您允许任何人更改您的资源,那么您可能会受到攻击,这可能是一个问题。没有什么能阻止我查看您的Javascript并对您的API进行逆向工程,然后发送虚假请求以人为地更改计数器。这可能是可接受的风险,但请确保您了解这可能发生。
另外,让经过身份验证的后端会增加页面被查看的次数。
后端?这是客户端还是服务器?听起来应该是客户。再一次,“递增”不是REST类型API的良好匹配。让服务器根据从客户端收到的请求来管理计数器。
假设我明白你在说什么,在我看来你只需要支持GET
。服务器可以在收到请求时自行更新这些计数器,客户端无需为此烦恼。
更新:在下面的评论中提供了一些其他信息之后,我认为您可以做的是RESTful也是实施PUT
请求(或PATCH
如果你是部分资源更新。
如果您执行PUT
,则客户端将发送上述相同的JSON表示,但它将递增相应的计数器。您可以在服务器中添加验证以确保计数器按顺序递增,如果发现它们不是,则返回400状态代码(对于某些经过身份验证的用户,可能会跳过此验证,由您决定)。例如,从上面的示例开始,如果您需要增加点击次数(而不是页面浏览量),请发送PUT
请求:
{
'url': 'http://example.com/api/pages/some_page_name',
'clicks': 36,
'page_views': 102
}
如果您使用PATCH
,则可以删除不会更改的项目:
{
'clicks': 36
}
老实说,我觉得这不是你问题的最佳设计。您在此处拥有非常特定的客户端和服务器,旨在相互协作。 REST对于分离的客户端和服务器来说是一个很好的设计,但如果你在线路的两边,那么REST并没有真正给你很多。
现在关于您的身份验证问题,如果您的PUT
/ PATCH
需要有选择地进行身份验证,那么您只能在必要时发出HTTP基本身份验证交换。我编写了Flask-HTTPAuth扩展名,您可以查看我如何实现此交换并将代码复制到您的视图函数中,以便您只在必要时才能发布它。
我希望这能澄清一些事情。