跨域对于前端来说是一个老大难的问题,许多方法如jsonpdocument.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构建反向代理的更多相关文章

  1. Vue解决接口访问跨域问题

    随手摘录 Vue解决接口访问跨域问题 1.打开 config -> index.js 2. 找到proxyTable 3.粘贴 如下代码,'https://www.baidu.com'换成要访问 ...

  2. nodejs服务实现反向代理,解决本地开发接口请求跨域问题

    前后端分离项目需要解决第一个问题就是,前端本地开发时如何解决通过ajax请求产生的跨域的问题.一般的做法是通过本地配置nginx反向代理进行处理的,除此之外,还可以通过nodejs来进行代理接口.当然 ...

  3. vue脚手架解决跨域问题-------配置反向代理

    1.打开config/index.js 2.在dev配置对象中找到proxyTable:{} 3.添加如下配置 // 配置反向代理,解决跨域请求 proxyTable: { '/api': { tar ...

  4. CORS跨域与Nginx反向代理跨域优劣对比

    最近写了一些关于前后端分离项目之后,跨域相关方案的基本原理和常见误区的帖子,主要包括CORS和Nginx反向代理.这两种方案项目中都有在用,各有优缺,关于具体使用哪种方案,大家的观点也不大一致,本文主 ...

  5. 跨域问题 - Nginx反向代理

    Nginx反向代理的思路,就是通过Nginx解析URL地址的时候进行判断,将请求转发的具体的服务器上. 解决思路 跨域问题,是由于JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象. ...

  6. vue 解决axios请求出现前端跨域问题

    vue 解决axios请求出现前端跨域问题 最近在写纯前端的vue项目的时候,碰到了axios请求本机的资源的时候,出现了访问报404的问题.这就让我很难受.查询了资料原来是跨域的问题. 在正常开发中 ...

  7. 解决 net core 3.x 跨域问题

    跨域:指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制. 以下几种情况是造成跨域的原因: 域名相同,端口不同 域名相同,协议不同(即,一个 ...

  8. 简单设置,解决使用webpack前后端跨域发送cookie的问题

    最近用vue来做项目,用webpack来做前端自动化构建.webpack-dev-server会在本地搭建一个服务器,在和后端调试的时候,就会涉及到跨域的问题. 刚开始时,没有用vue-cli来构建项 ...

  9. 「Django」rest_framework学习系列-API访问跨域问题

    #以中间件方式解决API数据访问跨域问题1.API下新建文件夹下写PY文件a.引入内置类继承: from django.middleware.common import MiddlewareMixin ...

随机推荐

  1. 02Modify.ashx(修改班级信息)

    02Modify.html 修改 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> & ...

  2. easyui Dialog 去边框

    使用Url页面显示 panel-body 的内容, 因页面高度大于iframe高度,右侧则会出现边框, 如果页面显示的内容高度真实大于iframe高度,那出现边框是很正常. 我的问题就是有内部页面 的 ...

  3. Codeforces 670F - Restore a Number - [字符串]

    题目链接:https://codeforces.com/contest/670/problem/F 题意: 有一个非负整数 $n$,在它的右侧添上它的位数后,被发送出去:例如 $6510$,加上位数 ...

  4. 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 ...

  5. java工程师学习计划

  6. Page11:状态反馈、输出反馈的概念及性能比较,极点配置的基本概念、意义及其算法[Linear System Theory]

    内容包含离散时间线性时不变系统的稳定判据 状态反馈.输出反馈的基本概念及其性能比较 极点配置的基本概念.意义及其算法

  7. iPhone开发之使用NSUserDefaults存储数据

    NSUserDefaults是什么,有什么用处 对于应用来说,每个用户都有自己的独特偏好设置,而好的应用会让用户根据喜好选择合适的使用方式,把这些偏好记录在应用包的plist文件中,通过NSUserD ...

  8. python的一些基本概念知识和面试题

    对于机器学习算法工程师而言,Python是不可或缺的语言,它的优美与简洁令人无法自拔.那么你了解过Python编程面试题吗?从Python基础到网页爬虫你是否能全方位Hold住?今天,机器之心为读者们 ...

  9. 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 ...

  10. redis缓存和mysql数据库同步

    附redis关于缓存雪崩和缓存穿透,热点key 穿透 穿透:频繁查询一个不存在的数据,由于缓存不命中,每次都要查询持久层.从而失去缓存的意义. 解决办法: 持久层查询不到就缓存空结果,查询时先判断缓存 ...