On Tue, 04 Oct 2011 08:30:47 -0600, Alex Rousskov wrote:
On 10/03/2011 08:49 PM, Amos Jeffries wrote:
We got a malformed max-stale value. We have only
two options when it comes to that value interpretation, I
think:
A1. Treat it as valueless max-stale.
A2. Ignore it completely.
BTW, we have three options when it comes to forwarding the
malformed
directive:
B1. Forward our own valid directive.
B2. Forward nothing.
B3. Forward the malformed directive.
The new updated RFC texts from HTTPbis are now stating:
"
A proxy, whether or not it implements a cache, MUST pass cache
directives through in forwarded messages, regardless of their
significance to that application, since the directives might be
applicable to all recipients along the request/response chain.
It is
not possible to target a directive to a specific cache.
"
So we do not have B2 as a compliant option. If we receive it, it
MUST be
relayed.
I disagree. The above HTTPbis text does not talk about malformed
directives, which are the only subject of the current discussion. B2
is
acceptable for malformed directives, IMO, even though B3 would match
the
spirit of the above spec better.
Erasing it could be an option, but not a compliant one. Striping the
unknown-value to make it less strict than we received would be more
likely to add problems in downstream software which might understand
it.
Squid can either drop the malformed directive completely (B2) or
forward
the original malformed directive (B3). B2 is easy to implement. B3 is
not so easy and is probably not very useful in practice so I would
not
spend cycles on it, but it is Kinkie's call.
Forwarding something other than the original is a bad idea, IMO,
because
it may result in more stale objects than the client wants to accept
(B1).
That said, the spec clearly outlines it as delta-seconds so if its
not
parseable as delta-seconds its clearly malformed and B1 probably
should
not pass "max-stale".
Exactly. Although, technically, it is easy to construct a well-formed
max-stale value that Squid would consider malformed:
max-stale=9999999999999999999999999999999999999999999999999999
The same is true for virtually all integer-based values in HTTP. We
can
hope such values will never be found in real requests until we meet
aliens that write software which can cache objects for eternity.
Or the science and archival communities. They have particular accuracy
requirements on the meaning of "forever".
Which leaves us in a mess because;
A1->B1 seems intuitively the right thing, but has bad side effects.
Neither A1 nor B1 are the right things, IMO, because they may lead to
responses that are more stale than what the client is willing to
accept.
A1->B3 seems like a reasonable alternative to avoid the effects,
but
gambles on delta-seconds never changing.
A1 has a side effect of serving a possibly "too stale" object to the
client. You may be confused by the old source code comments (now
fixed
by Kinkie) that valueless max-stale means "always stale". It actually
means "never stale". Thus, A1 and B1 convert "possibly stale at some
unknown point in time" to "never stale" which feels like a bad idea.
I was going by the RFC 2616 section 14.9.3 clause on max-stale:
"If no value is assigned to max-stale, then the client is willing to
accept a stale response of any age."
Treating it compliantly as valueless when a value was sent (but not
understood or malformed) means the client will get incorrect
overly-stale objects.
If we want the client _never_ to get stale objects then it must be
treated as max-stale=0 to override both the local max_stale directives
and the RFC "anything" behaviour of valueless field.
I think we might have to get around this by using the max_stale
directive (or refresh_pattern override value) to limit the max-stale
value relayed upstream from the current Squid. If we consider this
to be
an administrative override determining that this Squid will not emit
objects older than max_stale its reasonable to shrink the requested
staleness range from the valueless "anything" and ensure we get an
object as current as we want, within the wider range of what the
client
wants.
When max-stale=value is malformed, we do not know whether we shrink
or
extend it by supplying our own value. That is why I think A2 is the
only
acceptable option for Squid internal interpretation and B2 and B3 are
the only acceptable options for forwarding.
If we do A2, ignoring the header text entirely results in using the
max_stale directives local values.
If we do A1, the RFC requires "anything" and our max_stale directives
will always be smaller or equal to that. Usually smaller (1 week) so a
slight gain in worst-case freshness over a bare assumption of
"anything".
Amos