415 Exception Cherrypy Webservice
Solution 1:
I've realised that the question is in fact about CORS preflight request. CORS specification defines the following condition for a simple CORS request:
- Method:
GET,HEAD,POST - Headers:
Accept,Accept-Language,Content-Language,Content-Type - Cotent-type header value:
application/x-www-form-urlencoded,multipart/form-data,text/plain
Otherwise CORS request isn't simple, and use preflight OPTIONS request before actual request to ensure it's eligible. Here is good CORS how-to.
So if you want to keep things simple you may want to revert to normal application/x-www-form-urlencoded. Otherwise you need to handle preflight requests correctly. Here's working example (don't forget to add localhost alias).
#!/usr/bin/env python# -*- coding: utf-8 -*-'''
Add localhost alias, `proxy` , in /etc/hosts.
'''
import cherrypy
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 8
}
}
defcors():
if cherrypy.request.method == 'OPTIONS':
# preflign request # see http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
cherrypy.response.headers['Access-Control-Allow-Methods'] = 'POST'
cherrypy.response.headers['Access-Control-Allow-Headers'] = 'content-type'
cherrypy.response.headers['Access-Control-Allow-Origin'] = '*'# tell CherryPy no avoid normal handlerreturn True
else:
cherrypy.response.headers['Access-Control-Allow-Origin'] = '*'
cherrypy.tools.cors = cherrypy._cptools.HandlerTool(cors)
classApp:@cherrypy.expose
defindex(self):
return'''<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=utf-8' http-equiv='content-type'>
<title>CORS AJAX JSON request</title>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js'></script>
<script type='text/javascript'>
$(document).ready(function()
{
$('button').on('click', function()
{
$.ajax({
'type' : 'POST',
'dataType' : 'JSON',
'contentType' : 'application/json',
'url' : 'http://proxy:8080/endpoint',
'data' : JSON.stringify({'foo': 'bar'}),
'success' : function(response)
{
console.log(response);
}
});
})
});
</script>
</head>
<body>
<button>make request</button>
</body>
</html>
'''@cherrypy.expose
@cherrypy.config(**{'tools.cors.on': True})
@cherrypy.tools.json_in()
@cherrypy.tools.json_out()
defendpoint(self):
data = cherrypy.request.json
return data.items()
if __name__ == '__main__':
cherrypy.quickstart(App(), '/', config)
Solution 2:
In general if you have chosen a tool, then you're better using it, instead of fighting it. CherryPy tells you that for JSON input it expects request with application/json or text/javascript content-type.
Here's code of cherrypy.lib.jsontools.json_in:
defjson_in(content_type=[ntou('application/json'), ntou('text/javascript')],
force=True, debug=False, processor=json_processor):
request = cherrypy.serving.request
ifisinstance(content_type, basestring):
content_type = [content_type]
if force:
if debug:
cherrypy.log('Removing body processors %s' %
repr(request.body.processors.keys()), 'TOOLS.JSON_IN')
request.body.processors.clear()
request.body.default_proc = cherrypy.HTTPError(
415, 'Expected an entity of content type %s' %
', '.join(content_type))
for ct in content_type:
if debug:
cherrypy.log('Adding body processor for %s' % ct, 'TOOLS.JSON_IN')
request.body.processors[ct] = processor
force doesn't do anything more than removing existing body processors. If you set force to False, then you need to tell CherryPy how to treat the request body you send to it.
Or, better, use CherryPy and tell it correct content-type. With jQuery it's as simple as:
jQuery.ajax({
'type' : 'POST',
'dataType' : 'JSON',
'contentType' : 'application/json',
'url' : '/findRelated',
'data' : JSON.stringify({'foo': 'bar'})
});
Post a Comment for "415 Exception Cherrypy Webservice"