几种允许跨域请求的方法

     阅读:26

“跨域请求 Cross-Origin Resource Sharing(CORS) 被禁止”这个问题,应该很常见了,网上也有很多解释原因和解决方案的文章。

鉴于网上搜到的文章内容比较长,讲得也比较细,我这里就列举一些,几种平台(主要是我目前用到的)允许跨域请求的方法。

  1. 用nginx。我暂时没用到,跳过。以后用到了,再补充。
  2. 设置谷歌浏览器。
  3. 设置python的wsgiref搭建的web服务器的响应头。
  4. 设置django的响应头。
  5. 设置全局django。我暂时没用到,跳过。以后用到了,再补充。

以下为详细说明。

1. 用nginx。我暂时没用到,跳过。以后用到了,再补充。

2. 谷歌浏览器,通过设置快捷方式禁用部分设置。

创建chrome浏览器的快捷方式,在属性中找到打开路径,在…chrome.exe后面加上

--args --disable-web-security --user-data-dir="C:/ChromeDevSession",比如,我的谷歌浏览器chrome.exe的快捷方式的打开路径,可以修改为:C:\Users\qcy\AppData\Local\Google\Chrome\Application\chrome.exe --disable-web-security --user-data-dir="C:/ChromeDevSession"

3. 用python的wsgiref快速搭建的web服务器,在http响应头中增加允许访问的主机所在的域。


"""
提供web数据服务
"""

from wsgiref.simple_server import make_server
import datetime
from urllib.parse import parse_qs
import json


class DateEncoder(json.JSONEncoder):
    """
    这里可以写上对各种不能通过 json.dumps 这个函数
    直接序列化的处理方式。
    """

    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime("%Y-%m-%d %H:%M:%S")
        elif isinstance(obj, datetime.date):
            return obj.strftime("%Y-%m-%d")
        else:
            return json.JSONEncoder.default(self, obj)


def get_response(environ, response):
    # response  如下调用就会发送HTTP响应的Header,注意只能调用一次start_response()函数发送Header。
    # response  函数两个参数,一是HTTP响应码,一是一组list表示的HTTP Header,每个Header用一个包含两个str的数组表示

    # 这个编号是给协议的
    status = '200 OK'
    # response_headers  中添加请求头部 ,解决跨域问题
    response_headers = [('Content-type', 'application/json'),
                        ('Access-Control-Allow-Origin', '*'),  # * 表示任意域名都可以跨域访问
                        ('Access-Control-Allow-Methods', 'POST'),
                        ('Access-Control-Allow-Headers', 'x-requested-with,content-type'),
                        ]  # json
    response(status, response_headers)

    # 获取web端需要的data
    # 用environ['PATH_INFO']获取路径,做简单的路由
    print(environ['PATH_INFO'])
    path_info = environ['PATH_INFO']

    if path_info == '/node_detail/':
        # 这里可以查询由GET请求提交过来的参数

        request_field_dict = parse_qs(environ['QUERY_STRING'])
        start_yyyymmdd = request_field_dict.get('start_yyyymmdd')[0]
        end_yyyymmdd = request_field_dict.get('end_yyyymmdd')[0]
        graph_name = request_field_dict.get('graph_name')[0]
        node_name = request_field_dict.get('node_name')[0]

        data_dict = dict()
        data_json_str = '这里是一个可以转换为dict的json字符串'
        data_dict['driving_factor'] = json.loads(data_json_str)

        # 这个编号是给前端处理的
        response_dict = {
            "code": 200,
            "msg": "success",
            "data": data_dict,
        }

        binary_data_json = json.dumps(response_dict, cls=DateEncoder).encode('utf-8')

    return [binary_data_json]


if __name__ == '__main__':
    http = make_server('', 8000, get_response)

    print('server in 8000....')

    http.serve_forever()

4. django框架下,在http响应头中增加允许跨域访问的主机所在的域。以下这段代码,改编自pyecharts项目的整合django项目的示例代码。这是在django框架的一个APP下面view文件。

import json
from random import randrange

from django.http import HttpResponse
from rest_framework.views import APIView

from pyecharts.charts import Bar
from pyecharts import options as opts


# Create your views here.
def response_as_json(data):
    json_str = json.dumps(data)
    response = HttpResponse(
        json_str,
        content_type="application/json",
    )
    response["Access-Control-Allow-Origin"] = "*"
    return response


def json_response(data, code=200):
    data = {
        "code": code,
        "msg": "success",
        "data": data,
    }
    return response_as_json(data)


def json_error(error_string="error", code=500, **kwargs):
    data = {
        "code": code,
        "msg": error_string,
        "data": {}
    }
    data.update(kwargs)
    return response_as_json(data)


JsonResponse = json_response
JsonError = json_error


def bar_base() -> Bar:
    c = (
        Bar()
            .add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
            .add_yaxis("商家A", [randrange(0, 100) for _ in range(6)])
            .add_yaxis("商家B", [randrange(0, 100) for _ in range(6)])
            .set_global_opts(title_opts=opts.TitleOpts(title="Bar-基本示例", subtitle="我是副标题"))
            .dump_options_with_quotes()
    )
    return c


class ChartView(APIView):
    def get(self, request, *args, **kwargs):
        return JsonResponse(json.loads(bar_base()))

5. django项目的全局设置,暂时没有用到,以后补充。

(完)