解决异地服务器接口访问跨域,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 ...
随机推荐
- 02Modify.ashx(修改班级信息)
02Modify.html 修改 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> & ...
- easyui Dialog 去边框
使用Url页面显示 panel-body 的内容, 因页面高度大于iframe高度,右侧则会出现边框, 如果页面显示的内容高度真实大于iframe高度,那出现边框是很正常. 我的问题就是有内部页面 的 ...
- Codeforces 670F - Restore a Number - [字符串]
题目链接:https://codeforces.com/contest/670/problem/F 题意: 有一个非负整数 $n$,在它的右侧添上它的位数后,被发送出去:例如 $6510$,加上位数 ...
- CCPC-Wannafly Winter Camp Day5 Div1 - Sorting - [线段树]
题目链接:https://zhixincode.com/contest/22/problem/I?problem_id=314 样例输入 1 5 9 31 5 3 2 41 1 52 1 51 1 1 ...
- java工程师学习计划
- Page11:状态反馈、输出反馈的概念及性能比较,极点配置的基本概念、意义及其算法[Linear System Theory]
内容包含离散时间线性时不变系统的稳定判据 状态反馈.输出反馈的基本概念及其性能比较 极点配置的基本概念.意义及其算法
- iPhone开发之使用NSUserDefaults存储数据
NSUserDefaults是什么,有什么用处 对于应用来说,每个用户都有自己的独特偏好设置,而好的应用会让用户根据喜好选择合适的使用方式,把这些偏好记录在应用包的plist文件中,通过NSUserD ...
- python的一些基本概念知识和面试题
对于机器学习算法工程师而言,Python是不可或缺的语言,它的优美与简洁令人无法自拔.那么你了解过Python编程面试题吗?从Python基础到网页爬虫你是否能全方位Hold住?今天,机器之心为读者们 ...
- LeetCode 922 Sort Array By Parity II 解题报告
题目要求 Given an array A of non-negative integers, half of the integers in A are odd, and half of the i ...
- redis缓存和mysql数据库同步
附redis关于缓存雪崩和缓存穿透,热点key 穿透 穿透:频繁查询一个不存在的数据,由于缓存不命中,每次都要查询持久层.从而失去缓存的意义. 解决办法: 持久层查询不到就缓存空结果,查询时先判断缓存 ...