Taking into account Stuart and Greg's responses, here is a revised
proposal.
A. Reading the request trailer headers.
b) HttpServletRequest:
Add the following API to HttpServletRequest:
public String getTrailer(String name);
public Collection<String> getTrailers(String name);
public Collection<String> getTrailerNames();
Note: existing methods in HttpServletRequest interface use Enumeration here.
c) RequestTrailerMap (from Simone Bordet):
Add the following API to HttpServletRequest:
public Map<String, String> getTrailers();
d) RequestTrailerField (from Simone Bordet):
Add the following API to HttpServletRequest:
public TrailerFields getTrailers();
TrailerFields is a class representing a list of trailer fields
e) ConsumerCallback (from Stuart Douglas):
Add the following API to HttpServletRequest:
setTrailerCallback(Consumer<Map<String, String>> callback).
Note: For (b)-(e) above, then the trailer headers will "not" be
available to HttpServletRequest#getHeader, #getHeaders, #getHeaderNames.
On Sun, 9 Apr 2017 07:25:49 +1000, Greg Wilkins <gregw_at_webtide.com> said:
GW> with regards to request trailers, the key decision is when they are
GW> available, specially with async. Does the application have to read content
GW> to -1 or onAllDataRead before the trailers are available? I think yes.
GW> Then it does not make much sense to make them available via the normal
GW> header API and I think they need their own API.
B. Writing the response trailer headers.
a) HttpServletResponse:
public void addTrailer(String name, String value)
public void getTrailer(String name)
public Collection<String> getTrailers(String name)
public Collection<String> getTrailerNames()
b) Supplier (from Simone Bordet):
public void setTrailers(Supplier<TrailerFields>);
where TrailerFields is defined in A.d above.
c) SupplierMap (cf. A.c, above)
public void setTrailers(Supplier<Map<String, String>>);
SD> This does not support multiple headers with the same name (not sure if
SD> it will be a problem in practice).
Yes. In this case, the user need to combine headers with the name
into one header before calling the API.
According section 4.1.2 of RFC 7230:
A sender MUST NOT generate a trailer that contains a field necessary
for message framing (e.g., Transfer-Encoding and Content-Length),
routing (e.g., Host), request modifiers (e.g., controls and
conditionals in Section 5 of [RFC7231]), authentication (e.g., see
[RFC7235] and [RFC6265]), response control data (e.g., see Section
7.1 of [RFC7231]), or determining how to process the payload (e.g.,
Content-Encoding, Content-Type, Content-Range, and Trailer).
Since this is a supplier, I suggest the following:
The trailers that run afoul of the provisions of section 4.1.2 of RFC 7230
are ignored.
GW> For responses, a simple addTrailer API is also not sufficient again because
GW> of the timing of when it may be called. It may be too late to call
GW> addTrailer after some content has been written because if the response has
GW> been committed the container may have choosen to not use HTTP/1.1 chunking
GW> for the respone (because content-length was known or because
GW> Connection:close had been specified), so it may be impossible to add the
GW> trailers. Thus I think we need an API that allows the application to
GW> signal it's intent to maybe set trailers, so the container can choose a
GW> transport framing that does support trailers. That is why an API that
GW> uses Supplier or Future or similar makes sense, as it can be called early
GW> to indicate that trailers may be supplied and then the trailers can be set
GW> later (during and/or after content generation).
ACTION: Revised recommendations are now A.e ConsumerCallback and B.c SupplierMap.
Please let me know your opinion.
Thanks.
Shing Wai Chan