解决异地服务器接口访问跨域,node构建反向代理
跨域对于前端来说是一个老大难的问题,许多方法如jsonp
、document.domain + iframe
...都有或多或少的问题,一个最佳实践就是通过服务器nginx
做反向代理,但奈何不懂相关知识,就一直琢磨着使用 node.js
来做。
之前公司php写的接口,然后用node定义一样的路由,前端请求node的接口,然后通过Node在控制器中访问php的接口,这样确实能解决跨域问题,不过也是有缺点的,不能带上cookic等信息,不等同于反向代理;
事实上使用node是可以很容易构建本地的反向代理,使用 http-proxy-middleware 模块
假如目前有一个php提供的接口为 http://api.text.com/getdata 需要去代理
首先
npm i http-proxy-middleware --save //反向代理包
npm i cors --save //node跨域模块
然后:生成一个新的 express,app.js里面 删掉 index和user这两个路由,然后
var cors = require('cors');
var proxy = require('http-proxy-middleware');
var options = {
target: 'http://api.text.com', // 目标主机,提供接口服务的域名
changeOrigin: true, // 需要虚拟主机站点
};
var exampleProxy = proxy(options); //开启代理功能,并加载配置
app.use(cors()); app.use(exampleProxy); //代理任意请求的路由,也可以改成代理固定的某些路由
启动express服务
前段代码:
const host = "http://127.0.0.1:3000";
$.ajax({
url: host+ "/getdata"
}).then(function(data){
console.log(data);
}).fail(function(error){
console.log(error);
});
目前为止,反向代理成功,本地电脑可以跨域访问远程服务接口
另外,附加上,自己写的一个,携带cookic 的转发:
roouter.js 文件
var express = require('express');
var router = express.Router();
var request = require("request");
/* GET home page. */ const Api = {
GET(params){
params = params || {};
return new Promise(function(resolve,reject){
request({
method:"GET",
url:params.url,
qs:params.data,
headers:params.headers
},function (error, response, body) {
if (!error) {
resolve({response,body});
}else{
reject(error);
}
});
}) },
POST(params){
params = params || {};
return new Promise(function(resolve,reject){
request({
method:"POST",
url:params.url,
form:params.data,
headers:params.headers
},function (error, response, body) {
if (!error) {
resolve({response,body});
}else{
reject(error);
}
});
})
}
} module.exports = function(opt){
opt = opt || {};
var target = opt.target || '';
var url = opt.url || "**";
router.all(url,function(req,res,next){
var url = target + req.baseUrl + req.path;
var data = {};
var method = req.method;
if(method =="GET"){
data = req.query;
}else if(method == "POST"){
data = req.body;
}
let Cookie = req.header("Cookie");
let content = req.header('Content-type');
console.log("url:"+url,data,Cookie,content);
data.headers = {
"content-type": content,
"Cookie":Cookie
};
if(Api[req.method]){
Api[req.method]({
url:url,
data:data
}).then(function({response,body}){
try{
body = JSON.parse(body);
}catch(e){
}
// ************** 透传响应中的cookie **************
if (response.headers['set-cookie']) {
res.setHeader("set-cookie", response.headers['set-cookie']);
} // ************** 自定义cookie **************
//res.cookie('tc', 'test-cookie', {maxAge: 2 * 60 * 60 * 1000, httpOnly: true}); return res.status(response.statusCode).send(body);
//return res.json(body);
}).catch(function(e){
res.json(e);
})
}else{
res.json({code:500,msg:"不支持的请求类型"});
}
})
return router;
};
index.js
var express = require('express');
var router = require("./routers"); var cors = require('cors'); var app = express(); app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors()); var config = {
target:"http://xxxxxx"
}; app.use("/",router(config)); app.listen("3000",function(error){
console.log("启动服务-----3000");
})
koa2 版本
const router = require('koa-router')() var request = require("request");
/* GET home page. */ const Api = {
GET(params){
params = params || {};
return new Promise(function(resolve,reject){
request({
method:"GET",
url:params.url,
qs:params.data
},function (error, response, body) {
if (!error && response.statusCode == 200) {
try{
body = JSON.parse(body);
} catch(e){ }
resolve(body);
}else{
reject(error);
}
});
}) },
POST(params){
params = params || {};
return new Promise(function(resolve,reject){
request({
method:"POST",
url:params.url,
form:params.data
},function (error, response, body) {
if (!error && response.statusCode == 200) {
try{
body = JSON.parse(body);
} catch(e){ }
resolve(body);
}else{
reject(error);
}
});
})
}
} module.exports = function(opt){
opt = opt || {};
var target = opt.target || '';
var url = opt.url || "**";
if(opt.prefix){
router.prefix(opt.prefix)
}
router.all(url,async function(ctx,next){
var url = target + ctx.path; var data = {};
if(ctx.method =="GET"){
data = ctx.query;
}else if(ctx.method == "POST"){
data = ctx.request.body;
}
console.log("请求来源:"+url,data,ctx.method);
if(Api[ctx.method]){
try{
ctx.body = await Api[ctx.method]({
url:url,
data:data
});
}catch(e){
ctx.body = e;
} }else{
ctx.body = {code:500,msg:"不支持的请求类型"};
}
})
return router;
};
使用:
const proxy = require('./routers'); const insproxy = proxy({
target:"xxxx",
prefix:"/xxx"
}); app.use(insproxy.routes(), insproxy.allowedMethods());
解决异地服务器接口访问跨域,node构建反向代理的更多相关文章
- Vue解决接口访问跨域问题
随手摘录 Vue解决接口访问跨域问题 1.打开 config -> index.js 2. 找到proxyTable 3.粘贴 如下代码,'https://www.baidu.com'换成要访问 ...
- nodejs服务实现反向代理,解决本地开发接口请求跨域问题
前后端分离项目需要解决第一个问题就是,前端本地开发时如何解决通过ajax请求产生的跨域的问题.一般的做法是通过本地配置nginx反向代理进行处理的,除此之外,还可以通过nodejs来进行代理接口.当然 ...
- vue脚手架解决跨域问题-------配置反向代理
1.打开config/index.js 2.在dev配置对象中找到proxyTable:{} 3.添加如下配置 // 配置反向代理,解决跨域请求 proxyTable: { '/api': { tar ...
- CORS跨域与Nginx反向代理跨域优劣对比
最近写了一些关于前后端分离项目之后,跨域相关方案的基本原理和常见误区的帖子,主要包括CORS和Nginx反向代理.这两种方案项目中都有在用,各有优缺,关于具体使用哪种方案,大家的观点也不大一致,本文主 ...
- 跨域问题 - Nginx反向代理
Nginx反向代理的思路,就是通过Nginx解析URL地址的时候进行判断,将请求转发的具体的服务器上. 解决思路 跨域问题,是由于JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象. ...
- vue 解决axios请求出现前端跨域问题
vue 解决axios请求出现前端跨域问题 最近在写纯前端的vue项目的时候,碰到了axios请求本机的资源的时候,出现了访问报404的问题.这就让我很难受.查询了资料原来是跨域的问题. 在正常开发中 ...
- 解决 net core 3.x 跨域问题
跨域:指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制. 以下几种情况是造成跨域的原因: 域名相同,端口不同 域名相同,协议不同(即,一个 ...
- 简单设置,解决使用webpack前后端跨域发送cookie的问题
最近用vue来做项目,用webpack来做前端自动化构建.webpack-dev-server会在本地搭建一个服务器,在和后端调试的时候,就会涉及到跨域的问题. 刚开始时,没有用vue-cli来构建项 ...
- 「Django」rest_framework学习系列-API访问跨域问题
#以中间件方式解决API数据访问跨域问题1.API下新建文件夹下写PY文件a.引入内置类继承: from django.middleware.common import MiddlewareMixin ...
随机推荐
- java小tip
//20181128 ·javaJDK源码在c盘java安装目录里jdk文件夹src.zip压缩包里 ·HashCode()返回的数可能是负数 ·内部类的优点:可以方便调用所在类的方法 ·接口中定义常 ...
- Ubuntu系统中各种文件颜色的含义
蓝 色:文件夹 ,ls -l或ll时可以看到权限部分的第1个字母是d红色:压缩文件 绿色:可执行文件,包括jar白色:文本文件红色闪烁:错误的符号链接淡蓝色:符号链接黄色:设备文件灰色:其它文件 ...
- CCPC-Wannafly Winter Camp Day4 Div1 - 夺宝奇兵 - [简单思维题]
题目链接:https://zhixincode.com/contest/18/problem/A?problem_id=259 题目描述 wls正在玩一个寻宝游戏. 宝藏一共有 $n$ 种,都藏在一个 ...
- [No0000157].net core项目中拼音,excel,pdf处理库
汉字转拼音 1. HxfPinYin public static class Pinyin { public static string ConvertEncoding(string text, En ...
- window.location.reload(false);window.location.reload(true);history.Go(0)区别
在日常工作中常用的页面刷新方式的区别: 1 window.location.reload(false); 先说说window.location.reload(false);当我们window.loc ...
- mail 发送email
(一)首先安装ssmpt和mailutils: sudo apt-get install ssmtp mailutils (二)接下来编辑配置文件sudo gedit /etc/ssmtp/ssmtp ...
- >>>>>>>> [ovs][libvirt] virt-xml ovs-vsctl
查看可用的参数: [root@vrouter1 tong]# virt-xml --add-device --network=? |grep source source source_mode sou ...
- teamviewer 卸载干净
1 点击开始菜单,控制面板,卸载程序,找到软直接卸载2 按住Ctrl+R,输入%AppData%,删除teamview 相关文件夹3 输入regedit打开注册表HKEY_LOCAL_MACHINE\ ...
- SSL连接分为两个阶段:握手和数据传输阶段
一.SSL概述SSL连接分为两个阶段:握手和数据传输阶段.握手阶段对服务器进行认证并确立用于保护数据传输的加密密钥,必须在传输任何应用数据之前完成握手.一旦握手完成,数据就被分成一系列经过保护的记录进 ...
- 主动触发input框的失去焦点事件,阻止输入法跳出
今天遇到个问题,我在手机做一个选择生日的功能,但是当我点击input框时,事件选择插件和输入法都弹出来了,很丑,然后就想阻止输入法弹出来, 网上一个方法是:在input框的获取焦点事件里,主动触发失去 ...