hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Roland Weber <http-as...@dubioso.net>
Subject [HttpCore] mutability and immutability
Date Sun, 12 Feb 2006 18:15:54 GMT
Hi Oleg, hi all,

I'm not quite happy with the way http-core currently handles
mutable vs. immutable messages, in particular requests. There
is an instanceof check in HttpRequestExecutor: if a request
is an instance of HttpMutableRequest, it is preprocessed. If
it is not an instance of that interface, preprocessing is
skipped. This has some questionable implications:

- the default implementations we have (HttpGet, HttpPost)
  implement the mutable interface and can not be protected
  from being modified (out of the box)

- if an application implements the non-mutable interface,
  the skipping of preprocessing will most likely result in
  an invalid request being sent. In other words:

- although the signature of HttpRequestExecutor.execute
  declares to expect an immutable request, it actually
  requires a mutable request to function properly

- the design is not "fair", meaning: we implicitly expect
  applications to respect immutability if we declare a
  return value with an immutable interface, but our code
  does not show the same respect towards the application

Yes, the last three points are more or less the same.
That just shows you how many facets my unhappiness has :-)
One other point which seems unrelated at first sight is
the distinction between auto-generated headers and headers
provided by the application. In HttpClient < 4.0, this is
used to "undo" modifications to a request before retrying,
I think in the method director.
This design restricts our request interceptors to adding
headers. Removing a header, or changing a header value,
are operations that can not be undone. Even if we might
not provide interceptors that modify header values, the
mechanism is meant for use by application developers too.
Not allowing modifications or removal of headers is a
significant restriction. Some headers for which modifications
can be useful are Cookie, Connection, Content-Encoding.

An alternative way to address mutability and immutability
is through the use of wrappers. I have seen this technique
applied in similar scenarios. The Servlet API added wrappers
for requests and responses with version 2.3:

The idea is as follows: instead of an instanceof check to
decide whether request preprocessing should be performed,
a mutable wrapper is created for the request. Preprocessing
is *always* performed, modifications apply only to the
wrapper. The auto-generated flag for Headers is pointless,
modifications are undone by forgetting about the wrapper.
Wrappers that implement only the non-mutable interfaces
can be used to protect against unintentional modifications
of objects.
This change is based on a different interpretation of
"immutable". To me, immutable doesn't mean that a request
is sent without being processed by the interceptors.
It means that the object in memory is not modified.

If you feel like you've got a deja vu now, here's why:

Based on the result of this discussion, I will try to come
up with a patch next weekend - or not.
There would be some followup issues because the distinction
between entity enclosing and header-only requests is currently
based on another instanceof check. This can be addressed by
implementing plenty of different wrapper classes, or by
removing the instanceof check in favor of a flag that can be
queried. (We don't have different response classes either.)
But that is a secondary issue to the big question:
to wrap or not to wrap?

I'm signing off now, it's been a long day. Looking forward
to read your comments tomorrow.


To unsubscribe, e-mail: httpclient-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: httpclient-dev-help@jakarta.apache.org

View raw message