RFC 2145 says: "An implementation of HTTP/x.b sending a message to a recipient whose version is known to be HTTP/x.a, a < b, MUST NOT depend on the recipient understanding a header not defined in the specification for HTTP/x.a. For example, HTTP/1.0 clients cannot be expected to understand chunked encodings, and so an HTTP/1.1 server must never send "Transfer-Encoding: chunked" in response to an HTTP/1.0 request."
In specific cases, implementations can choose to send some HTTP/1.1 headers to HTTP/1.0 clients, but in the general case, the solution is usually to downgrade the entire HTTP response to 1.0 features only. Under WSGI, "an implementation of HTTP/x.b" is an emergent property of the entire stack; servers, middleware, and applications all share this responsibility to downgrade the entire response to HTTP/1.0 features if any of the other components is not HTTP/1.1 compliant. Unfortunately, the WSGI 1.0 spec doesn't require WSGI servers to tell WSGI applications what version of HTTP they support. If a WSGI origin server "fails to satisfy one or more of the MUST or REQUIRED level requirements for the protocols it implements" (as too many WSGI servers do!), WSGI applications have no standardized way of knowing this, and may output headers which contradict the version number output by the WSGI server. CherryPy hacks around this by having the origin server send a custom entry in the WSGI environ called "ACTUAL_SERVER_PROTOCOL", which tells the rest of the WSGI stack the version for which the origin server is at least conditionally compliant: # Compare request and server HTTP protocol versions, in case our # server does not support the requested protocol. Limit our output # to min(req, server). We want the following output: # request server actual written supported response # protocol protocol response protocol feature set # a 1.0 1.0 1.0 1.0 # b 1.0 1.1 1.1 1.0 # c 1.1 1.0 1.0 1.0 # d 1.1 1.1 1.1 1.1 # Notice that, in (b), the response will be "HTTP/1.1" even though # the client only understands 1.0. RFC 2616 10.5.6 says we should # only return 505 if the _major_ version is different. rp = int(req_protocol[5]), int(req_protocol[7]) sp = int(server.protocol[5]), int(server.protocol[7]) if sp[0] != rp[0]: self.simple_response("505 HTTP Version Not Supported") return # Bah. "SERVER_PROTOCOL" is actually the REQUEST protocol. environ["SERVER_PROTOCOL"] = req_protocol # set a non-standard environ entry so the WSGI app can know what # the *real* server protocol is (and what features to support). # See http://www.faqs.org/rfcs/rfc2145.html. environ["ACTUAL_SERVER_PROTOCOL"] = server.protocol self.response_protocol = "HTTP/%s.%s" % min(rp, sp) The "application-side" bits of CherryPy inspect this value (if present) and perform the same min(rp, sp) calculation as the server in order to determine which features to support. WSGI 2 should, at the least, add a standard environ entry similar to ACTUAL_SERVER_PROTOCOL. This would provide the minimum enforcement of full-stack compliance, since WSGI origin servers tend to be the least-compliant portions of any WSGI stack. As far as I am aware, the CherryPy 3 wsgiserver is the only one currently claiming to be even "conditionally compliant" with HTTP/1.1. WSGI 2 might, in addition, require WSGI origin servers to perform the min(rp, sp) calculation once and pass the result in a new "RESPONSE_PROTOCOL_SUPPORT" environ entry. Note this is not necessarily the same version number as what will be output in the response Status-Line: "An HTTP server SHOULD send a response version equal to the highest version for which the server is at least conditionally compliant, and whose major version is less than or equal to the one received in the request. An HTTP server MUST NOT send a version for which it is not at least conditionally compliant. A server MAY send a 505 (HTTP Version Not Supported) response if [it] cannot send a response using the major version used in the client's request." If a given WSGI application or middleware component is not at least conditionally compliant with HTTP/1.1, the WSGI origin server should downgrade the response version it emits in the Status-Line, but has no standardized way to be informed of this state of affairs. Currently, the burden tends to fall on those who compose WSGI stacks to manually instruct the WSGI origin server to always output HTTP/1.0 if any WSGI component is not conditionally compliant with HTTP/1.1. This issue may need to be addressed in a separate spec covering the composition of WSGI stacks. Robert Brewer System Architect Amor Ministries [EMAIL PROTECTED] _______________________________________________ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com