cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dan Diephouse" <...@envoisolutions.com>
Subject Re: Identification of Partial Responses
Date Fri, 12 Jan 2007 16:19:24 GMT
On 1/12/07, Glynn, Eoghan <eoghan.glynn@iona.com> wrote:
>
>
> Well I guess it would be legal to chunk a zero-length response, if a bit
> non-sensical.
>
> And I think there's at least one more way of the server-side indicating
> a zero-length response ... by setting the Connection:close header, and
> then closing down the write side of its end of the connection without
> writing an entity body.
>
> So to be *absolutely* certain there is no entity-body data on the
> back-channel, we'd probably have to be tolerant of the following
> unlikely possibilities:
> 1. response is chunked, but first chunk is zero-length
> 2. response has connection:close set instead of content-length, but no
> content
> 3. response has non-null content-type, but no content
>
> For #1 & #2 we'd need to peek at the first octet of the input stream, to
> check if there's any actual content.
>
> Remember that in the HTTPconduit, we only need to check for a partial
> responses in the oneway case, so the question boils down to "is there a
> non-empty entity body in the response".
>
> So we'd end up with something like the following belt'n'braces logic for
> HTTPConduit.isPartialResponse():
>
> boolean isPartialResponse(URLConnection connection, Message inMessage) {
>     // a null content-type is a definite indication of no entity-body
> data
>     //
>     if (connection.getContentType() == null) {
>         return false;
>     }
>
>     // content-length if present gives a definite indication of
> entity-body
>     // data presence or absence
>     //
>     if (connection.getContentLenght() != -1) {
>         return connection.getContentLenght() > 0;
>     }
>
>     // a non-null content-type or unset content-length is not sufficient
> to establish
>     // an empty entity-body, must peek ahead on response stream if
> chunked or
>     // connection:close
>     //
>     if
> ("chunked".equalsIgnoreCase(connection.getHeaderField("transfer-encoding
> "))
>         ||
> "close".equalsIgnoreCase(connection.getHeaderField("connection"))) {
>         InputStream is = connection.getInputStream();
>         PushBackInputStream peekIS = new PushBackInputStream(is, 1)
>         int c = peekIS.read();
>         if (c != -1) {
>             peekIS.unread(c);
>             inMessage.setContent(InputStream.class, peekIS);
>             return true;
>         }
>     }
>     return false;
> }


Consider the case of zero length files in a RESTful request - a
content-length check won't work there. This is a case I would like to
support too as I want to get the HTTP binding working with non xml messages.

After reading the HTTP spec I think the Content-Type is primarily what we
should look at [1] (Greg Wilkins from Jetty confirmed this for me ). The
only case a content-type is valid with an empty body is a HEAD request.
There are some cases where people can return no content-type, but I'm pretty
sure we only want to work with messages that have content-types, no?  If we
want to handle the edge cases of messages that don't have content-types we
can also look at the http response code:

"""
For response messages, whether or not a message-body is included with
a message is dependent on both the request method and the response
status code (section 6.1.1). All responses to the HEAD request method
MUST NOT include a message-body, even though the presence of entity-
header fields might lead one to believe they do. All 1xx
(informational), 204 (no content), and 304 (not modified) responses
MUST NOT include a message-body. All other responses do include a
message-body, although it MAY be of zero length.
"""

So I would argue that we use a content-type for all request/responses (and
not just partial responses) and possibly check the response codes if we're
worried about messages without content types.


*snip*
>
> Trust me, we've returned to the drawing board many times on this one :)
> And we keep coming to the same conclusion, that partial responses in
> some form are required, and these must be distinguishable from full
> responses.


So, with the exception of this email thread, I haven't been questioning the
need for them, but rather attempting to find a more non-invasive way to
implement them. I don't think it was fruitless however. We've learned who
exactly implements this functionality, some interop requirements (http 200),
documented why we need the functionality (I'll write this up soon too), and
determined a better way to check for response messages in HTTP. Whats more I
feel like I can actually contribute to this part of the code base now,
answer questions about it on the mailing list, and brag about our ability to
handle partial responses :-)

Sorry if I've been a complete PITA about this, but I need to be able to
justify things to other people as they judge CXF (and myself) on them. I
have already gotten questions and strange looks (and I'm not speaking
figuratively here) on parts of the API in the Transport layer. People ask
why they should have to worry about partial responses, what they are, etc.
While I understand them whole lot better now, the semantics are still
difficult to explain to someone not fully versed in RM an WS-A - aka your
average developer doing webservices.

Hence my proposal on the mailing list on removing the decoupling support
from the transport layer. That proposal doesn't remove the partial response
functionality, but simply moves things around. Are you still against that?
I'm not saying that you have to go out and make the changes, I am more than
willing to do what is necessary.

- Dan

1. http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17
-- 
Dan Diephouse
Envoi Solutions
http://envoisolutions.com | http://netzooid.com/blog

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message