[mod_python] HTTP-Keep alive bug?

Sébastien Arnaud arnaudsj at mac.com
Mon Aug 9 21:38:41 EDT 2004


Grisha,

Thank you for your enlightenment in those dark areas of my assumptions 
(oh man, let's say it, I was wrong on the whole HTTP 1.1 thing ;)

Here are 2 simple tests that hopefully will speak for themselves better 
than I can explain it. I ran with apache bench (2.40) against one 
simple test page rendered by mod_python.

############# BEGIN: FIRST TEST ##############
ab -v 3 -n 1 -k http://localhost/test/index.py
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.121.2.10 $> 
apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, 
http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, 
http://www.apache.org/

Benchmarking localhost (be patient)...INFO: POST header ==
---
GET /test/index.py HTTP/1.0
User-Agent: ApacheBench/2.0.40-dev
Connection: Keep-Alive
Host: localhost
Accept: */*


---
LOG: header received:
HTTP/1.1 200 OK
Date: Tue, 10 Aug 2004 01:19:55 GMT
Server: Apache
Cache-Control: no-cache="set-cookie"
Set-Cookie: testcookie=testvalue2; expires=Tue, 10-Aug-2004 01:24:56 GMT
Connection: close
Content-Type: text/html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test XSLT View</title>
</head>
<body><p>The message is: <span></span></p></body>
</html>

LOG: Response code = 200
..done


Server Software:        Apache
Server Hostname:        localhost
Server Port:            80

Document Path:          /test/index.py
Document Length:        178 bytes

Concurrency Level:      1
Time taken for tests:   0.17957 seconds
Complete requests:      1
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      406 bytes
HTML transferred:       178 bytes
Requests per second:    55.69 [#/sec] (mean)
Time per request:       17.957 [ms] (mean)
Time per request:       17.957 [ms] (mean, across all concurrent 
requests)
Transfer rate:          0.00 [Kbytes/sec] received

Connection Times (ms)
               min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    17   17   0.0     17      17
Waiting:        8    8   0.0      8       8
Total:         17   17   0.0     17      17
################# END FIRST TEST #####################

Note, the "Connection: close" returned by apache even though ab 
requested a "Connection: Keep-Alive"
Now, the same request, but the simple test.py script is now setting 
req.headers_out['Content-Length']

################ BEGIN SECOND TEST ###################
ab -v 3 -n 1 -k http://localhost/test/index.py
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.121.2.10 $> 
apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, 
http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, 
http://www.apache.org/

Benchmarking localhost (be patient)...INFO: POST header ==
---
GET /test/index.py HTTP/1.0
User-Agent: ApacheBench/2.0.40-dev
Connection: Keep-Alive
Host: localhost
Accept: */*


---
LOG: header received:
HTTP/1.1 200 OK
Date: Tue, 10 Aug 2004 01:19:03 GMT
Server: Apache
Cache-Control: no-cache="set-cookie"
Set-Cookie: testcookie=testvalue2; expires=Tue, 10-Aug-2004 01:24:03 GMT
Content-Length: 178
Keep-Alive: timeout=30, max=1000
Connection: Keep-Alive
Content-Type: text/html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test XSLT View</title>
</head>
<body><p>The message is: <span></span></p></body>
</html>

LOG: Response code = 200
..done


Server Software:        Apache
Server Hostname:        localhost
Server Port:            80

Document Path:          /test/index.py
Document Length:        178 bytes

Concurrency Level:      1
Time taken for tests:   0.282956 seconds
Complete requests:      1
Failed requests:        0
Write errors:           0
Keep-Alive requests:    1
Total transferred:      466 bytes
HTML transferred:       178 bytes
Requests per second:    3.53 [#/sec] (mean)
Time per request:       282.956 [ms] (mean)
Time per request:       282.956 [ms] (mean, across all concurrent 
requests)
Transfer rate:          0.00 [Kbytes/sec] received

Connection Times (ms)
               min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   282  282   0.0    282     282
Waiting:      247  247   0.0    247     247
Total:        282  282   0.0    282     282
#################### END SECOND TEST #############################

Note, that suddenly here Apache replies properly to the keep-alive 
request with the response headers:
"Keep-Alive: timeout=30, max=1000" and "Connection: Keep-Alive". All of 
this because we did set the "content-length" header in the python code.

Anybody, who has a more in depth knowledge of Apache, tempted to solve 
this mystery?

Cheers,

Sébastien


On Aug 9, 2004, at 9:12 AM, Gregory (Grisha) Trubetskoy wrote:

>
>
> On Sun, 8 Aug 2004, [ISO-8859-1] S?bastien Arnaud wrote:
>
>> First, I was wrong when I said mod_python was forcing the HTTP Header 
>> "Connection: Close", it is in fact responding to a client request 
>> http keep-alive, but it is missing an important part: the HTTP header 
>> "Content-Length: xxx"!
>
> If this is HTTP 1.1, then absense of content-length indicates that the 
> browser wants chunked-encoding, which means that the output is a 
> number indicating size, followed by a chunk of data. With HTTP 1.1 
> content-length is obsolete. There is a pretty good description of it 
> here:
>
> http://www.apacheweek.com/features/http11
>
>> Since it is the only way browsers can keep connections alive (to know 
>> how much bytes they need to expect back from the server),
>
> ...not with HTTP 1.1
>
>> without it, most browsers will NOT keep the connection alive (maybe 
>> your version of Firefox is sensitive to this missing header and tries 
>> to wait for more content to come back from the server)
>
> No, this doesn't make a lot of sense. :-) The browser isn't keeping it 
> alive because it is seeing a Connection: close, most likely.
>
>> For the record I got mistaken in my early tests because I used Lynx 
>> to get the HTTP headers back, and found out that Lynx did not send a 
>> valid HTTP 1.1 request with keep-alive (duh!), therefore it was ok to 
>> receive a "Connection: Close" back then.
>>
>> Anyway, I think it would be nice to have an explanation why 
>> mod_python is not setting by default the Content-Length HTTP header 
>> when it is already setting the "Connection: Keep-alive" HTTP header 
>> in response to a keep-alive request from the client.
>
> Mod_python does not set the connection header anywhere in the code, 
> but other code in Apache probably does. In my experience it is very 
> smart about it, so there is more than likely a good reason for it. 
> Something is telling Apache to send a "close"... It could the 
> configuration, some module in Apache, and it could be something that 
> the browser has caused (without seeing the actual headers its hard to 
> tell).
>
> Grisha
> _______________________________________________
> Mod_python mailing list
> Mod_python at modpython.org
> http://mailman.modpython.org/mailman/listinfo/mod_python
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 155 bytes
Desc: This is a digitally signed message part
Url : http://modpython.org/pipermail/mod_python/attachments/20040809/2ec59bcf/PGP.bin


More information about the Mod_python mailing list