美文网首页
使用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