Chr*_*ris 5 python ajax cherrypy cross-domain
我正在尝试构建Cherrypy / Python Web服务。我已经花费了一整天的时间来研究如何使跨域Ajax请求成为可能。终于可以了,但是现在我有下一个问题。我想我已经知道了解决方案,但是我不知道如何实现。问题是,当我发送ajax请求时,Cherrypy服务器将响应:
415 Unsupported Media Type
Expected an entity of content type application/json, text/javascript
Traceback (most recent call last): File "/Library/Python/2.7/site-packages/cherrypy/_cprequest.py", line 663, in respond self.body.process() File "/Library/Python/2.7/site-packages/cherrypy/_cpreqbody.py", line 996, in process super(RequestBody, self).process() File "/Library/Python/2.7/site-packages/cherrypy/_cpreqbody.py", line 538, in process self.default_proc() File "/Library/Python/2.7/site-packages/cherrypy/_cperror.py", line 411, in __call__ raise selfHTTPError: (415, u'Expected an entity of content type application/json, text/javascript')
Run Code Online (Sandbox Code Playgroud)
我找到并尝试测试的解决方案是将以下行添加到配置中:
'tools.json_in.force': False
Run Code Online (Sandbox Code Playgroud)
所以我尝试在以下代码中实现它:
import cherrypy
import json
import sys
class RelatedDocuments:
def index(self):
return "Hello World!"
@cherrypy.tools.json_out()
@cherrypy.tools.json_in()
def findRelated(self, **raw):
#Get JSON message form request
request = cherrypy.request.json
result = []
#SOME CODE...
return result;
# Expose the index method through the web. CherryPy will never
# publish methods that don't have the exposed attribute set to True.
index.exposed = True
findRelated.exposed = True
def CORS():
cherrypy.response.headers["Access-Control-Allow-Origin"] = "*"
import os.path
tutconf = os.path.join(os.path.dirname(__file__), 'webserver.conf')
config = {
'global': {
'server.socket_host':'127.0.0.1',
'server.socket_port': 8080,
'log.error_file' : 'Web.log',
'log.access_file' : 'Access.log'
},
'/': {
'tools.CORS.on': True
}
}
if __name__ == '__main__':
cherrypy.tools.CORS = cherrypy.Tool('before_finalize', CORS)
cherrypy.quickstart(RelatedDocuments(),config=config)
Run Code Online (Sandbox Code Playgroud)
我在tools.CORS.on行下添加了config行,但这没有用。接下来我尝试了这个:
cherrypy.config.update({
'tools.json_in.force': False,
});
Run Code Online (Sandbox Code Playgroud)
没成功。.next我试图在findRelated方法上方实现此功能:
@cherrypy.config(**{'tools.json_in.force': False})
Run Code Online (Sandbox Code Playgroud)
所有的实现给我一个500错误,如果有人可以帮助我,我非常感谢。提前致谢!
我意识到问题实际上是关于CORS 预检请求。CORS规范为简单的 CORS 请求定义了以下条件:
GET,HEAD,POSTAccept, Accept-Language, Content-Language,Content-Typeapplication/x-www-form-urlencoded, multipart/form-data,text/plain否则 CORS 请求并不简单,请在实际请求之前使用预检 OPTIONS 请求以确保其符合条件。这是很好的 CORS 操作方法。
因此,如果您想让事情变得简单,您可能需要恢复正常application/x-www-form-urlencoded。否则,您需要正确处理预检请求。这是工作示例(不要忘记添加localhost别名)。
#!/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
}
}
def cors():
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 handler
return True
else:
cherrypy.response.headers['Access-Control-Allow-Origin'] = '*'
cherrypy.tools.cors = cherrypy._cptools.HandlerTool(cors)
class App:
@cherrypy.expose
def index(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()
def endpoint(self):
data = cherrypy.request.json
return data.items()
if __name__ == '__main__':
cherrypy.quickstart(App(), '/', config)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2268 次 |
| 最近记录: |