xuyl
V2EX  ›  Flask

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

  •  
  •   xuyl · Oct 24, 2017 · 5374 views
    This topic created in 3297 days ago, the information mentioned may be changed or developed.

    接口逻辑如下

    
    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 replies  •  2019-07-06 13:13:06 +08:00
    0ZXYDDu796nVCFxq
    0ZXYDDu796nVCFxq
    Oct 24, 2017
    1
    nginx+uwsgi 部署,静态和接口同域就可以了

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

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

    @xuyl 试试把 self.args = self.parser.parse_args() 移到 post() 方法里去?
    winglight2016
    winglight2016
    Oct 25, 2017
    13
    400 问题,一般是客户端用了 json 或者 form 提交,服务端却仅支持 url 带参数,这种提交数据格式不规范的错误
    可以试一下加入 headers:content-type,另外楼主中断一下服务端看看提交的 request 走到了代码哪个部分?或者把完整的 request 输出一下看看什么问题?
    xuyl
    xuyl
    OP
    Oct 25, 2017
    14
    @Kilerd location=['form', headers', 'values', 'json', 'data', 'args'] 全试过,都一样的 400 错误
    xuyl
    xuyl
    OP
    Oct 25, 2017
    15
    @lgh 试过了,不行,依然 400 错误
    Kilerd
    Kilerd
    Oct 25, 2017 via iPhone
    16
    @xuyl location 写 form,然后 parse_args 放到 post 里面去
    bengle
    bengle
    Oct 25, 2017
    17
    改用 jsonp,是 get 的,只要没有文件上传什么的应该都可以,安全性也差点
    xuyl
    xuyl
    OP
    Oct 25, 2017
    18
    @bengle 用 jsonp 只是解决跨域问题,现在跨域不是问题,是参数解析的问题
    xuyl
    xuyl
    OP
    Oct 25, 2017
    19
    @Kilerd 试过,400 错误依旧,我得出的结论就是 ie8 通过 x domain request(xdr)方式兼容 cors 跨域,参数在 request.data 里面,利用 flask-restful 的参数解析是无法获取到参数的,只能硬解 request.data/request.get_data(), 并且这里获取到的还是 binary。
    vZexc0m
    vZexc0m
    Oct 26, 2017
    20
    我是后端解决的。
    ```
    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
    xuyl
    OP
    Oct 26, 2017
    21
    @vZexc0m 你看我主帖里,我也用了 flask_cors,跨域是没问题的,是参数解析的问题。
    vZexc0m
    vZexc0m
    Oct 26, 2017
    22
    @xuyl 试试不用 flask_result,直接用框架看看有没有问题
    xuyl
    xuyl
    OP
    Oct 28, 2017
    23
    @vZexc0m 多谢你的回复,参数在 request.data 里可获取到,但不用 flask-restful,对于规范化接口比较痛苦。
    vZexc0m
    vZexc0m
    Oct 30, 2017
    24
    restful 只是一种规范而已,不插件也可以实现
    ropon
    ropon
    Jul 6, 2019
    25
    请问解决了么? abort 抛出异常,状态码 400 就会出现跨域
    ![]( https://i.bmp.ovh/imgs/2019/07/9ab5c8f3cc91dcae.jpg)
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2899 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 51ms · UTC 14:04 · PVG 22:04 · LAX 06:04 · JFK 09:04
    ♥ Do have faith in what you're doing.