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/>