V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xuyl
V2EX  ›  Flask

flask-restful 封装接口, ie8/9 下 跨域调用的问题,快被折磨死了。

  •  
  •   xuyl · 2017-10-24 22:01:06 +08:00 · 4159 次点击
    这是一个创建于 2592 天前的主题,其中的信息可能已经有所发展或是发生改变。

    接口逻辑如下

    
    from flask import Flask, request
    from flask_restful import reqparse, abort, Api, Resource
    from flask_cors import CORS
    
    app = Flask(__name__)
    CORS(app)
    api = Api(app)
    
    class Suggest(Resource):
    	#decorators = [check_http_headers, check_request_frequency]
    	def __init__(self):
    		super(SuggestApi, self).__init__()
    		self.parser = reqparse.RequestParser()
    		self.parser.add_argument('name', type=str, required=True, help='name 不能空')
                    self.parser.add_argument('age', type=int, required=True, help='age 不能空')
    		self.args = self.parser.parse_args()
    
    	def post(self):
        	       name = self.args['name']
                   age = self.args['age']
                   return {'name': name, 'age': age}, 200
                   #return request.data.decode('utf-8')
    
    api.add_resource(Suggest, '/api/v1/suggest')
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    前端测试页面如下(因为不支持 cors 跨域, 所以用了 xdomain request)

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Document</title>
    </head>
    <body>
    	<button>发送 post 请求</button>
    	<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    	<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js"></script>
    	<script>
    		$(function() {
    			$('button').on('click',function() {
    				var param = {name:'test', age: 25};
    				if(!$.support.cors) {
    					param = JSON.stringify(param);
    				}
    
    				$.ajax('http://127.0.0.1:5000/api/v1/suggest',{
    					type:'post',
    					dataType:'json',
    					data:param,
    					success:function(resp) {
    						console.log(resp);
    					}
    				})
    			})
    		})
    	</script>
    </body>
    </html>
    

    测试结果

    只要用了参数解析reqparse.RequestParser(),并且required=True, 调用接口就是 400 错误;将required=True去掉,虽然不再 400 错误,但并不能在self.args中获取到参数, 测试参数是在request对象里的data属性里面。

    求助?

    参数解析帮了很大忙,不想因为兼容 ie8 就不用参数解析了,有什么办法能做到让 ie8 兼容呢?

    25 条回复    2019-07-06 13:13:06 +08:00
    0ZXYDDu796nVCFxq
        1
    0ZXYDDu796nVCFxq  
       2017-10-24 22:26:39 +08:00
    nginx+uwsgi 部署,静态和接口同域就可以了

    PS:楼主是 tab 和空格混用的异端……
    zhengjian
        2
    zhengjian  
       2017-10-24 22:31:23 +08:00 via iPhone
    响应头带上 Access-Control-Allow-Origin
    will0404
        3
    will0404  
       2017-10-24 22:35:41 +08:00   ❤️ 1
    我的妈 2017 年了还在兼容 IE8
    xuyl
        4
    xuyl  
    OP
       2017-10-24 23:30:54 +08:00
    @zhengjian 用了 flask_cors 了
    xuyl
        5
    xuyl  
    OP
       2017-10-24 23:31:09 +08:00
    @will0404 政府项目,没办法
    xuyl
        6
    xuyl  
    OP
       2017-10-24 23:32:24 +08:00
    @gstqc 不是部署的问题,部署我用 gunicorn,现在就是要在跨域下做调用,能同域名就不会来这里问了。
    Kilerd
        7
    Kilerd  
       2017-10-25 00:16:27 +08:00 via iPhone
    add_argument 那里添加参数 location,指明从哪里读取数据。
    Kilerd
        8
    Kilerd  
       2017-10-25 00:21:10 +08:00 via iPhone
    楼上的人包括楼主到底知不知道出现跨域问题是有啥症状?
    能出现 400 错,楼上还回复这些东西?

    实在看不下去了
    meszyouh
        9
    meszyouh  
       2017-10-25 00:48:14 +08:00
    开个浏览器吧 , 看下请求 options 请求响应的是啥
    hard2reg
        10
    hard2reg  
       2017-10-25 05:21:18 +08:00
    @xuyl 政府不用什么 360 安全浏览器的吗?那个好像有 chrome 内核
    kaneg
        11
    kaneg  
       2017-10-25 08:09:36 +08:00 via iPhone
    400 bad request, 一般是因为 http 请求的格式不合法,貌似是 http client 的问题
    lgh
        12
    lgh  
       2017-10-25 08:33:58 +08:00 via iPhone
    @Kilerd
    @kaneg
    真相了……

    @xuyl 试试把 self.args = self.parser.parse_args() 移到 post() 方法里去?
    winglight2016
        13
    winglight2016  
       2017-10-25 09:52:32 +08:00
    400 问题,一般是客户端用了 json 或者 form 提交,服务端却仅支持 url 带参数,这种提交数据格式不规范的错误
    可以试一下加入 headers:content-type,另外楼主中断一下服务端看看提交的 request 走到了代码哪个部分?或者把完整的 request 输出一下看看什么问题?
    xuyl
        14
    xuyl  
    OP
       2017-10-25 10:55:10 +08:00
    @Kilerd location=['form', headers', 'values', 'json', 'data', 'args'] 全试过,都一样的 400 错误
    xuyl
        15
    xuyl  
    OP
       2017-10-25 10:55:56 +08:00
    @lgh 试过了,不行,依然 400 错误
    Kilerd
        16
    Kilerd  
       2017-10-25 11:32:47 +08:00 via iPhone
    @xuyl location 写 form,然后 parse_args 放到 post 里面去
    bengle
        17
    bengle  
       2017-10-25 11:49:04 +08:00
    改用 jsonp,是 get 的,只要没有文件上传什么的应该都可以,安全性也差点
    xuyl
        18
    xuyl  
    OP
       2017-10-25 15:45:31 +08:00
    @bengle 用 jsonp 只是解决跨域问题,现在跨域不是问题,是参数解析的问题
    xuyl
        19
    xuyl  
    OP
       2017-10-25 15:48:31 +08:00
    @Kilerd 试过,400 错误依旧,我得出的结论就是 ie8 通过 x domain request(xdr)方式兼容 cors 跨域,参数在 request.data 里面,利用 flask-restful 的参数解析是无法获取到参数的,只能硬解 request.data/request.get_data(), 并且这里获取到的还是 binary。
    vZexc0m
        20
    vZexc0m  
       2017-10-26 09:56:19 +08:00
    我是后端解决的。
    ```
    from flask_cors import CORS

    cors = CORS()

    def create_app(name):
    app = Flask(__name__)
    app.config.from_object(config[name])
    config[name].init_app(app)

    cors.init_app(app, supports_credentials=True)
    ```
    你试试能不能行
    xuyl
        21
    xuyl  
    OP
       2017-10-26 13:49:57 +08:00
    @vZexc0m 你看我主帖里,我也用了 flask_cors,跨域是没问题的,是参数解析的问题。
    vZexc0m
        22
    vZexc0m  
       2017-10-26 15:42:53 +08:00
    @xuyl 试试不用 flask_result,直接用框架看看有没有问题
    xuyl
        23
    xuyl  
    OP
       2017-10-28 21:01:08 +08:00
    @vZexc0m 多谢你的回复,参数在 request.data 里可获取到,但不用 flask-restful,对于规范化接口比较痛苦。
    vZexc0m
        24
    vZexc0m  
       2017-10-30 09:13:48 +08:00
    restful 只是一种规范而已,不插件也可以实现
    ropon
        25
    ropon  
       2019-07-06 13:13:06 +08:00
    请问解决了么? abort 抛出异常,状态码 400 就会出现跨域
    ![]( https://i.bmp.ovh/imgs/2019/07/9ab5c8f3cc91dcae.jpg)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1624 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 17:01 · PVG 01:01 · LAX 09:01 · JFK 12:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.