正在向cherrypy发送JSON字符串

Sending JSON string to cherrypy

本文关键字:JSON 字符串 发送 cherrypy      更新时间:2023-09-26

我正试图通过Javascript将一个JSON字符串从一个HTML(该文件不由cherrypy提供(文件发送到cherrpy服务器。

这是我的最小cherrypy示例(遵循"处理json"部分(

import cherrypy
class HelloJson(object):
    @cherrypy.expose
    @cherrypy.tools.json_in()
    def default(self):
        data = cherrypy.request.json
        print(data)
        return "Hello world!"
if __name__ == '__main__':
    cherrypy.config.update({'server.socket_port':1234})
    cherrypy.quickstart(HelloJson())

通过python发送JSON字符串的效果很好

>>> requests.post('http://localhost:1234', json=json.dumps({'Hello': 'Json'}))
<Response [200]>
>>> 

cherrypy输出也打印json字符串

20:59 $ ./HelloJson.py 
[24/Aug/2015:20:59:34] ENGINE Listening for SIGTERM.
[24/Aug/2015:20:59:34] ENGINE Listening for SIGUSR1.
[24/Aug/2015:20:59:34] ENGINE Listening for SIGHUP.
[24/Aug/2015:20:59:34] ENGINE Bus STARTING
CherryPy Checker:
The Application mounted at '' has an empty config.
[24/Aug/2015:20:59:34] ENGINE Started monitor thread '_TimeoutMonitor'.
[24/Aug/2015:20:59:34] ENGINE Started monitor thread 'Autoreloader'.
[24/Aug/2015:20:59:34] ENGINE Serving on http://127.0.0.1:1234
[24/Aug/2015:20:59:34] ENGINE Bus STARTED
{"Hello": "Json"}
127.0.0.1 - - [24/Aug/2015:21:00:17] "POST / HTTP/1.1" 200 12 "" "python-requests/2.7.0 CPython/3.4.3 Linux/4.1.5-1-ARCH"

所以我的单个HTML文件看起来像这个

<html>
<head>
<script>
function makeRequest()
{
    var insertJSON = { "my_key": "my_value" };
    var xmlhttp = new XMLHttpRequest();   // new HttpRequest instance 
    xmlhttp.open("POST", "http://localhost:1234");
    xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    xmlhttp.send(JSON.stringify(insertJSON));
}
</script>
</head>
<body>
<form name="frm1" id="yourTextBox" onsubmit="makeRequest()">
<input type="submit" value="Submit">
</form>
</body>
</html>

但这会导致错误AttributeError: 'Request' object has no attribute 'json'

[24/Aug/2015:21:10:36] HTTP 
Request Headers:
  CONNECTION: keep-alive
  ACCEPT-LANGUAGE: en-US,en;q=0.5
  ACCESS-CONTROL-REQUEST-HEADERS: content-type
  ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  USER-AGENT: Mozilla/5.0 (X11; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0
  ACCESS-CONTROL-REQUEST-METHOD: POST
  ACCEPT-ENCODING: gzip, deflate
  PRAGMA: no-cache
  CACHE-CONTROL: no-cache
  HOST: localhost:1234
  Remote-Addr: 127.0.0.1
  ORIGIN: null
[24/Aug/2015:21:10:36] HTTP Traceback (most recent call last):
  File "/usr/lib/python3.4/site-packages/cherrypy/_cprequest.py", line 670, in respond
    response.body = self.handler()
  File "/usr/lib/python3.4/site-packages/cherrypy/lib/encoding.py", line 217, in __call__
    self.body = self.oldhandler(*args, **kwargs)
  File "/usr/lib/python3.4/site-packages/cherrypy/_cpdispatch.py", line 61, in __call__
    return self.callable(*self.args, **self.kwargs)
  File "./HelloJson.py", line 15, in default
    data = cherrypy.request.json
  File "/usr/lib/python3.4/site-packages/cherrypy/__init__.py", line 224, in __getattr__
    return getattr(child, name)
AttributeError: 'Request' object has no attribute 'json'
127.0.0.1 - - [24/Aug/2015:21:10:36] "OPTIONS / HTTP/1.1" 500 1515 "" "Mozilla/5.0 (X11; Linux x86_64; rv:40.0) Gecko/20100101 Firefox/40.0"

我不知道我做错了什么。

您看到的OPTIONS请求是CORS飞行前请求,它显然不是JSON请求,您会看到错误。因为您从file://协议(或其他主机(打开文件,并且CherryPyhttp://127.0.0.1:1234上提供服务,所以您会执行跨域请求,该请求受同源策略的约束。

解决这一问题的最简单方法是还通过CherryPy(静态内容服务(提供HTML文件。困难的方法是提供适当的CORS头以允许跨域请求(请参阅此答案(

我同意saaj的回应,即浏览器发送CORS飞行前请求,可以通过以下方式处理:

import cherrypy
class HelloJson(object):
    @cherrypy.expose
    @cherrypy.tools.json_in()
    def POST(self):
        data = cherrypy.request.json
        print(data)
        return "Hello world!"
    def OPTIONS(self):
        cherrypy.response.headers["Access-Control-Allow-Methods"] = "POST, OPTIONS"
        cherrypy.response.headers["Access-Control-Allow-Credentials"] = "true"
        cherrypy.response.headers["Access-Control-Max-Age"] = "86400"
        cherrypy.response.headers[
            "Access-Control-Allow-Headers"] = "X-Mobile, Authorization, Origin, X-Requested-With, Content-Type, Accept"
        cherrypy.response.headers["Content-Type"] = "application/json; charset=utf-8"
        return ''

if __name__ == '__main__':
    cherrypy.config.update({
            'server.socket_port':1234, 
            'request.dispatch': cherrypy.dispatch.MethodDispatcher()
    })
    cherrypy.quickstart(HelloJson(), '/')

这将起作用,因为现在您已经启用API后端来侦听浏览器的OPTIONS调用,该调用告诉浏览器允许的方法和来源是什么。cherrypy.dispatch.MethodDispatcher()使您能够将类视为方法分配器,因此您可以使用该类为RESTFUL API提供服务。