发送 JSON 字符串到 cherrypy
Sending JSON string to cherrypy
我正在尝试通过 Javascript 从单个 HTML(此文件不由 cherrypy 提供服务)文件发送 JSON 字符串到 cherrpy 服务器。
这是我的最小 cherrypy 示例 (followed the "dealing with json" part)
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 preflight request, which obviously isn't a JSON request and you see the error. Because you open your file from file://
protocol (or another host), and CherryPy is serving on http://127.0.0.1:1234
you do a cross-domain request, which is subject to Same-Origin Policy。
解决此问题的最简单方法是同时通过 CherryPy (Static content serving). The hard way is to provide proper CORS headers to allow cross domain requests (see )
提供 HTML 文件
我同意 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()
使您能够将 class 视为方法调度程序,因此您可以使用 class 服务 RESTFUL API.
我正在尝试通过 Javascript 从单个 HTML(此文件不由 cherrypy 提供服务)文件发送 JSON 字符串到 cherrpy 服务器。
这是我的最小 cherrypy 示例 (followed the "dealing with json" part)
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 preflight request, which obviously isn't a JSON request and you see the error. Because you open your file from file://
protocol (or another host), and CherryPy is serving on http://127.0.0.1:1234
you do a cross-domain request, which is subject to Same-Origin Policy。
解决此问题的最简单方法是同时通过 CherryPy (Static content serving). The hard way is to provide proper CORS headers to allow cross domain requests (see
我同意 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()
使您能够将 class 视为方法调度程序,因此您可以使用 class 服务 RESTFUL API.