WSGI: what's the purpose of start_response function

Boris Burkov picture Boris Burkov · May 27, 2013 · Viewed 9.4k times · Source

Could you supply a real-life example of WSGI start_response function? (Web-server provides that function to wsgi application)

I can't understand the purpose of introducing the start_response.

(I've read like 10 identical texts about the WSGI standard. They all say "WSGI standard is..." None of them says "WSGI is designed this way in order to..." :()

Answer

Aya picture Aya · May 27, 2013

Could you supply a real-life example of WSGI start_response() function?

Well, the start_response() function for mod_wsgi is defined on line 2678 of mod_wgsi.c

None of them says "WSGI is designed this way in order to..."

There doesn't seem to be much rationale for this aspect of WSGI's design in PEP3333. Looking through the web-sig mailing list archives, I came across this message...

Some time ago I objected the decision to remove start_response function from next version WSGI, using as rationale the fact that without start_callable, asynchronous extension are impossible to support.

Now I have found that removing start_response will also make impossible to support coroutines (or, at least, some coroutines usage).

[...]

...which started a long thread about the rationale for this part of the implementation which might be worth a read.

If you really want to know the origins of this aspect of the WSGI interface, you'll have to read a lot of the messages between this initial draft in December 2003, and this later draft in August 2004.


Update

How would that be compatible with that other protocol?

I'm not quite sure what you mean. Ignoring all the early drafts, the WSGI 1.x interface can be used in two different ways.

The 'deprecated' method is...

def application(environ, start_response):
    write = start_response(status, headers)
    write('content block 1')
    write('content block 2')
    write('content block 3')
    return None

...and the 'recommended' method is...

def application(environ, start_response):
    start_response(status, headers)
    return ['content block 1',
            'content block 2',
            'content block 3']

Presumably, you could use both, with...

def application(environ, start_response):
    write = start_response(status, headers)
    write('content block 1')
    return ['content block 2',
            'content block 3']

...but the resulting behavior may be undefined.

By the looks of this blog post, the new WSGI 2.x method being considered is...

def application(environ):
    return (status,
            headers,
            ['content block 1',
             'content block 2',
             'content block 3'])

...which eliminates the start_response() callable, and, obviously, the write() callable, but there's no indication as to when (or even if) this is likely to supercede WSGI 1.x.