解决异地服务器接口访问跨域,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 ...
随机推荐
- 170824、storm 环境搭建
/*********************storm 环境搭建 **********************/ 1 安装jdk1.7 2 安装zookeeper集群环境 3 安装Python2.6. ...
- 堆的C语言实现
在C++中,可以通过std::priority_queue来使用堆. 堆的C语言实现: heap.c /** @file heap.c * @brief 堆,默认为小根堆,即堆顶为最小. */ #in ...
- 关于SQL SERVER中的FLOAT转换为VARCHAR
关于SQL SERVER中的FLOAT转换为VARCHAR 一个FLOAT型的字段,要转换为VARCHAR,可是小数点后面的都自动被删去了...后查得可以通过如下转换获得: SELECT CAST(C ...
- .NET Core开发日志——Dapper与MySQL
Dapper作为.NET生态中广为人知的轻量级ORM类库在.NET Core里仍能被有效利用,并且其不但可以连通SQL Server数据库还提供对其它数据库,比如MySQL的支持.这里试验了一下通过D ...
- Prometheus 函数
函数列表 一些函数有默认的参数,例如:year(v=vector(time()) instant-vector).v是参数值,instant-vector是参数类型.vector(time())是默认 ...
- hadoop内存配置方案
Configuration File Configuration Setting Value Calculation 8G VM (4G For MR) yarn-site.xml ...
- mac休眠掉电快,更改休眠模式
打开终端输入: $ pmset -g 查看休眠模式 hibernatemode 发现值为3, 这是大多数的设置,如果为0 ,那么休眠时严重掉电, 我们可以改变这个模式: $ sudo pmset -a ...
- 关于nginx重新编译
nginx安装成功后,发现有一些其他模块没有编译进去,或者想额外添加一些模块,这时候就要重新编译nginx. 首先,查看之前编译的一些参数,比如: 1 2 3 4 5 [root@lmode ngin ...
- char是所有类型中最短的 char多为8位,
https://en.wikipedia.org/wiki/C_data_typesIn practice, char is usually eight bits in size and short ...
- 搭建Kubernetes服务集群遇到的问题
kube-proxy问题: Apr 12 09:42:49 compute1 kube-proxy[12965]: E0412 09:42:49.602342 12965 reflector.go:2 ...