middleware to monitor python wsgi applications
I’m working on some RESTful python wsgi application. For debugging and monitoring I needed a way to see the request and response HTTP header without modifying the actual code.
So I posted the question to stackoverflow where Florian Boenisch came up with a nice solution.
from wsgiref.util import request_uri
import sys
def logging_middleware(application, stream=sys.stdout):
def _logger(environ, start_response):
stream.write('REQUEST\n')
stream.write('%s %s\n' %(
environ['REQUEST_METHOD'],
request_uri(environ),
))
for name, value in sorted(environ.items()):
if name.startswith('HTTP_'):
stream.write(' %s: %s\n' %(
name[5:].title().replace('_', '-'),
value,
))
stream.flush()
def _start_response(code, headers):
stream.write('RESPONSE\n')
stream.write('%s\n' % code)
for data in sorted(headers):
stream.write(' %s: %s\n' % data)
stream.flush()
start_response(code, headers)
return application(environ, _start_response)
return _logger
def application(environ, start_response):
start_response('200 OK', [
('Content-Type', 'text/html')
])
return ['Hello World']
if __name__ == '__main__':
logger = logging_middleware(application)
from wsgiref.simple_server import make_server
httpd = make_server('', 1234, logger)
httpd.serve_forever()
This middelware is is a example of accessing the response from the wrapped middleware.
The output will be something like this:
REQUEST
PUT http://localhost:5000/testdb/1
Accept-Encoding: identity
Host: localhost:5000
User-Agent: Python-httplib2/$Rev: 196 $
RESPONSE
201 CREATED
content-type: application/json
['{"rev": "1222169702", "ok": true, "id": "1"}']
REQUEST
GET http://localhost:5000/_all_dbs
Accept-Encoding: compress, gzip
Host: localhost:5000
User-Agent: Python-httplib2/$Rev: 196 $
RESPONSE
200 OK
Content-Type: text/plain; charset=utf-8
['["testdb"]']
REQUEST
DELETE http://localhost:5000/testdb
Accept-Encoding: identity
Host: localhost:5000
User-Agent: Python-httplib2/$Rev: 196 $
RESPONSE
200 OK
Content-Type: text/plain; charset=utf-8
['{"ok":true}']