7

RFC 7231 - HTTP/1.1 Semantics and Content, 5.3 Content Negotiation does not define how to specify to accept a multipart/related content type with particular content types for body parts in the accept header field.

For instance, how to express acceptance of multipart/related content with text/html body parts

Accept: multipart/related;type=text/html

or

Accept: multipart/related,text/html

And if you want to specify precedences for different html flavours?

Accept: multipart/related;type=text/html;q=0.7,
   multipart/related;type=text/html;level=1,
   multipart/related;type=text/html;level=2;q=0.4

or

Accept: multipart/related,text/html;q=0.7,
   text/html;level=1,
   text/html;level=2;q=0.4

What's right? Both?

Community
  • 1
  • 1
Gunter Zeilinger
  • 131
  • 1
  • 2
  • 4
  • The second option is motivated by https://www.w3.org/Protocols/HTTP/Object_Headers.html : "Content-Type: : Multipart types MIME provides for a number of "multipart" types. These are encapsulations of several body parts in the one message. In HTTP, Multipart types may be returned on the condition that the client has indicated acceptability (using Accept: )of the multipart type **and** _(emphased by myself)_ also of the content types of each consitutent body part. The body parts ( unlike in MIME ) MAY contain HTTP metainformation header fields which ARE significant." – Gunter Zeilinger Mar 31 '16 at 12:42

2 Answers2

9

To start off, HTTP is a MIME-like protocol, not a MIME-compliant one. To quote RFC 7230, section 2.1:

Messages are passed in a format similar to that used by Internet mail [RFC5322] and the Multipurpose Internet Mail Extensions (MIME) [RFC2045] (see Appendix A of [RFC7231] for the differences between HTTP and MIME messages).

This is important to keep in mind, as this grants us some liberties when dealing with MIME content.

The Accept header is subject to RFC 7231, sec. 5.3.2. The syntax described there allows for a list of comma-seperated mediatypes (see RFC 7230, sec. 7) with an arbitrary number of mediatype-specific parameters each in addition to the HTTP-specific weight parameter q (see RFC 7231, sec. 5.3.1).

Section 3.1.1.1 discusses which mediatypes are considered valid for the Accept and Content-Type headers:

HTTP uses Internet media types [RFC2046] in the Content-Type and Accept header fields in order to provide open and extensible data typing and type negotiation. [...] Internet media types ought to be registered with IANA according to the procedures defined in [BCP13]

[BCP13] is referring to RFC 6838, eventually leading to the IANA Media Types Registry.

It bears mentioning that the syntax of the Accept header does not require any parameters to be present; they are all optional as far as the HTTP spec is concerned. If there are required parameters, they must be required directly by the mediatype in question:

The presence or absence of a parameter might be significant to the processing of a media-type, depending on its definition within the media type registry.

The multipart/related MIME type itself is subject to RFC 2387. Section 3.1 of which explicitly makes the type paramater mandatory. It is also a single value, not a list. Interestingly, the HTTP spec is stressing out the importance of the presence of the boundary parameter over RFC 2046, section 5.1.1. From RFC 7231, section 3.1.1.4:

All multipart types share a common syntax, as defined in Section 5.1.1 of [RFC2046], and include a boundary parameter as part of the media type value.

My guess is that it never occured to the authors that one would put a multipart mediatype into an Accept header, which would render the boundary useless. This could indeed be a candidate for an errata (Julian?). So technically, the absolutely correct™ way to request this would be:

Accept: multipart/related; type=text/html; boundary=--my-top-notch-boundary-

