zoukankan      html  css  js  c++  java
  • vue flask 跨域问题

      最近一直忙着检查点测试平台的开发。之前主要是从事后端开发,现在所有的东西都需要自己一个人撸。也遇到了之前在后端服务开发中未碰到的问题,在此记录下解决的全过程。

      前端采用vue + element的技术,开发完成后生成静态文件扔到nginx服务器上。后端用python的flask,完成之后放到gunicorn中。两个单独开发到没有什么太大问题,问题就出在将两个合在一起的时。

      第一次合并的时候出现了下面的问题,额。。。跨域问题,问题不大改改后台的响应就ok,就写了一个简单的装饰器

      

      装饰器代码:

    def mkrp(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            repjson = func(*args, **kw)
            response = make_response(repjson)
            response.headers['Access-Control-Allow-Origin'] = '*'
            response.headers['Access-Control-Allow-Methods'] = 'PUT,GET,POST,DELETE,OPTIONS'
            return response
        return wrapper

       然后就是见证奇迹的时刻,果然页面正常,部分请求都好了。但好景不长,为啥post请求全跪了呢,还都是上面的问题,wtf

                                          

      在chrome的开发者工具中查看请求信息,发现所有的post请求之前,都会发一次 Request - Method:OPTIONS的请求,然后post请求就没发出,这玩意儿到底又是啥呢。

      options请求类似于一个探针,在post请求前先去发送,然后根据Access-Control-*的返回,判断是否是否对指定站点有访问权限。然后网上找了各种资料,其中艰辛不表。

      找的各种方案基本上不合适,不知道是不是我自己写的代码太low导致的。咨询了运维的兄弟,他直接让我走ngix转发,让两个后台的请求直接和前端地址再同一个域里面,nginx的配置如下:

      

    server 
    {
            listen 8099; 
            server_name mywebhost;
            index index.html index.htm index.php;
            root /usr/local/vue-dists/dist;
            location / {
            try_files $uri $uri/ @router;
                    index index.html;
            }
            location @router {
                    rewrite ^.*$ /index.html last;
            }
            #access_log off;
            access_log logs/vue.log main;
            error_log logs/vue_error.log;
            location /python/ {
                    if ($request_method = 'OPTIONS') {
                            add_header 'Access-Control-Allow-Origin' '*';
                            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                            add_header 'Content-Type' 'text/plain';
                            add_header 'Content-Length' 0;
                            return 204;
                    }
                    if ($request_method = 'POST') {
                            add_header 'Access-Control-Allow-Origin' '*';
                            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                    }
                    if ($request_method = 'GET') {
                            add_header 'Access-Control-Allow-Origin' '*';
                            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                    }
    
                    proxy_pass http://myapihost:5000/;
            }
    }
    ~

      果然,这位仁兄的解决方案果然靠谱,跨域的问题全部解决。

      但是问题是解决了,但是心中还有是有些不甘,咱毕竟是个有追求的开发者,不能这么认命,还是想通过服务端的方式来解决这个问题。不是post请求之前发了一个options的探针吗,咱就吧请求拦截了,你要啥,我返回啥。

      看了下flask的官方文档,可以用before_request的装饰器来过滤拦截,上代码:

      

    @app.before_request
    def option_replay():
        if request.method =='OPTIONS':
            resp = app.make_default_options_response()
            if 'ACCESS_CONTROL_REQUEST_HEADERS' in request.headers:
                resp.headers['Access-Control-Allow-Headers'] = request.headers['ACCESS_CONTROL_REQUEST_HEADERS']
            resp.headers['Access-Control-Allow-Methods'] = request.headers['Access-Control-Request-Method']
            resp.headers['Access-Control-Allow-Origin'] = request.headers['Origin']
            return resp
    
    
    @app.after_request
    def set_allow_origin(resp):
        h = resp.headers
        if request.method != 'OPTIONS' and 'Origin' in request.headers:
            h['Access-Control-Allow-Origin'] = request.headers['Origin']

      其中我遇到了一个坑,对于响应头,我一开始只设置了all methods和allow orgin,返回还是怎都有问题,后来查了阮一峰大神的博客,找到相关内容,将allow headers加上去就木有问题了。

      

      参考资料:http://www.ruanyifeng.com/blog/2016/04/cors.html 

     

       

     

      

      

  • 相关阅读:
    mina 实例(转载)
    Java NIO 转载
    解决 Tomcat reload WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesJdbc The web application [] registered the JDBC driver [com.mysql.jdbc.Driver] but fail
    ECharts的使用相关参考---转
    转-——推荐几个web中常用的一些js图表插件
    (转)Log4J日志配置详解
    ~与~+的用法
    【转】sed 高级用法
    使用sed替换一行内多个括号内的值
    【转】 SED多行模式空间
  • 原文地址:https://www.cnblogs.com/rubeitang/p/8351119.html
Copyright © 2011-2022 走看看