Bug 65281 - Tomcat does not process correctly Etag and send HTTP 400 error code
Summary: Tomcat does not process correctly Etag and send HTTP 400 error code
Status: RESOLVED INVALID
Alias: None
Product: Tomcat 9
Classification: Unclassified
Component: Connectors (show other bugs)
Version: 9.0.45
Hardware: PC Linux
: P2 regression (vote)
Target Milestone: -----
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-04-30 11:49 UTC by François PLOU
Modified: 2021-05-03 20:32 UTC (History)
0 users



Attachments
Exported HAR (17.21 KB, text/plain)
2021-04-30 12:40 UTC, François PLOU
Details
Exported HAR (2) (24.50 KB, text/plain)
2021-04-30 12:41 UTC, François PLOU
Details
ok.har (205.87 KB, text/plain)
2021-04-30 14:56 UTC, François PLOU
Details
ko.har (17.20 KB, text/plain)
2021-04-30 14:56 UTC, François PLOU
Details

Note You need to log in before you can comment on or make changes to this bug.
Description François PLOU 2021-04-30 11:49:53 UTC
When a response to a request contains following header (and more specially the Etag attribute) :

Cache-Control, Etag, Expires, Last-Modified as this example :


HTTP/1.1 200 OK
Last-Modified: Thu, 01 Apr 2021 15:36:29 GMT
Cache-Control: public, must-revalidate
Expires: ven., 30 avr. 2021 13:47:45 +0200
Accept-Ranges: bytes
ETag: W/"12581-1617291389000"
Content-Type: text/css
Content-Length: 12581
Date: Fri, 30 Apr 2021 11:37:45 GMT
X-Cache: MISS from kamino
X-Cache-Lookup: MISS from kamino:3128
Via: 1.0 kamino (squid/3.1.23)
Connection: keep-alive

The next request of the browser on same resource will send back following header to check if the resource has been modified :

If-Modified-Since: Thu, 01 Apr 2021 15:36:29 GMT
If-None-Match: W/"12581-1617291389000"

Normally tomcat must answer http 200 or http 304 but it sends and http 400 status.

The problems also concerns Tomcat 8.5.63.
The release 9.0.37 does not have this behaviour.

In addition, if the browser sends If-None-Match: *, the http 400 does not occurs.


Regards

