Such posts are really dev issues, not peer user support issues :)

Redirecting you to d...@httpd

On 10/8/2010 12:12 PM, Ben Cooper wrote:
> I’ve been investigating why weak eTags aren’t being handled properly, 
> specifically why we
> always get a status 200 when we include a weak eTag, and only get a status 
> 304 when we
> delete the weak eTag and use the last modified date instead, or make the eTag 
> strong. 
> I’ve found the bug: it’s because the W tag is upper case, and Apache seems to 
> assume all
> headers are lower case.  However, I don’t know where the best place is to fix 
> the bug, as
> discussed below. 
> 
>  
> 
> The bug is in the source code as follows:-
> 
>  
> 
> The response is evaluated in http_protocol in a function called 
> ap_meets_conditions(), as
> follows
> 
> http_protocol.c: v2.2.16, line 355
> 
> not_modified = ap_find_list_item(r->pool, if_nonematch, etag);
> 
>  
> 
> This line of code is executed for both strong and weak eTags for full Get 
> requests (ie not
> Range requests, which are caught by a previous if-statement).  The call to
> ap_find_list_item is used to compare the etag in the resource to the one in 
> the request
> (held in a hash table pointed to by the char *if_nonematch)
> 
>  
> 
> Ap_find_list_item exits in the util.c file.
> 
> util.c:  v2.2.16, line 1372
> 
> good = good && (*pos++ == apr_tolower(*ptr));
> 
>  
> 
> The for-loop surrounding this line of code walks through the characters in 
> the two
> strings, comparing them character-by-character.  It maintains some state 
> variables, such
> as in_qstr that tracks whether or not the pointer is currently within a 
> quote.  If it is
> within a quote, it compares the two characters directly; if not within 
> quotes, it executes
> line 1372 that lower-cases *ptr value.  This assumes that the *pos value is 
> already lower
> case.  However, the weak eTag is defined by protocol as beginning with the 
> uppercase
> letter W, and it appears that uppercase W is indeed what is stored in the 
> hash table
> pointed to by if_nonematch and pos. 
> 
>  
> 
> Testing this, my colleagues have created eTags with values such as
> 
> “W1234-123123”
> 
> W/”1234-123123”
> 
> w/”1234-123123”
> 
>  
> 
> We have found that provided the eTag is fully quoted, or preceded by a 
> lowercase w, httpd
> works as we would expect and returns a 304 to a conditional Get.  However, if 
> the eTag is
> preceded by an uppercase W, as per the protocol, then httpd always returns 
> 200.  It
> appears as if the cache is not working, but that is not the problem – it is 
> the comparison
> of the W that is failing and causing the behaviour.
> 
>  
> 
> A targeted fix is to lowercase if_nonematch just prior to calling 
> ap_find_list_item(). 
> Because if_nonematch is a pointer, this may have an undesirable side-effect 
> elsewhere in
> the code, so a “safer” approach is first to copy the string into a local 
> variable, then
> lowercase the W, and then call ap_find_list_item().  However, I wonder if a 
> more natural
> home for the fix would be to make the W lowercase when the hash table is 
> loaded? 
> 
>  
> 
> Could someone who knows the code much better than me take up this issue, 
> decide the best
> location for a fix, and implement it? 
> 
> Many thanks,
> 
> Ben Cooper
> 
> Please consider the environment before printing this email.
> 
> This message should be regarded as confidential. If you have received this 
> email in error please notify the sender and destroy it immediately.
> Statements of intent shall only become binding when confirmed in hard copy by 
> an authorised signatory.  The contents of this email may relate to dealings 
> with other companies within the Detica Limited group of companies.
> 
> Detica Limited is registered in England under No: 1337451.
> 
> Registered offices: Surrey Research Park, Guildford, Surrey, GU2 7YP, England.
> 
> 

Reply via email to