OLD | NEW |
(Empty) | |
| 1 import sys |
| 2 import cherrypy |
| 3 from cherrypy._cpcompat import basestring, ntou, json, json_encode, json_decode |
| 4 |
| 5 def json_processor(entity): |
| 6 """Read application/json data into request.json.""" |
| 7 if not entity.headers.get(ntou("Content-Length"), ntou("")): |
| 8 raise cherrypy.HTTPError(411) |
| 9 |
| 10 body = entity.fp.read() |
| 11 try: |
| 12 cherrypy.serving.request.json = json_decode(body.decode('utf-8')) |
| 13 except ValueError: |
| 14 raise cherrypy.HTTPError(400, 'Invalid JSON document') |
| 15 |
| 16 def json_in(content_type=[ntou('application/json'), ntou('text/javascript')], |
| 17 force=True, debug=False, processor = json_processor): |
| 18 """Add a processor to parse JSON request entities: |
| 19 The default processor places the parsed data into request.json. |
| 20 |
| 21 Incoming request entities which match the given content_type(s) will |
| 22 be deserialized from JSON to the Python equivalent, and the result |
| 23 stored at cherrypy.request.json. The 'content_type' argument may |
| 24 be a Content-Type string or a list of allowable Content-Type strings. |
| 25 |
| 26 If the 'force' argument is True (the default), then entities of other |
| 27 content types will not be allowed; "415 Unsupported Media Type" is |
| 28 raised instead. |
| 29 |
| 30 Supply your own processor to use a custom decoder, or to handle the parsed |
| 31 data differently. The processor can be configured via |
| 32 tools.json_in.processor or via the decorator method. |
| 33 |
| 34 Note that the deserializer requires the client send a Content-Length |
| 35 request header, or it will raise "411 Length Required". If for any |
| 36 other reason the request entity cannot be deserialized from JSON, |
| 37 it will raise "400 Bad Request: Invalid JSON document". |
| 38 |
| 39 You must be using Python 2.6 or greater, or have the 'simplejson' |
| 40 package importable; otherwise, ValueError is raised during processing. |
| 41 """ |
| 42 request = cherrypy.serving.request |
| 43 if isinstance(content_type, basestring): |
| 44 content_type = [content_type] |
| 45 |
| 46 if force: |
| 47 if debug: |
| 48 cherrypy.log('Removing body processors %s' % |
| 49 repr(request.body.processors.keys()), 'TOOLS.JSON_IN') |
| 50 request.body.processors.clear() |
| 51 request.body.default_proc = cherrypy.HTTPError( |
| 52 415, 'Expected an entity of content type %s' % |
| 53 ', '.join(content_type)) |
| 54 |
| 55 for ct in content_type: |
| 56 if debug: |
| 57 cherrypy.log('Adding body processor for %s' % ct, 'TOOLS.JSON_IN') |
| 58 request.body.processors[ct] = processor |
| 59 |
| 60 def json_handler(*args, **kwargs): |
| 61 value = cherrypy.serving.request._json_inner_handler(*args, **kwargs) |
| 62 return json_encode(value) |
| 63 |
| 64 def json_out(content_type='application/json', debug=False, handler=json_handler)
: |
| 65 """Wrap request.handler to serialize its output to JSON. Sets Content-Type. |
| 66 |
| 67 If the given content_type is None, the Content-Type response header |
| 68 is not set. |
| 69 |
| 70 Provide your own handler to use a custom encoder. For example |
| 71 cherrypy.config['tools.json_out.handler'] = <function>, or |
| 72 @json_out(handler=function). |
| 73 |
| 74 You must be using Python 2.6 or greater, or have the 'simplejson' |
| 75 package importable; otherwise, ValueError is raised during processing. |
| 76 """ |
| 77 request = cherrypy.serving.request |
| 78 if debug: |
| 79 cherrypy.log('Replacing %s with JSON handler' % request.handler, |
| 80 'TOOLS.JSON_OUT') |
| 81 request._json_inner_handler = request.handler |
| 82 request.handler = handler |
| 83 if content_type is not None: |
| 84 if debug: |
| 85 cherrypy.log('Setting Content-Type to %s' % content_type, 'TOOLS.JSO
N_OUT') |
| 86 cherrypy.serving.response.headers['Content-Type'] = content_type |
| 87 |
OLD | NEW |