我需要为HTTP GET请求添加content-type头吗?

220

据我理解,设定内容类型的地方有两处:

  1. 客户端为发送到服务器的正文(例如Post请求)设置内容类型。
  2. 服务器为响应设置内容类型。

这是否意味着在所有get请求(客户端部分)中都不需要或者不应该设置内容类型?如果可以或者应该设置,那么要设置什么样的内容类型呢?

此外,在几篇文章中我读到客户端的内容类型指定了客户端想要接收的内容类型。所以,也许我的第一点是错误的?

7个回答

168
根据RFC 7231第3.1.5.5节规定:
引发包含有效载荷主体的消息的发送方应该在该消息中生成Content-Type头字段,除非发送方不知道封装表示的预期媒体类型。如果没有Content-Type头字段,则接收方可以假定媒体类型为“application/octet-stream” ([RFC2046]第4.5.1节)或者检查数据以确定其类型。
这意味着Content-Type HTTP头字段仅应针对PUTPOST请求设置。

16
@Epoc,引用的消息最多只是暗示。它并没有真正地说如果没有实体正文的消息就不应该包含 Content-Type。我们有明确的引用吗? - Pacerier
3
@Pacerier,请不要将别人的答案核心结论划掉,即使它是错误的。我同意Epoc的答案是错误的——他引用的部分中没有任何支持他答案结论的内容,并且应该被踩。但这并不意味着你应该编辑答案以消除其核心前提,从而完全改变其含义。 - Mark Amery
19
我认为你们太过于字面理解@Epoc的话了。的确,引用的内容并不是他所说的意思。但是在OPs问题的背景下,我认为结论是正确的。OP正在寻找何时包含Content-Type有意义,何时没有意义的清晰说明。Epoc提供了关于头部如何使用的信息,并得出了任何合理开发者都会得出的结论:对于具有负载主体的请求(主要是PUT和POST),你“应该”使用Content-Type,而在GET或HEAD等不需要它的地方则可能不需要它。 - JVMATL
4
你的发言:“这意味着…”——有些牵强附会。 - Adrian Bartholomew
2
@Pacerier,实际上并不需要,但是它确实说“在GET请求消息中的有效载荷没有定义的语义;在GET请求中发送有效载荷主体可能会导致某些现有的实现拒绝该请求。”——我仍然解释为“不应该”(最佳实践),而不是明确的“必须不”,这只是建议您不应该期望服务器实现的一致性。但是,是的,如果您包含有效载荷,则“应该”还包括Content-Type;只是GET中的有效载荷不是标准的一部分。 - patricknelson
当然,这种解释(比如Postman使用的)肯定是可以讨论的。例如,你可能希望使用GET请求来获取application/json(而不是text/plain)。你可以发送一个Accept:头部字段来指定这个 —— 这样或许更正确 —— 但并不是每个系统都会查看这个头部字段。人们只是假设如果请求需要XML,那么应该返回XML;同样,对于HTML、纯文本、JSON以及明天我们想出来的任何格式也是一样。 - Gwyneth Llewelyn

71

GET请求不应该有Content-Type,因为它们不具有请求实体(即,请求主体)


43
@Dmitry,需要提供引用来源,否则它只是一种假设,而不是事实。 - Pacerier
6
虽然我同意规范并没有说不能在GET请求中使用Content-Type,但是在.Net的HttpClient中似乎强制要求。请参见https://dev59.com/72gv5IYBdhLWcg3wVPTU - Adam
1
规范甚至没有强制要求GET请求不带正文... - pishpish
1
我同意“不应该”的观点,因为这种行为没有被定义(根据规范),仅此而已。再次强调,“应该”并不等同于“必须不”。只是不要期望一致的行为,因为根据规范,“GET请求消息中的有效载荷没有定义的语义;在GET请求中发送有效载荷主体可能会导致某些现有实现拒绝该请求。”但是,如果你要这样做,那么Content-Type是有意义的。 - patricknelson
1
我同意这个答案。然而,最近我在调用一个 REST API GET 端点时,除非头部 Content-Type 存在,否则它拒绝回复 200。对我来说有些疯狂... - kevinarpe
正如所说,非常正确:应该不,但并非必须不。两者之间存在着天壤之别! - Gwyneth Llewelyn

