1import simplejson 2import cgi 3 4class JSONFilter(object): 5 def __init__(self, app, mime_type='text/x-json'): 6 self.app = app 7 self.mime_type = mime_type 8 9 def __call__(self, environ, start_response): 10 # Read JSON POST input to jsonfilter.json if matching mime type 11 response = {'status': '200 OK', 'headers': []} 12 def json_start_response(status, headers): 13 response['status'] = status 14 response['headers'].extend(headers) 15 environ['jsonfilter.mime_type'] = self.mime_type 16 if environ.get('REQUEST_METHOD', '') == 'POST': 17 if environ.get('CONTENT_TYPE', '') == self.mime_type: 18 args = [_ for _ in [environ.get('CONTENT_LENGTH')] if _] 19 data = environ['wsgi.input'].read(*map(int, args)) 20 environ['jsonfilter.json'] = simplejson.loads(data) 21 res = simplejson.dumps(self.app(environ, json_start_response)) 22 jsonp = cgi.parse_qs(environ.get('QUERY_STRING', '')).get('jsonp') 23 if jsonp: 24 content_type = 'text/javascript' 25 res = ''.join(jsonp + ['(', res, ')']) 26 elif 'Opera' in environ.get('HTTP_USER_AGENT', ''): 27 # Opera has bunk XMLHttpRequest support for most mime types 28 content_type = 'text/plain' 29 else: 30 content_type = self.mime_type 31 headers = [ 32 ('Content-type', content_type), 33 ('Content-length', len(res)), 34 ] 35 headers.extend(response['headers']) 36 start_response(response['status'], headers) 37 return [res] 38 39def factory(app, global_conf, **kw): 40 return JSONFilter(app, **kw) 41