Forum Discussion
Sake_Blok
Nimbostratus
Mar 28, 2006Workaround for invalid 304 content-length
Hi,
In a migration towards the BigIP, I encounter a problem with http-304 responses. In the http-header there is a "Content-Length" header with a value greater than 0. The http-rfc clearly states that a 304 MUST NOT have a body, therefore a content-length is also invalid. The effect of this content-length-header is that the BigIP is waiting for the amount of data that the header is announcing. Only after the server terminates the connection the BigIP will send the 304-response back to the client. This is an unacceptable delay.
The problem will be fixed on the http-server, but in the meantime I would like to build an iRule as a temporary workaround.
I have tried many things already and only the following iRule is working:
when HTTP_RESPONSE {
if {([HTTP::status] == 304) && [HTTP::header exists Content-Length]} {
log local0. "304 found with content-length"
HTTP::respond 304
HTTP::disable
}
}But the HTTP::disable disables HTTP-parsing for subsequent http-requests in the TCP-session (OneConnect is enabled also on this virtual). If I do a 'HTTP::header replace "Content-Length" "0"' the header is altered towards the client, but I guess there is still an internal variable that is holding the content-length value, so the BigIP will still try to collect that amount of data from the http-response and this will result in the timeout on the server and the delay towards the client.
Is there a way to change this internal variable? Or is there another way the stop the BigIP from waiting on this (nonexisting) content?
Cheers, Sake
8 Replies
- Colin_Walker_12Historic F5 Account
- Sake_Blok
Nimbostratus
Hi Colin,
Yes, I did try "HTTP::release", as well as "HTTP::collect 0". The first did not help, the BigIP still waited for the announced amount of data. The second gave an error, the parameter needs to be greater than 0.
I have a case for this issue also (C260102), there seem to be some CR's, but unfortunately it seems our configuration (on 9.1.1) is still vulnerable. It also looks like this is not fixed in later releases, hence the iRule-workaround...
So far, the only thing that stops the BigIP from waiting for the content that neven comes is "HTTP::disable", but I'm afraid that'll break other stuff.
Cheers, Sake - bl0ndie_127134Historic F5 AccountUnfortunately the only work around (at the moment) is to do a 'TCP::collect' and replace the data at the TCP layer on the server response. We have seen applications (Sharepoint) that do send data on a 304 response. There should be examples of 'TCP::collect' and 'TCP::payload replace' in the forum.
- Sake_Blok
Nimbostratus
Hi Bl0ndie, Uhmm... this application does not send data on the 304, it only adds a "Content-Length" header *as if* it is going to send data. I don't think a TCP::collect will accept a "0" as parameter. But tomorrow I will be on site, I might give it a shot.
IMHO the only way to solve this issue is to tell the BigIP that there is no data to collect. That way it will not enter the HTTP::collect or TCP::collect that happens between the HTTP_RESPONSE and the HTTP_RESPONSE_DATE (please correct me if my interpretation of how iRules work is incorrect). I'm just not sure if this is possible, and if it is how it can be done...
Cheers, Sake - bl0ndie_127134Historic F5 AccountGive this a try ...
when SERVER_CONNECTED { TCP::collect 12 } when HTTP_REQUEST_SEND { set response_pending 1 TCP::collect 12 } when SERVER_DATA { if {$response_pending == 1} { Check for 304 response if {[TCP::payload] starts_with "HTTP/1.1 304"} { set index [string first "Content-Length" [TCP::payload]] Check if header is found if {$index != -1} { TCP::payload replace $index 2 "X-" } elseif {[string first "\r\n\r\n" [TCP::payload]] == -1} { Dont have the end of header. Collect more. TCP::collect return } } set response_pending 0 } - bl0ndie_127134Historic F5 AccountOk one more try, here it is again. Looks like I lost some text when pasting.
when SERVER_CONNECTED { TCP::collect 12 } when HTTP_REQUEST_SEND { set response_pending 1 TCP::collect 12 } when SERVER_DATA { if {$response_pending == 1} { Check for 304 response if {[TCP::payload] starts_with "HTTP/1.1 304"} { set index [string first "Content-Length" [TCP::payload]] Check if header is found if {$index != -1} { TCP::payload replace $index 2 "X-" } elseif {[string first "\r\n\r\n" [TCP::payload]] == -1} { Dont have the end of header. Collect more. TCP::collect return } } set response_pending 0 } TCP::release TCP::collect } - Sake_Blok
Nimbostratus
Hi Bl0ndie,
Changing the tcp-payload before the http-parser gets hold of it does indeed do the trick. I now get the http-reponse straight away. Thanks a lot for your help!
Cheers, Sake
PS I reread your initial reply about tcp:collect and realise I misunderstood you. I thought you meant reading out the http-response-data (by tcp-collect) instead of http-resonse-header. Sorry for that... - Julio_Kato_4411
Nimbostratus
Hi,
This bug is return in version 9.2.3 !!!! I have applies workaround in my bigip.... ..
[]´s
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects