jsr369-experts@servlet-spec.java.net

[jsr369-experts] revised trailer proposals

From: Shing Wai Chan <shing.wai.chan_at_oracle.com>
Date: Tue, 11 Apr 2017 14:07:47 -0700

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