jsr369-experts@servlet-spec.java.net

[jsr369-experts] Re: HTTP trailer

From: Stuart Douglas <sdouglas_at_redhat.com>
Date: Mon, 10 Apr 2017 11:34:28 +1000

On Fri, Apr 7, 2017 at 4:27 AM, Shing Wai Chan
<shing.wai.chan_at_oracle.com> wrote:
> In section 5.2 of servlet spec, we have:
>
> "To be successfully transmitted back to the client, headers must be set
> before the response is committed. Headers set after the response is
> committed will be ignored by the servlet container"
>
> So servlet does not support trailer headers, as specified in RFC7230
> [1]. This is an attempt to provide better HTTP support for protocols built on
> top of it that rely on this trailer feature (such as gRPC).
>
> In the following we will investigate the various options of supporting
> trailer headers in servlet.
>
> A. Reading the request trailer headers.
> a) StandardHeader:
> Request trailer headers are standard http request headers.
> This can be accessed by using standard header APIs in HttpServletRequest.
> No new API is added in this case.

I don't think this is a good approach. The trailers will not be
available immediately, so this will basically result in the headers
changing after the request has been read. I think it could be very
confusing to the developer.

>
> 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
>
> Note: For (b)-(d) above, then the trailer headers will "not" be
> available to HttpServletRequest#getHeader, #getHeaders, #getHeaderNames.

I think all of these still have the problem that it is not really
obvious when the trailers are available. What happens if you call them
before the request has been read and the trailers consumed? If we went
with one of these approaches I would expect them to throw
IllegalStateException if the end of the request has not yet been read.

Another option would be something like
setTrailerCallback(Consumer<Map<String, String>> callback).

This would allow you to set a callback that would receive the trailers
when they arrive (if there are none then you get an empty map, and if
they have already been read the callback is invoked immediately). It
also maps better to the Supplier approach below.

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

I think some form of supplier approach is best, as it means that the
headers can be generated at the exact time they are needed.

>
> c) SupplierMap (cf. A.c, above)
> public void setTrailers(Supplier<Map<String, String>>);

This does not support multiple headers with the same name (not sure if
it will be a problem in practice).

Stuart

>
> ACTION: Please reply by April 11, 2017, COB. In the absence of responses, I am inclined
> to select A.a HttpServletRequest and B.a HttpServletResponse.
>
> Shing Wai Chan
>
> ps.
> [1] https://tools.ietf.org/rfc/rfc7230.txt