7

I have a mod_include (SSI) page that is generating erronous output during chunked encoding when requested by a HTTP/1.1 browser.

The page is output fine when requested by a HTTP/1.0 (because the output is not chunked).

How can I tell Apache not to use chunked encoding when requested by a HTTP/1.1 browser?

More info: The erronous chunked output is caused by having sendfile() support enabled on a Solaris 5.10 machine with a sparc processor. Disabling sendfile() support causes this problem to disappear; however I am trying to catch this bug and fix it.

1
  • 2
    It turned out I was using an old Solaris kernel with a known buggy version of sendfile() which would report fewer bytes transmitted than actually put on the wire.
    – PP.
    Jun 30, 2010 at 8:48

5 Answers 5

10

If you pre-specify Content-length, Apache won't have to use chunked. Without Content-length, Apache has no option but to use it.

To be clear: HTTP/1.0 manages it because Apache reads in the entire response before sending it along, so it know how large it'll be. This is hilariously inefficient, and slow, and AFAIK there's no way to enable this logic for HTTP/1.1 requests, except by forcing them to HTTP/1.0 (which you really, really don't want to do, do you? If you do, the environment variable to set is "downgrade-1.0")

1
  • I believe that it is impossible to force Apache to read in the entire response before sending using HTTP/1.1. However I appreciate this answer to the question so have accepted it as the answer.
    – PP.
    Jun 30, 2010 at 8:48
12

The above answer is incorrect.

If request is HTTP/1.0, Apache never buffers the response before sending it (with Content-Length header). Of course Apache could do that, but there is more elegant solution that Apache uses: it responds with "Connection: close" header and closes connection as soon as it sends all the data.

According to HTTP spec, the presence of "Connection: close" header means the client needs to read till connection is closed.

The solution to your problem is to force Apache treat the request as HTTP/1.0 by setting the mentioned downgrade-1.0 environment variable. The chunked Transfer-Encoding is a HTTP/1.1 feature, and Apache won't use it for HTTP/1.0 request.

E.g. here is how you could disable chunked responses for php files:

++++++++++++
apache.conf
++++++++++++

<Files *.php>
    SetEnv downgrade-1.0
</Files>
3
  • 2
    Would this result in the webserver responding with a HTTP/1.0 response or a HTTP/1.1 response but without HTTP/1.1 features?
    – PP.
    Jul 21, 2011 at 14:05
  • @PP Apache still responds with HTTP/1.1 (tested on 2.2.29)
    – pumbo
    Aug 15, 2018 at 11:33
  • You're absolutely right, of course. Leaving my answer as-is so yours continues to make sense, but subsequent readers should please ignore what I said about Content-Length in Apache under HTTP/1.0 in my answer.
    – BMDan
    Dec 18, 2019 at 21:18
0

Apache client will try to determine the size of the body being sent. Pre-0specifying "Content-Length" will cause an error unless you use special interceptors.

It checks the entity it will be sending to identify if it is chunked or if the size of the body (content-length) < 0 and if either are true then it uses the "Transfer-Encoding=chunked" header. If the entity does not prefer chunking and a content length > -1 is found then it uses "Content-Length" header.

Typically if the source of the body is a mime body part it will use "Transfer-Encoding" because a call to the size() method returns -1 so converting the mime body part to a byte array would work since it will return the number of bytes in the array.

0

I had similar issues. I solved the problem by removing the Transfer-encoding header from the response, directly in the application.

0

I usually let research pave the way, but with mixed answers and nothing working, I decided to start playing around. After a few hours, I've come up with setting these two headers:

Content-Length: 0
Content-Type: application/octet-stream

If you do this, Apache will not add the Transfer-Encoding header at all. I've added screenshots of TCP payload data being transferred and the headers to prove that setting the length to zero will not affect the return. Note, possibly to future self, that I'm using WebSocket encoded messages (binary content) being sent back over HTTP Upgrade directly with Apache's default resolution (currently index.php). Wireshark will ultimately show these messages in readable text. Specifically, data frames are what the encoding handles and they do not obfuscate the text. From a WebSocket perspective, this is only true if all three custom masks have been set to zero.? The mask bits are not typically set.

Headers sent with Apache Version 2.4.58 Data is transferred proof

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .