专栏首页Ryan Miao使用nginx代理跨域,使用nginx代理bing的每日一图

使用nginx代理跨域,使用nginx代理bing的每日一图

前言

自从搞清楚了跨域原理后一直自鸣得意,感觉跨域没啥问题了。而事实上对关于跨域的几个header的理解也有限,但那又如何,我能做到跨域就行了。今天想把博客背景图改成bing的每日一图,发现遇到跨域问题。首先想到的就是自己写一个web,请求bing,然后传出结果,把自己的接口允许跨域。确实做到了,但是。我找了一台阿里云服务器,我安装了java,我编写了一个基于dropwizard的webservice。我需要写脚本去部署,确保系统稳定,挂了自动重启。我要写一堆的java代码来完成这件事。忽然想到nginx,于是一发不可收拾。

安装好Nginx

参阅 http://blog.rmiao.top/install-nginx-on-centos/

找到配置文件/usr/local/nginx/nginx.conf

新增代理路由

location ^~/proxy/bing/ {
    add_header 'Access-Control-Allow-Origin' 'http://localhost:8088';
    add_header 'Cache-Control' 'public, max-age=604800';

    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

    rewrite ^/proxy/bing/(.*)$ /$1 break;
    proxy_pass https://cn.bing.com/; 
}

浏览器访问自动代理

http://101.200.218.760/proxy/bing/HPImageArchive.aspx?format=js&idx=0&n=1

代理对象为:
https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1

这是最简单的实现方案,但缺点是只能指定一个域名跨域。

如果我想增加多个origin怎么办

不要想用逗号隔开,这个不行,浏览器不允许。那么只能自己判断比较后插入一个合适的值。

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
        root   html;
        index  index.html index.htm;
    }

    location ^~/proxy/bing/ {

        set $cors "local";

        if ( $http_referer ~* "(https?://www\.cnblogs\.com/woshimrf[^\s]*)|(https?://api.rmiao.top[^\s]*)|(https?://blog.rmiao.top[^\s]*)|(http://localhost[^\s]*)" ) {
            set $cors "allow";
        }

        if ( $request_method = "OPTIONS" ) {
            set $cors "${cors}options";
        }

        if ( $cors = "allowoptions" ) {
            add_header 'Access-Control-Allow-Origin' "$http_origin";
            add_header 'Access-Control-Allow-Credentials' "true";
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
            add_header 'Access-Control-Allow-Headers' 'reqid, nid, host, x-real-ip, x-forwarded-ip, event-type, event-id, accept, content-type';
            add_header 'Access-Control-Max-Age' 2592000;
            add_header 'Content-Length' 0;
            add_header 'Content-Type' 'text/plain, charset=utf-8';
            
            # indicate successful return with no content
            return 204;
        }
        
        if ($cors = "allow") {
            rewrite ^/proxy/bing/(.*)$ /pub_cors/$1 last;
        }

        if ($cors = "local") {
            return 403;
        }

    }

    location ^~/pub_cors/ {
        internal;
        # Tells the browser this origin may make cross-origin requests
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        # in a preflight response, tells browser the subsequent actual request can include user credentials (e.g., cookies)
        add_header 'Access-Control-Allow-Credentials' "true";
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
        add_header 'Access-Control-Allow-Headers' 'reqid, nid, host, x-real-ip, x-forwarded-ip, event-type, event-id, accept, content-type';
        add_header 'Access-Control-Max-Age' 2592000;
        add_header 'Cache-Control' "public, max-age=604800";

        rewrite ^/pub_cors/(.*)$ /$1 break;
        proxy_pass https://cn.bing.com/; 
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }



}