43

确实非常可选。我正在写关于未来的事情,而且即使在现在,许多 API,许多 API 根本不会关注 Accept 头部。然而,它们确实会关注 Content-Type 来确定请求者期望接收的格式。现在我意识到这就是为什么一些经常使用 GET 的 API 会使用查询字符串来传递格式参数的原因... - Gwyneth Llewelyn

37
接受的答案是错误的。引用是正确的,但声称PUT和POST必须有附加内容是不正确的。实际上PUT或POST没有要求必须具有额外的内容。而且,GET实际上也不禁止具有内容。
RFC文件确切地说明了它们的意思...如果您的一方(客户端或源服务器)将发送超出HTTP头的其他内容,则应指定Content-Type标头。但请注意,可以省略Content-Type,仍然包括内容(例如通过使用Content-Length标头)。

11

简短回答:大多数情况下,您不需要在HTTP GET请求中使用content-type头。但是规范似乎也没有排除HTTP GET请求中使用content-type头的可能性。

支持材料:

  1. "Content-Type" is part of the representation (i.e. payload) metadata. Quoted from RFC 7231 section 3.1:

    3.1. Representation Metadata

    Representation header fields provide metadata about the representation. When a message includes a payload body, the representation header fields describe how to interpret the representation data enclosed in the payload body. ...

    The following header fields convey representation metadata:

    +-------------------+-----------------+
    | Header Field Name | Defined in...   |
    +-------------------+-----------------+
    | Content-Type      | Section 3.1.1.5 |
    | ...               | ...             |
    

    Quoted from RFC 7231 section 3.1.1.5(by the way, the current chosen answer had a typo in the section number):

    The "Content-Type" header field indicates the media type of the associated representation

  2. In that sense, a Content-Type header is not really about an HTTP GET request (or a POST or PUT request, for that matter). It is about the payload inside such a whatever request. So, if there will be no payload, there needs no Content-Type. In practice, some implementation went ahead and made that understandable assumption. Quoted from Adam's comment:

    "While ... the spec doesn't say you can't have Content-Type on a GET, .Net seems to enforce it in it's HttpClient. See this SO q&a."

  3. However, strictly speaking, the specs itself does not rule out the possibility of HTTP GET contains a payload. Quoted from RFC 7231 section 4.3.1:

    4.3.1 GET

    ...

    A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

    So, if your HTTP GET happens to include a payload for whatever reason, a Content-Type header is probably reasonable, too.


如果HTTP GET请求不包含任何有效载荷,但希望以JSON或XML格式接收响应,而被调用的API对客户端的“Accept”标头并不关心,那该怎么办?这是一个需要解释的问题... - Gwyneth Llewelyn

0

-2
不在GET消息中传递内容类型的问题在于,虽然服务器端无论如何都会确定内容,但内容类型确实是无关紧要的。 我遇到的问题是,现在有很多地方设置了他们的Web服务,使其足够智能,可以捕捉到您传递的内容类型并以您请求的“类型”返回响应。 例如,我们目前正在与一个默认为JSON的地方通信,但是,他们已经设置了他们的Web服务,如果您传递了xml的内容类型,他们将返回xml而不是他们的JSON默认值。我认为这是一个很好的想法,可以推动未来的发展。

为什么这个被踩的原因还是个谜。@Leeroy只是在陈述API的实际情况。curl在设置任何Content-Type头部时都没有问题,即使是GET请求,这样可以让API聪明地确定返回的格式。虽然这不是应该的方式——Accept头部应该用于告诉服务器可接受的内容类型——但实际上很多聪明的API确实使用了它。请注意,这只是对规范的解释;规范并没有明确禁止这种机制,因此它被使用了。 - Gwyneth Llewelyn

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