In reality, implementors seem to be inclined to deliberately ignore these requirements as this example shows. I usually do not advocate against following the RFC, but I think it actually makes sense here to skip the boundary parameter. Bearing in mind that this is a request header used in content negotiation and not a dedscription of seom actual content with a specified boundary between message parts, I cannot think of a use case where requesting such a boundary were legit; unles you are out for causing some mischief. But then again you were requesting a manipulated request for yourself. I am undecided on omitting the type parameter, though. IMHO doing so would imply type=*/*, which is efectively an "I don't care, send whatever you see fit." While this may result in a response perfectly in line with RFC2387, I would personally feel uneasy about having this little control over the returned content type. (On a side note: You may always want to check the content type of responses. A 2xx code is no guarantee that you got what you requested)

Now if you send out a request with Accept: mutlipart/related, text/html, you are requesting either several parts of unspecified type or alternatively a single HTML document. If you want to negotiate the content, you will need to request several variations of multipart/related with different types:

Accept: multipart/related; type=text/html,
        multipart/related; type=text/plaintext

(Note: Line continuation added for improved legibility. Please take note that line continuation has been deprecated and should no longer be used in the context of HTTP.)

Regarding your example, I was quite surprised to find that the syntax for this mediatype is extraordinarily strict when it comes to parameters. The situation is as follows:

  • The Accept header as such is subject to RFC 7231, sec. 5.3.2
  • The mediatype(s) and subtype(s) are straight out of the IANA Media Types Registry per RFC 6838
  • The parameters are being handled as follows:
    • q is under authority of RFC 7231, sec. 5.3.1
    • boundary is under authority of RFC 2046, sec. 5.1.1
    • Remaining parameters are subject to the mediatypes' respective RFCs. In this case this means that type is required, followed by the optional parameters start and start-info
    • Unrecognized parameters are to be discarded as per RFC 2046, section 1:

MIME implementations must also ignore any parameters whose names they do not recognize.

So, if level were a recognized parameter (currently this is not even the case for the text/html mediatype. And yes, I am aware it appears in multiple examples), the correct solution were indeed this:

Accept: multipart/related; type=text/html; q=0.7,
        multipart/related; type=text/html; level=1,
        multipart/related; type=text/html; level=2; q=0.4

But stripping out the level parameter, we're down to this:

Accept: multipart/related; type=text/html; q=0.7,
        multipart/related; type=text/html,
        multipart/related; type=text/html; q=0.4

which is sementically the same as:

Accept: multipart/related; type=text/html
Community
  • 1
  • 1
DaSourcerer
  • 6,288
  • 5
  • 32
  • 55
  • I don't think that RFC 2387 clarifies my question: It was not written with the usage of `multipart/related` in the HTTP `Accept` header field in mind, and if you think you have/can apply it literally also to the HTTP `Accept` header field, you would also have to specify the also _mandatory_ `boundary` parameter (s. RFC 2046, Common Syntax of Multipart Media Type), which does not sound sensible for me. – Gunter Zeilinger Apr 03 '16 at 14:19
  • None of the referenced RFC's explicitly discuss the usage of `multipart` media types in the HTTP `Accept` header field. You may argue, so they should not be handled different to other media types. But - as already mentioned - if you argue, you have to provide a `type` parameter for `multipart/related` because it is specified as _mandatory_ in RFC 2387, you also have to explain, why you don't need to provide the `boundary` parameter, although it is specified as _mandatory_ for all `multipart` media types in RFC 2046. – Gunter Zeilinger Apr 04 '16 at 07:58
  • So far I only found one (quite old) [document](https://www.w3.org/Protocols/HTTP/Object_Headers.html#z16), which explicitly talks about usage of `multipart` media types in the HTTP `Accept` header field. Just was interested, if someone else found more. – Gunter Zeilinger Apr 04 '16 at 07:59
  • @GunterZeilinger I just updated my answer with some clarifications. – DaSourcerer Apr 05 '16 at 12:40
0

Actually, it does define it -- it says that optional parameters are allowed. How these are interpreted depends on the media type definition, not the syntax of the Accept header field.

Julian Reschke
  • 40,156
  • 8
  • 95
  • 98
  • But how to distinguish between parameters of `multipart/related` and parameters of the body part content type (e.g. `text/html;level=1`) in the expression `multipart/related;type=text/html;level=1` ? – Gunter Zeilinger Apr 03 '16 at 14:36
  • @JulianReschke Can you take a look at my answer? There may be something errata-worthy about RFC 7231, sec. 3.1.1.4 – DaSourcerer Apr 06 '16 at 13:55
  • Didn't have time; thanks for the research. If you believe there is something that needs to be fixed then by all means send mail to the HTTP WG's mailing list. – Julian Reschke Apr 07 '16 at 10:47