语法要点就不推测了。后面有机会认真学习下。不过,这里还是可以有几个语法参考的。

  1. 设置变量 set $cors "local";
  2. 正则表达式 location ^~/proxy/bing/ {
  3. 获取request的refer $http_referer
  4. 获取request的method $request_method
  5. 获取request的origin $http_origin
  6. 变量的读取,包裹在引号里也可以, add_header 'Access-Control-Allow-Origin' "$http_origin";
  7. 变量的读取,可以用大括号包裹, set $cors "${cors}options";
  8. if 里的判断可以用正则, ~* 表示不区分大小写,匹配正则, 取反!~*
  9. ~ 区分大小写,匹配正则, 取反 !~
  10. 添加一个header, add_header 'Access-Control-Max-Age' 2592000;
  11. 设置option的预检请求为204
  12. 跳转, rewrite ^/proxy/bing/(.*)$ /pub_cors/$1 last;, 分3部分,第一部分是正则,是匹配当前location的url的正则。 第二部分是映射的值,在第二部分里可以使用$1来获得匹配第一个括号匹配的内容。
  13. if 里的判断可以用等号, if ($cors = "allow") {
  14. internal;是不是只能内部访问?
  15. 对于这种代理,尤其是bing这个,完全可以缓存掉。 add_header 'Cache-Control' "public, max-age=604800";
  16. proxy_pass https://cn.bing.com/; 代理host,看样子下一步请求的host就是它,对于rewrite ^/pub_cors/(.*)$ /$1 break;则是把匹配的$1拼接到host之后。即,完成了转发操作。

确实比自己写Java web来做转发的好。

TODO 研究Nginx 配置文件的语法

上面的编写过程都是猜测出来的,没有看官方文档。英语不好就是不愿意看官网。后面有机会再研究具体语法。不过短期应该不会,很少用到nginx。到用到的时候再说吧。

TODO 正则表达式学习

虽然看了很多变正则表达式,但仅仅会写一个简单的基础模型。nginx里的配置让我看到了正则表达式的强大。什么时候深入学习一下呢?只能放到todo list里了,短期没时间规划。

参考

了解到怎么返回405:

照抄写的跨域方案:

最先看到的解决方案,虽然不合适:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 照着官方文档学习react

    准备 先要准备环境。搭建一个基于webpack的react环境:Hello ReactJS. 一些要点 我在想是否应该完整的记录照抄的过程呢。毕竟已经开始一段,...

    Ryan-Miao
  • maven 插件

    一直没注意看maven执行过程中的打印日志,今天突然发现一段话,说编译以及resource未指定编码,默认gbk。于是,百度了设置编码的方式: <plugin>...

    Ryan-Miao
  • 使用Apache Server 的ab进行web请求压力测试

    参考:http://www.cnblogs.com/spring3mvc/archive/2010/11/23/2414741.html 自己写代码经常是顺着逻...

    Ryan-Miao
  • Android GridView组件的使用

    GridView是一个网络布局的视图,他能让你的元素显示在一个个的格子里。我们的桌面就是一个GridView。。

    飞雪无情
  • 今天,你有微信小游戏提交审核吗?

    12月10日的推文里,写过在未来2个月里,微信小程序应该是要开放了,不然开发者们应该是憋不住了,结果确实都憋不住了。今天微信官方开放了小游戏的能力,同期上线小游...

    企鹅号小编
  • 微信小游戏正式上线,H5游戏迎新机遇

    游戏头条 微信号:gametoutiao(←长按复制) 中国首家顾问式新媒体定制属于您自己的媒体内容 导语:12月28日,微信更新至 6.6.1 版本。微信公众...

    企鹅号小编
  • 有关跨域请求的一些记录

    最近做一个玩的东西需要用到天气API,便从今天头条首页抓了一个想自己用。https://www.toutiao.com/stream/widget/local_...

    yumusb
  • 一文彻底搞懂Python可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)的概念

    在Python中可迭代(Iterable)、迭代器(Iterator)和生成器(Generator)这几个概念是经常用到的,初学时对这几个概念也是经常混淆,现在...

    阳仔
  • 通过实例学习ROP技术

    这两天闲着无聊就在 exploit-db 上找个小软件练练手,但是 exploit-db 上面给的 poc 并能正常运行,无奈只好自己写了一个,顺便写篇文章把自...

    信安之路
  • Linux学习笔记之在 CentOS 里下载 RPM 包及其所有依赖包

    前几天我尝试去创建一个仅包含我们经常在 CentOS 7 下使用的软件的本地仓库。当然,我们可以使用 curl 或者 wget 下载任何软件包,然而这些命令并不...

    Jetpropelledsnake21

扫码关注云+社区

领取腾讯云代金券