前言 针对网页资源跨域请求问题如果是自己服务器通常会在nginx添加header头1 add_header Access-Control-Allow-Origin *;
来解决,如果不是自己的服务器对于动态数据交互请求我们通常的做法有jsonp或者请求先到自己服务器,然后自己服务器再和目标服务器交互获取响应返回给网页客户端,最近我们就遇到了这样的跨域问题,unity打包出来的web游戏内有访问平台用户头像的需求,而用户头像资源请求平台没有开放header的跨域设置,那只能使用后者通过自己的服务器代理访问资源。
设计规划 假设需要访问的ifeng的logo
经过我们自己的服务资源请求则变成(urlencode原始请求后追加到代理地址后面)
node实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 var corss = require('cors'); var request = require('request'); var validUrl = require('valid-url'); var express = require('express'); var URL = require("url"); var app = express(); app.use(corss({ origin: '*' })); app.disable('x-powered-by'); app.get('/proxy/:url', function (req, res) { if (req.params.url.length) { var url = decodeURIComponent(req.params.url); if (validUrl.isWebUri(url)) { res.setHeader('State', 'YES'); request(url).pipe(res); } else { res.setHeader('State', 'NO'); res.statusCode = 404; res.end() } } else { res.setHeader('State', 'NO'); res.statusCode = 404; res.end() } }); app.listen(3000);
package.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { "name": "proxy", "version": "1.0.0", "description": "", "main": "proxy.js", "dependencies": { "cors": "^2.8.4", "corsproxy": "^1.5.0", "express": "^4.16.3", "request": "^2.87.0", "valid-url": "^1.0.9" }, "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "xingqiba", "license": "MIT" }
nginx代理到本地 1 2 3 4 5 6 7 8 9 server { listen 80; server_name -; root /var/www/proxy; location ~ /proxy { proxy_pass http://127.0.0.1:3000; } }
supervisor管理代理服务 1 2 3 4 5 6 7 8 9 10 [program:proxy] numprocs=1 command=/bin/bash /data/server/proxy/start.bash user=root autorestart=true autostart=true stdout_logfile=/var/log/supervisor/proxy_stdout.log stderr_logfile=/var/log/supervisor/proxy_stderr.log stdout_logfile_maxbytes=500MB stdout_logfile_backups=2
php实现(以参数url传递) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?php $url = $_GET["url"]; if (!preg_match("~^https?://~i", $url)) { $url = "http://" . $url; } $ch = curl_init($url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); $response_headers_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $response_headers = explode("\r\n", substr($response, 0, $response_headers_size)); $response_body = substr($response, $response_headers_size); curl_close($ch); $propagate_headers = array("content-type"); foreach ($response_headers as $header) { if (in_array(strtolower(explode(": ", $header)[0]), $propagate_headers)) { header($header); } } header("Access-Control-Allow-Origin: *"); echo $response_body;
结论
功能已经实现,但适用吗?显然浪费了带宽,可以优化为先保存到本地服务器,然后作为本地服务器资源的一部分返回给客户端
支持