通用跨域请求代理文件

<script type="text/javascript">
document.domain = 'test.cn';

var $ = {}; 
$.xho = function () { //创建xmlhttprequest对象 
    var http_request = null; 
    if (window.XMLHttpRequest) { //Mozilla 浏览器 
        http_request = new XMLHttpRequest(); 
        if (http_request.overrideMimeType) {//设置MIME类别 
            http_request.overrideMimeType("text/xml"); 
        } 
    } 
    else if (window.ActiveXObject) { //IE浏览器 
        try { 
            http_request = new ActiveXObject("Msxml2.XMLHTTP"); 
        } catch (e) { 
            try { 
                http_request = new ActiveXObject("Microsoft.XMLHTTP"); 
            } catch (e) { } 
        } 
    } 
    return http_request; 
};

$.rsc = function (obj, callfunc) { 
    return function () { 
        if (obj.readyState == 4) { 
            if (obj.status == 200) { 
                callfunc(obj.responseText); 
            } 
        } 
    };
};

$.GET = function (url, callfunc) { 
    var xho = $.xho(); 
    if (xho == null) return; 
    xho.onreadystatechange = $.rsc(xho, callfunc); //设置回调函数 
    //第三个参数指定在等待服务器返回信息的时间内是否继续执行下面代码,如果为true,则不会继续执行,默认为true 
    xho.open("GET", url, true); 
    xho.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xho.send(null); 
};

$.POST = function (url, data, callfunc) {
    var xho = $.xho(); 
    if (xho == null) return; 
    xho.onreadystatechange = $.rsc(xho, callfunc); //设置回调函数 
    xho.open("POST", url, true); 
    xho.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //post请求必须修改MIME类别 
    xho.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xho.send(data); 
};

function call(func, param)
{
    func = eval('parent.window.' + func);
    func(param);
}


function isJson(obj){
    var isjson = typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length;    
    return isjson;
}

function isEmpty(obj) {
    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            return false;
    }
    return true;
}

function json2Query(params) {
    tail = [];
    for (var p in params) {
        if (params.hasOwnProperty(p)) {
            tail.push(p + "=" + encodeURIComponent(params[p]));
        }
    }
    return tail.join("&")
}

var invokeApi = function(api, param, method, callback) {
    var m = (!method || method.toLowerCase() == 'get') ? 'get' : 'post';
    if ('get' == m) {
        debugger
        if (isJson(param) && ! isEmpty(param)) {
            param = json2Query(param);
        }

        if (param) {
            api = (api.indexOf('?') == -1) ? api + '?' + param : api  + '&' + param;
        }


        $.GET(
            api,
            function(data){
                call(callback, data);
            }
        )
    } else {
        if (isJson(param)) {
            param = json2Query(param);
        }
        $.POST(
            api,
            param,
            function(data) {
                call(callback, data);
            }
        )
    }
}

</script>

 说明:比如 a.test.cn的js想发送请求到 b.test.cn,这时只需要在 b.test.cn 的根目录新增一个 proxy.html ,内容为上面的代码。然后在 a.test.cn 下新建一个html文件,内容如下:

<script type="text/javascript">

mod = {};

mod.submod = function() {

    var ifr_win = '';

    var init = function() {
        load_iframe();
    }

    var load_iframe = function() {
            document.domain = 'test.cn';
            var ifr = document.createElement('iframe');
            ifr.src = 'http://b.test.cn/proxy.html';
            ifr.style.display = 'none';
            ifr.id = 'proxy_ifr';
            document.body.appendChild(ifr);
            ifr.onload = function() {
                ifr_win = ifr.contentWindow;
            };
    };

    var cb = function(msg) {
        console.log(msg);
    }

    var get_dl = function() {
        ifr_win.invokeApi(
            'http://b.test.cn/ajax/dl',
            {"id":13082, "from":"office", "app":"helper", "file_type":1},
            'POST',
            'mod.submod.cb'
        );
    }

    var get_preview = function() {
        ifr_win.invokeApi(
            'http://b.test.cn/ajax/preview',
            {"mb_id":12269, "moban_type":"2", "app":"helper", "file_type":2},
            'GET',
            'mod.submod.cb'
        );
    }

    return {
            init : init,
            cb : cb,
            get_dl : get_dl,
            get_preview : get_preview
    };
}();

mod.submod.init();

setTimeout("mod.submod.get_dl()", 500);

setTimeout("mod.submod.get_preview()", 500);

</script>

 

### Fetch 请求的相关问题及解决方案 当使用 `fetch` 处理请求时,CORS(源资源共享)配置是非常重要的一步。如果没有正确配置 CORS,可能会导致浏览器阻止请求完成。以下是几种常见的解决方法及其具体实现。 #### 后端配置 CORS 最安全和推荐的做法是在后端启用 CORS 支持。这通常涉及设置 HTTP 响应头以允许特定的名访问资源。例如,在 Express.js 中可以这样配置[^2]: ```javascript app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("Content-Type", "application/json;charset=utf-8"); next(); }); ``` 以上代码片段设置了通用权限,适用于大多数场景下的开发需求。注意 `"*"` 表示允许任何来源访问,但在生产环境中建议替换为具体的白名单地址列表以提高安全性。 #### 使用 Vue CLI 的代理功能 在前端框架如 Vue.js 中,也可以通过配置代理的方式来规避限制。这种方法特别适合于本地调试阶段。可以在项目的 `vue.config.js` 文件里添加如下内容[^1]: ```javascript module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:5000', // 替换为目标服务器的实际URL changeOrigin: true, pathRewrite: { '^/api': '' } } } } }; ``` 这里 `/api` 是一个路径前缀,所有的匹配到这个前缀的请求都会被转发给目标服务器,并且会修改原始请求中的 Host 字段使之看起来像是直接向目标服务器发出的一样。 #### 客户端 fetch 设置 withCredentials 属性 有时候即使已经完成了基本的 CORS 配置,仍然可能出现身份验证失败的情况。这是因为默认情况下 cookies 或者其他认证信息不会随同请求一起发送出去。此时需要显式开启 credentials option: ```javascript fetch('https://other-domain.com/api/resource', { method: 'GET', credentials: 'include' // or 'same-origin' }) .then(response => response.json()) .catch(error => console.error('Error:', error)); ``` 这里的 `credentials: 'include'` 参数告诉浏览器应该连同请求一同提交 cookie 数据等敏感资料[^3]。 --- ### 总结 综上所述,针对 fetch 请求的问题可以从以下几个方面入手解决:一是确保后端已适当开放了必要的 CORS 权限;二是在前端利用构建工具提供的代理机制绕过浏览器的安全策略约束;三是必要时候调整客户端 fetch 请求的行为使其能够携带所需的身份凭证信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值