[Web-SIG] Request and Response objects

Ian Bicking ianb at colorstudy.com
Wed Nov 5 12:08:44 EST 2003


On Nov 5, 2003, at 10:34 AM, Gregory (Grisha) Trubetskoy wrote:
> On Wed, 5 Nov 2003, Stuart Bishop wrote:
>> The "response"-type class is the interesting bit - the API for setting
>> status codes, headers, cookies etc. And you do want multiples, of
>> which only one is sent to the client. In particular, if you catch an
>> exception and are preparing an error message you will want a clean
>> response to work with rather than, for example, accidently sending
>> your error message with the wrong content-type. The alternative would
>> be a reset() method on the response buffer, although this isn't as
>> flexible.
>>
>> def handler(request):
>> 	try:
>> 		response = Reponse(request)
>> 		filename = response.request.getFirst('filename')
>> 		response.headers['Content-Type'] = 'image/jpeg'
>> 		response.cookies['latest'] = filename
>> 		response.write(open(filename,'rb').read()) # A filelike object
>> 	except IOError:
>> 		response = Response(request)
>> 		response.status = 404
>> 		print >> response, 'File not found'
>> 	response.close() # No more data - compute content-length header
>> 	response.send() # Send to client.
>
>
> The functional equivalent of the above would look like this in 
> mod_python.
>
> def handler(req):
>
> 	req.content_type = 'image/jpeg'
>
> 	try:
> 		req.sendfile(req.filename)
> 	except IOError:
> 		return apache.HTTP_NOT_FOUND
>
> 	return apache.OK
>
>
> 1. This is a pretty good example of the fact that dual objects don't do
> much other than introduce extra typing.

Dual objects avoid something like "req.content_type = 'image/jpeg'", 
which is not just a misnomer, but confusing and ambiguous, because both 
request and response have a content type.

> 2. This is too low level of an example:
>
> The specifics of how an HTTP error is handled are going to vary from
> server to server - e.g. Apache httpd will furnish it's own error text.
> (BTW, HTTP errors shouldn't happen if your application is written 
> well.)

Of course applications should return errors.  404 is common, 401 and 
403 are entirely reasonable, and 400 is a reasonable way to respond to 
unexpected input; 30x errors are obviously okay, and fit into an 
overall framework of exceptions.  And WebDAV servers have to set the 
error response very specifically, including the body of the response.

A boilerplate message is fine when nothing else is specified, but there 
should exist the possibility of setting the message in your 
application.

> Response.close() and response.send() also assume too much control over 
> the
> server. Unless we abstract completely by providing our own buffering
> (which would do little other than introduce inefficiency), the 
> buffering
> is handled by the server, and whether and when content-length is set
> depends on encoding used (chunked doesn't need content-length), which 
> is
> something also best left for the server to decide.

Some sort of buffering is probably necessary if we want to be able to 
add headers after some of the body has been created.  This is a common 
practice.  Raising an exception in the middle of creating the body 
should also be handled gracefully.  I think it's okay to make an 
exception when someone explicitly says they want to stream the 
response, but for most pages it doesn't matter.

> Whatever we come up with needs to be at a higher level.
>
> having flush() would be appropriate I think.
>
> sendfile() is another nice thing to have - if the environment has a
> native implementation (e.g. mod_python), then it could be used, 
> otherwise
> it'd just be req.write(open(file)read())

Yes, that's a good idea to have.

--
Ian Bicking | ianb at colorstudy.com | http://blog.ianbicking.org




More information about the Web-SIG mailing list