通过HTTP API发送空的HTTP POST请求或GET请求以生成随机值

16

在我的 HTTP API 中,其中一个端点应该返回一个随机生成的值,并且该值将与端点的认证调用者相关联。目前,我有以下结构:

GET http://example.com/random-ticket HTTP/1.1
Authorization: Basic base64-encoded-basic-auth-value
Accept: application/json
Host: example.com

HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Type: application/json; charset=utf-8
Date: Thu, 03 Oct 2013 07:25:56 GMT
Content-Length: 59

{"user-ticket":"Pfa42634e-1a2e-4a7d-84b9-2d5c46a8dd81"}

发出GET请求以检索随机值。然而,HTTP GET调用应该是幂等的,而我的上述实现没有遵守这个规则。另一方面,我不确定是否可以使用空消息体发出HTTP POST请求。

按照HTTP规范,执行此类操作的正确方法是什么?

4个回答

18
  • 安全 => 调用是否会导致服务器状态的改变。
  • 幂等性 => 多次调用是否导致服务器上的相同更改。

因此,问题不在于返回的数据,而在于服务器状态:如果将此值存储在服务器上导致状态更改,则不适合使用GET。否则,如果返回的是数据,则可以使用GET。调用http://stackoverflow.com每隔10分钟返回不同的数据。

让我们看另一个例子,一个时钟服务,它返回当前时间。每次调用都会得到不同的值,但调用本身不会导致服务器上的状态更改,因为时钟状态是单独维护的。因此,在这里使用GET是一个好选择。


创建资源并不等同于将值存储在服务器上。 - Filip W
@FilipW 我没有说存储一个值。它是改变状态 - Aliostad
谢谢大家。这个答案更加详细,解决了我所有的困惑。 - tugberk
你说过:“如果你将这个值存储在服务器上,那么它就不适合用于GET请求。” - Filip W

12

抱歉,我混淆了GET的概念!但问题也在于服务器状态,这里没有提到,而这是关键。 - Aliostad
我认为OP非常清楚他不应该在此处使用GET,因此我试图解释他为什么不必害怕改用POST。 - Filip W
我也是这么认为。如果随机数是在内存中生成的,并且不是现有资源的一部分,会导致副作用改变,那么使用GET方法完全没有问题。 - brazo
1
我们不是在谈论创建一个与服务器状态无关的值。据我所知,生成的票证将与用户相关联,因此实际上已经创建了一个新资源(“用户-票证”资源)。这就是为什么我认为时钟服务也不是一个好的比喻。 - Filip W

5
有一个使用GET的随机生成器没有问题,因为没有被存储的服务器状态。同样地,您可以创建一个计算器,它接受参数并在调用GET时将它们相加。关于可缓存性的问题是有趣的,但对于随机生成器来说并不适用,因为资源本质上不能被缓存。这仍然不能改变它可以以安全/幂等的方式设计的事实。
至于没有正文的POST,甚至在查询字符串中使用参数也是可以的。 POST的关键是它'可能'导致对服务器的更改。不能像GET一样保证它不会发生更改,但也不能保证它会发生更改。是否设置任何内容都不会改变可能会有更改的事实。例如,想象一个虚构的资源“\counter\increment”。每次向其POST都会导致\counter增加。我没有发送任何有效载荷,但我正在引起服务器状态的更改,因此应该是POST或PUT。

1
在这种情况下,您应该使用POST,因为按设计,GET调用可以被缓存。关于空的POST正文,没有问题。类似的场景也在POST with empty body中讨论过,其中一个帖子提到:
“没有内容长度和正文的POST等同于Content-Length:0且后面没有内容的POST,例如上传空文件时可能发生这种情况。资源由URL确定,服务器必须知道如何处理正文,包括如果它是空的。事实上,我不认为这里有问题:-/”
-注:请保留html标签

2
“GET调用可以被缓存”这是正确的,但取决于您想要实现的数据一致性,即服务器上数据更改的频率。因此,您可能还有不希望允许缓存的GET请求。此外,请考虑不能缓存的经过身份验证的数据。因此,您的缓存参数在这里并不完全适用。 - brazo
3
您可以返回适当的缓存头信息。 - Aliostad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接