Hello,
I have a client sending chunked requests and configured mod_wsgi to be
in daemon mode.
The request looks like this
POST adsf HTTP/1.1
Host: adsf:adsf
SOAPAction: ""
User-Agent: AAAAAAAAAAAAAAA/4.34
Accept: */*
Content-Type: text/xml
Transfer-Encoding: chunked
56d
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="
http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="
http://schemas.xmlsoap.org/soap/encoding/"
xmlns:cwmp="urn:dslforum-org:cwmp-1-0"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="
http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Header>
<cwmp:ID SOAP-ENV:mustUnderstand="1">100</cwmp:ID>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<cwmp:Inform>
<DeviceId>
<Manufacturer>AAAAA</Manufacturer>
<OUI>AAAAAA</OUI>
<ProductClass>AAAAAAAAAAAA</ProductClass>
<SerialNumber>AAAAAAAAAAAA</SerialNumber>
</DeviceId>
<Event SOAP-ENC:arrayType="cwmp:EventStruct[2]">
<EventStruct>
<EventCode>0 BOOTSTRAP</EventCode>
<CommandKey></CommandKey>
</EventStruct>
<EventStruct>
<EventCode>4 VALUE CHANGE</EventCode>
<CommandKey></CommandKey>
</EventStruct>
</Event>
<MaxEnvelopes>1</MaxEnvelopes>
<CurrentTime>2012-04-26T14:02:37</CurrentTime>
<RetryCount>1</RetryCount>
<ParameterList SOAP-ENC:arrayType="cwmp:ParameterValueStruct[8]">
<ParameterValueStruct>
<Name>InternetGatewayDevice.DeviceSummary</Name>
<Value xsi:type="xsd:string">InternetGatewayDevice:1.4[](Baseline:
1, EthernetLAN:1, WiFiLAN:1, EthernetWAN:1, ADSLWAN:1, IPPing:1,
DSLDiagnostics:1, Time:1), VoiceService:1.0[1](Endpoint:1, SIPEndpoin
573
t:1)</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.DeviceInfo.SpecVersion</Name>
<Value xsi:type="xsd:string">1.0</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.DeviceInfo.HardwareVersion</Name>
<Value xsi:type="xsd:string">AAAAAAAAAAAA</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.DeviceInfo.SoftwareVersion</Name>
<Value xsi:type="xsd:string">AAAAAAAAAAAAAAAAAAAAAAA</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.DeviceInfo.ProvisioningCode</Name>
<Value xsi:type="xsd:string"></Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.ManagementServer.ConnectionRequestURL</
Name>
<Value xsi:type="xsd:string">
http://AAAAAAAAAAAAAAAAAA/CWMP/
ConnectionRequest</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.ManagementServer.ParameterKey</Name>
<Value xsi:type="xsd:string"></Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>InternetGatewayDevice.WANDevice.3.WANConnectionDevice.
1.WANPPPConnection.1.ExternalIPAddress</Name>
<Value xsi:type="xsd:string">AAAAAAAAAAAAA</Value>
</ParameterValueStruct>
</ParameterList>
</cwmp:Inform>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
0
From a HTTP/1.1 perspective the request if fine, i checked if the
chunk-sizes are correctly submitted and if all \r\n are correctly
send.
Furthermore I set the WSGIChunkedRequest On.
However if I do a environ['wsgi.input'].read() the following error
message is generated.
[Fri Apr 27 09:09:42 2012] [error] [client 127.0.0.1] Traceback (most
recent call last):
[Fri Apr 27 09:09:42 2012] [error] [client 127.0.0.1] File "/tmp/
wsgi", line 3, in application
[Fri Apr 27 09:09:42 2012] [error] [client 127.0.0.1] print
environ['wsgi.input'].read()
[Fri Apr 27 09:09:42 2012] [error] [client 127.0.0.1] IOError: request
data read error
I search through mod_wsgi.c and apaches modules/http/http_filters.c
and for me it looks like that the HTTP body send to the daemon is
*free* from the chucking information. Which means no annoying (56d\r
\n, 574\r\n and \r\n0\r\n\r\n the end).
Inside the daemon the 'ap_http_filter' is added again to the input-
chain and then called by ap_get_client_block when the application
needs data. However in this scenario 'ap_http_filter' inside the
daemon process has *no* Content-Length header (obvious because it is
chunking) and *no* chunking information inside the body itself, like
the trailing '0'
'ap_http_filter' has no chance and returns APR_EOF to
ap_get_client_block. ap_get_client_block interprets APR_EOF as an
error and returns -1 which is converted by mod_wsgi.c to the exception
above.
Right now I see this solutions
1) Don't solve this at mod_wsgi level and write a separate
apache_module which does the 'dechunking of its own'. This module
reads the *whole* request at once (similar to mod_request in
apache2.4) then it can calculate the body size and replaces the
'Transfer-Encoding' header with a Content-Length.
2) Do it like above but integrate the code it to mod_wsgi itself. This
code runs then before the request is send to the daemon.
3) Don't run ap_http_filter at all inside the daemon. I mean
'ap_http_filter' runs already in the process which accepts the
request. So why execute it a second time in the daemon itself? To be
more precise this line from 2007 makes me wondering
'ap_add_input_filter("HTTP_IN", NULL, r, r->connection);'
I disabled this line just for fun and then it works, because the only
filter called now is 'ap_core_input_filter' which return APR_SUCCESS
if no more data is coming.
On the other side I can image that there is a use case why this line
makes sense, I don't simply see it.
If there is a good reason not do option three I have no problem with
the other ones, because the requests our application expects will not
blow up memory.
Regards,
Stephan