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

背景

在开发一个简单后台分析统计的时候,因为涉及到了前端和后端接口进行联调的问题,而且前端主要是使用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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容