François
Comment 1 Remy Maucherat 2021-04-30 12:26:39 UTC
(In reply to François PLOU from comment #0)
> The release 9.0.37 does not have this behaviour.

The real question is if 9.0.45 has the behavior, because a telnet works for me with a matching If-None-Match and the comparison code (which is returning 400 only with a malformed header) appears sound.
Comment 2 François PLOU 2021-04-30 12:40:57 UTC
Created attachment 37842 [details]
Exported HAR

Exported har from firefox with http400
Comment 3 François PLOU 2021-04-30 12:41:50 UTC
Created attachment 37843 [details]
Exported HAR (2)

Exported HAR from Firefox when the problem does not occurs
Comment 4 François PLOU 2021-04-30 12:44:19 UTC
Yes the 9.0.45 has this behaviour.
I forgot to mention the this is not 100% the case. Sometimes it works sometimes not.

I just need to click on refresh.

The attachment sample.har contains the case on resource logo-headerH.png.
The attachement sample2.har is a refresh on same resource where the problem does not occurs.

Thanks
Comment 5 Konstantin Kolinko 2021-04-30 14:07:04 UTC
(In reply to François PLOU from comment #0)
> When a response to a request contains following header (and more specially
> the Etag attribute) :
> 
> Cache-Control, Etag, Expires, Last-Modified as this example :
> 
> 
> HTTP/1.1 200 OK
> Last-Modified: Thu, 01 Apr 2021 15:36:29 GMT
> Cache-Control: public, must-revalidate
> Expires: ven., 30 avr. 2021 13:47:45 +0200
> Accept-Ranges: bytes
> ETag: W/"12581-1617291389000"
> Content-Type: text/css
> Content-Length: 12581
> Date: Fri, 30 Apr 2021 11:37:45 GMT
> X-Cache: MISS from kamino
> X-Cache-Lookup: MISS from kamino:3128
> Via: 1.0 kamino (squid/3.1.23)
> Connection: keep-alive

As you can see above, there are the following headers:

> Last-Modified: Thu, 01 Apr 2021 15:36:29 GMT
> Expires: ven., 30 avr. 2021 13:47:45 +0200

In attachment 37842 [details] (from comment #2), the broken (400) response contains:

>          "headers": [
>            {
>              "name": "Last-Modified",
>              "value": "jeu., 1 avr. 2021 17:37:40 +0200"
>            },
>...
>            {
>              "name": "Expires",
>              "value": "ven., 14 mai 2021 14:36:45 +0200"
>            },

Please note, that the values above that are not in English are illegal for those headers.

RFC 7232 ch.2.2 defines

> Last-Modified = HTTP-date

RFC 7234 ch.5.3 defines

> Expires = HTTP-date

RFC 7231 ch.7.1.1.1 defines

> HTTP-date    = IMF-fixdate / obs-date

and IMF-fixdate is defined in English (with fixed character strings for "Mon" etc.)

>     IMF-fixdate  = day-name "," SP date1 SP time-of-day SP GMT
>     ; fixed length/zone/capitalization subset of the format
>     ; see Section 3.3 of [RFC5322]
>
>     day-name     = %x4D.6F.6E ; "Mon", case-sensitive
>                  / %x54.75.65 ; "Tue", case-sensitive
>                  / %x57.65.64 ; "Wed", case-sensitive
>                  / %x54.68.75 ; "Thu", case-sensitive
>                  / %x46.72.69 ; "Fri", case-sensitive
>                  / %x53.61.74 ; "Sat", case-sensitive
>                  / %x53.75.6E ; "Sun", case-sensitive

https://cwiki.apache.org/confluence/display/TOMCAT/Specifications

As other response (with status 200) from the same har file has a correct header, I guess that this response is not generated by Apache Tomcat.

1. I suggest you to find out, what generates that incorrect response.

2. Regarding you problem:

- Please verify, whether the request has reached Apache Tomcat. (E.g. enable an access log).

- If the proxy sends incorrect headers to Tomcat, Tomcat can respond with error 400.

BTW,

> X-Cache: MISS from kamino
> X-Cache-Lookup: MISS from kamino:3128
> Via: 1.0 kamino (squid/3.1.23)
Comment 6 François PLOU 2021-04-30 14:56:38 UTC
Created attachment 37844 [details]
ok.har
Comment 7 François PLOU 2021-04-30 14:56:50 UTC
Created attachment 37845 [details]
ko.har
Comment 8 François PLOU 2021-04-30 14:57:00 UTC
Thanks for your answer. I have modified the response header in order to be compliant and problem is the same (check attachement : ok.har and ko.har)

I confirm the request as reached Apache Tomcat as it is a direct connection between browser and Eclipse running Apache.

There is no proxy.


We have the same problem on production system after a tomcat upgrade and we have found a bypass (not a good one but it is a solution right now) by removing the header Etag from the response.
Once Etag is removed, the browser does not send anymore the If-None-Match attribute and it works well.

On this production system we have an Apache HTTP server in front of the Tomcat Server. And I can confirm we see the 400 status in the Tomcat log.

Thanks
Comment 9 Mark Thomas 2021-05-03 20:32:57 UTC
This is not a Tomcat issue. I have manually tested this (with Telnet) and Tomcat happily accepts the following request:

GET /tomcat.svg HTTP/1.1
Host: localhost:8080
If-Modified-Since: Mon, 03 May 2021 20:24:44 GMT
If-None-Match: W/"67795-1620035809000"

and correctly returns a 304 response.

It is clear from the headers in the provided attachments that the application has at least one component providing caching. I suspect the issue is somewhere in that code.

Please do not re-open this issue unless you can provide a valid HTTP request that incorrectly generates a 400 response when sent to a clean Apache Tomcat install.