美文网首页
使用bottle前后端分离进行接口调试时候的跨域问题(1)

使用bottle前后端分离进行接口调试时候的跨域问题(1)

作者: 小钟钟同学 | 来源:发表于2018-03-30 11:00 被阅读487次

    背景

    在开发一个简单后台分析统计的时候,因为涉及到了前端和后端接口进行联调的问题,而且前端主要是使用Vue.js来相关开发,在使用axios和本地的后端接口进行联调的时候遇到了一个跨域的问题。

    如图示:

    前端的请求接口:


    image.png

    后端接口服务:


    image.png image.png

    问题描述:

    按理说跨域如果后端不支持的话,要想前端完成请求处理,需要进行使用nginx转发处理。

    但是既然是本地调试,我们后端直接开启支持即可。
    以下是bollte开启支持跨域的代码:

    image.png
    @hook('after_request')
    def enable_cors():
        """
        钩子函数,处理请求路由之后需要做什么的事情
        :return:
        """
        response.headers['Access-Control-Allow-Origin'] = '*'
    

    如果你使用的是get提交的话是没问题的:


    image.png

    使用get提交没有添加

    response.headers['Access-Control-Allow-Origin'] = '*'
    

    会出现以下的错误

    image.png

    添加后是:可以返回了数据结果

    image.png

    可惜不幸的是:当你使用POST提交的时候还是遇到405不支持跨域的问题:

    POST提交请求:
     C2S_Login (data) {
          // 登录
          return this.action_post('http://127.0.0.1:8189/api/user/login/',data)
        },
    

    请求结果:


    image.png

    问题分析:

    xhr.js:178 OPTIONS http://127.0.0.1:8189/api/user/login/ 405 (Method Not Allowed)
    

    查看请求对应的头部信息:

    image.png

    我提交的是POST 怎么变成了OPTIONS

    尝试把:

    @post('/api/user/login/')
    @get('/api/user/login/')
    def callback():
        return web_helper.return_msg(200, '登入成功!')
    

    变为:

    @route('/api/user/login/', method='POST')
    def callback():
        return web_helper.return_msg(200, '登入成功!')
    

    可惜还是不行:
    按其他的方案处理:

    
    def allow_cross_domain(fn):
        def _enable_cors(*args, **kwargs):
            # set cross headers
            response.headers['Access-Control-Allow-Origin'] = '*'
            response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS'
            allow_headers = 'Referer, Accept, Origin, User-Agent'
            response.headers['Access-Control-Allow-Headers'] = allow_headers
            if request.method != 'OPTIONS':
                # actual request; reply with the actual response
                return fn(*args, **kwargs)
    
        return _enable_cors
    
    
    @route('/api/user/login/', method='POST')
    @allow_cross_domain
    def callback():
        return web_helper.return_msg(200, '登入成功!')
    
    

    这时候出现还是405 但是不是说是跨域错误的问题,而是另一种错误!

    image.png

    参考:
    https://www.cnblogs.com/SilenceTom/p/6697484.html
    修改了对应的装饰器可惜还是不行!

    def allow_cross_domain(fn):
        def _enable_cors(*args, **kwargs):
            # set cross headers
            response.headers['Access-Control-Allow-Origin'] = '*'
            response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS'
            allow_headers = 'Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name'
            response.headers['Access-Control-Allow-Headers'] = allow_headers
            if request.method != 'OPTIONS':
                # actual request; reply with the actual response
                return fn(*args, **kwargs)
    
        return _enable_cors
    

    最终不经意发现原来焕哥大佬已经把这个问题的答案说了!!!感谢大佬!不然还真不知道怎么处理这问题!
    问题解决的答案地址:https://www.cnblogs.com/EmptyFS/p/6895479.html

    大神就是大神!建议大家都膜拜一下这个大神!也可以加入的他的群多多学习
    更多内容,敬请观注他的博客哟,他写的一系列的bottle都是很不错的:
    地址:http://www.cnblogs.com/EmptyFS/

    我按方法2处理之后post就完美返回了!:

    image.png

    考虑修改源码的方式侵入比较强,不方便后期扩展,可能把bottle给遗漏了!!所有最后还是修改为了再钩子文件处理,按方案1的方式!

    最后修改的的代码:

    #!/usr/bin/evn python
    # coding=utf-8
    
    """
    Author = zyx
    @Create_Time: 2017/11/30 18:12
    @version: v1.0.0
    @Contact: 308711822@qq.com
    @File: main.py
    @文件功能描述:
    """
    
    import logging
    import os
    import sys
    
    import bottle
    from beaker.middleware import SessionMiddleware
    from bottle import TEMPLATE_PATH
    from bottle import default_app, run, hook, request, response, get, error, abort
    
    from business_logic import api_offer
    
    # 引入该项目所有用到的API接口
    # from api_offer import config, proxy_address_multiple, order_code, order
    
    from abase_framework_module.net_workers import web_helper
    from abase_framework_module.cache_workers import redis_cache_helper as cache_helper
    from business_logic.app_configs import redis_config
    
    # from api_offer import app_configs
    
    #############################################
    # 初始化bottle框架相关参数----应用程序的主入口文件
    # 调用的时候
    #############################################
    
    # 获取本脚本所在的路径
    pro_path = os.path.split(os.path.realpath(__file__))[0]
    sys.path.append(pro_path)
    
    # 设置当前bottle运行提交的最大数据值为2M
    bottle.BaseRequest.MEMFILE_MAX = 1024 * 1024 * 2
    
    # 定义静态文件目录路径
    static_path = os.path.join(pro_path, 'template')
    
    # 定义模板路径
    TEMPLATE_PATH.append(os.path.join(pro_path, 'template'))
    
    # 如果不存在log文件夹, 则再当前脚本目录下创建log文件夹存放日志文件-
    if not os.path.exists('log'):
        os.mkdir('log')
    
    # 定义日志目录
    log_path = os.path.join(pro_path, 'log')
    # print('当前日志路径------', log_path)
    
    # 定义日志输出格式-输出是信息等级的
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        filename="%s/info.log" % log_path,
                        filemode='a')
    
    # 设置session参数
    session_opts = {
        'session.type': 'file',
        'session.cookie_expires': 3600,
        'session.data_dir': '/tmp/sessions/order',
        'session.auto': True
    }
    
    
    def allow_cross_domain(fn):
        def _enable_cors(*args, **kwargs):
            # set cross headers
            response.headers['Access-Control-Allow-Origin'] = '*'
            response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,OPTIONS'
            allow_headers = 'Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name'
            response.headers['Access-Control-Allow-Headers'] = allow_headers
            print('打印!!request.method!', request.method)
            if request.method == 'OPTIONS':
                # actual request; reply with the actual response
                print('打印!!!')
                response.close()
                return fn(*args, **kwargs)
    
        return _enable_cors
    
    
    @hook('before_request')
    def validate():
        """
        钩子函数,处理请求路由之前需要做什么的事情
        :return:
        """
        """使用勾子处理页面或接口访问事件"""
        # 让bottle框架支持jquery ajax的RESTful风格的PUT和DELETE等请求
        REQUEST_METHOD = request.environ.get('REQUEST_METHOD')
        HTTP_ACCESS_CONTROL_REQUEST_METHOD = request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_METHOD')
        if REQUEST_METHOD == 'OPTIONS' and HTTP_ACCESS_CONTROL_REQUEST_METHOD:
            request.environ['REQUEST_METHOD'] = HTTP_ACCESS_CONTROL_REQUEST_METHOD
    
        if request.method == 'OPTIONS':
            # actual request; reply with the actual response
            print('打印!!!')
        # 获取当前访问的Url路径
        path_info = request.environ.get("PATH_INFO")
        # 过滤不用做任何操作的路由
        if path_info in ['/favicon.ico', '/check_err/', '/log/']:
            return ''
        # 记录客户端提交参数信息----实测是成功
        web_helper.write_request_log(path_info)
    
    
    @hook('after_request')
    @allow_cross_domain
    def enable_cors():
        """
        钩子函数,处理请求路由之后需要做什么的事情
        :return:
        """
        pass
        # response.headers['Access-Control-Allow-Origin'] = '*'
    
    
    @get('/favicon.ico')
    def favicon():
        return ''
    
    
    @get('/log/')
    def callback():
        pass
        # """输出日志记录"""
        # if not const.IS_ONLINE:
        #     return static_file('info.log', root=log_path)
    
    
    @error(500)
    def miss(code):
        # ssh
        # 错误页面,一般来说,可以在网站制定一个404的HTML页面,然后用return template('404')去访问404这个页面
        return web_helper.return_msg(500, '服务器系统故障')
    
    
    @error(404)
    def miss(code):
        # 错误页面,一般来说,可以在网站制定一个404的HTML页面,然后用return template('404')去访问404这个页面
        return web_helper.return_msg(404, '接口不存在')
    
    
    # 函数主入口
    if __name__ == '__main__':
    
        # 初始化全局的redis缓存处理工具
        cache_helper.set_redis(redis_config.REDIS)
        app_argv = SessionMiddleware(default_app(), session_opts)
        run(app=app_argv, host='127.0.0.1', port=8189, debug=True, reloader=True)
    else:
        # 初始化全局的redis缓存处理工具
        cache_helper.set_redis(redis_config.REDIS)
        # 初始化email发送参数
        # mail_helper.set_mail(const.MAIL)
        application = SessionMiddleware(default_app(), session_opts)
    
    
    @post('/api/user/login/')
    @get('/api/user/login/')
    def callback():
        """获取短链接生成页面html"""
        return web_helper.return_msg(200, '登入成功!')
    

    ============================
    2018年12月16日 13:55:29--跨域问题的新总结
    =======================

    image.png

    解决问题的方式如下注释:
    加上以下代码即可:

    allow_headers = 'Referer, Accept, Origin, User-Agent,X-Requested-With, Content-Type, X-File-Name'
        response.headers['Access-Control-Allow-Headers'] = allow_headers
    
    image.png

    相关文章

      网友评论

          本文标题:使用bottle前后端分离进行接口调试时候的跨域问题(1)

          本文链接:https://www.haomeiwen.com/subject/zypbcftx.html