jsr369-experts@servlet-spec.java.net

[jsr369-experts] Re: [servlet-spec users] Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: revised trailer proposals

From: Shing Wai Chan <shing.wai.chan_at_oracle.com>
Date: Fri, 21 Apr 2017 17:04:43 -0700

Let me summarize our dicussions on #getTrailers API.
I. We will choose NeverReturnNull option.

II. Trailer vs Trailers.
    SW> In RFC 7230, Appendix B. Collected ABNF, we have the followimg:
    SW> Trailer = *( "," OWS ) field-name *( OWS "," [ OWS field-name ] )
    SW> chunked-body = *chunk last-chunk trailer-part CRLF
    SW> t-codings = "trailers" / ( transfer-coding [ t-ranking ] )
    SW> trailer-part = *( header-field CRLF )

    SW> In 4.1.2 of RFC 7230, we have
    SW> A trailer allows the sender to include additional fields at the end
    SW> of a chunked message in order to supply metadata that might be
    SW> dynamically generated while the message body is sent, such as a
    SW> message integrity check, digital signature, or post-processing
    SW> status. The trailer fields are identical to header fields, except
    SW> they are sent in a chunked trailer instead of the message's header
    SW> section.

    SW> In 4.3 of RFC 7230, we have
    SW> The TE field-value consists of a comma-separated list of transfer
    SW> coding names, each allowing for optional parameters (as described in
    SW> Section 4), and/or the keyword "trailers".

    SW> So, look like "trailers" is a keyword used in TE.
    SW> And a trailer is a collection of headers.

    SW> Should we rename our API as
    SW> #getTrailerFields, #setTrailerFields or
    SW> #getTrailer, #setTrailer?
    SW> I prefer the former.

    GW> I still prefer #getTrailers, but if we have to change
    GW> then #getTrailerFields is second choice.

    Any comments from other EG members?

III. The data structure for trailer.
   SW> In the current proposal, we use Map<String, String>.
   SW> Here, lower case is used to store header name as key.
   SW> Also, we assume that multiple headers with the same header name will be combined into one.

   MT> If you have multiple header fields with the same name, then order is
   MT> important but that is why I was suggesting Map<String,List<String>>

   SW> Let us take a look at the 3.2.2 of RFC 7230:
   ...
   SW> In other words, all header fields except "Set-Cookie" can be combined into one.
   SW> However, "Set-Cookie" cannot be used as a trailer.
   SW> Do we still want to have the flexibility to have multiple header fields with
   SW> the same field name?

   GW> Maybe List<Map.Entry<String,String>> is a better type to use as it is
   GW> fully semantically equivalent to HTTP headers rather than an approximation.

   Then Greg has started a discussion of whether using Map/TreeMap and with or without List.
   As mentioned before, we should not use TreeMap in the API. So, the five options should
   be as follows:

        1. Map<String, String> - lower case keys, multiple fields merged.
        2. Map<String, String> - case insensitive, multiple fields merged.
        3. Map<String, List<String>> - lower case keys
        4. Map<String, List<String>> - case insensitive
        5. List<Map.Entry<String,String>> - ugly, very inconvenient

   MT> 3 > 1 > 4 > 2 > 5
   GW> 1, 4

   GW> I called Map<String, List<String>> inconvenient as for the common case of
   GW> wanting a single value, the user must deal with a list. They must decide if
   GW> they are going to iterate, take the first element after a range check or
   GW> just trust it has more than 0 elements.

   GW> In the case that the field can have multiple values, they still need to parse
   GW> each value in the list as that to can be a CSV:

   GW> trailer: a,b
   GW> trailer: c,d

   GW> Would arrive as {"trailer"=["a,b","c,d"]}, or are you saying that the container
   GW> should parse values and return {"trailer"=["a","b","c","d"]}?
   GW> While this would be very convenient, it is a big difference to our handling of
   GW> getHeaders and may not be appropriate for all headers.

   GW> If the list value types are to provide parsed/split values, then I'm less keen
   GW> on them. As much as I think the container should have provided that semantic,
   GW> that horse bolted decades ago and we have ceded the responsibility for that to
   GW> frameworks and applications.

   GW> So I still like 1. Map<String,String> and a mostly sufficient simplification
   GW> of the trailer semantic. But if there is not universal support for it
   GW> (or for the list variants), then I think we have to look at something like
   GW> ugly but correct like 5. List<Map.Entry<String,String>>

   Any other comments?
   Thanks.
       Shing Wai Chan


> On Apr 21, 2017, at 3:35 PM, Greg Wilkins <gregw_at_webtide.com> wrote:
>
>
> On 22 April 2017 at 01:32, Mark Thomas <markt_at_apache.org <mailto:markt_at_apache.org>> wrote:
> I disagree with the convenient / inconvenient tags above.
>
> If a header has multiple values in the vast majority of cases the first
> thing the user is going to want to do is split it up into the individual
> values. I'd argue it makes more sense for the container to write that
> code once than have every user write that code.
>
> Mark,
>
> I called Map<String, List<String>> inconvenient as for the common case of
> wanting a single value, the user must deal with a list. They must decide if they are going to iterate, take the first element after a range check or just trust it has more than 0 elements.
>
> In the case that the field can have multiple values, they still need to parse each value in the list as that to can be a CSV:
>
> trailer: a,b
> trailer: c,d
>
> Would arrive as {"trailer"=["a,b","c,d"]}, or are you saying that the container should parse values and return {"trailer"=["a","b","c","d"]}? While this would be very convenient, it is a big difference to our handling of getHeaders and may not be appropriate for all headers.
>
> If the list value types are to provide parsed/split values, then I'm less keen on them. As much as I think the container should have provided that semantic, that horse bolted decades ago and we have ceded the responsibility for that to frameworks and applications.
>
> So I still like 1. Map<String,String> and a mostly sufficient simplification of the trailer semantic. But if there is not universal support for it (or for the list variants), then I think we have to look at something like ugly but correct like 5. List<Map.Entry<String,String>>
>
> regards
>
>
>
>
>
>
> --
> Greg Wilkins <gregw@webtide.com <mailto:gregw@webtide.com>> CTO http://webtide.com <http://webtide.com/>