var http = require('http');
var https = require('https');
var url=require("url");
var pass = require('stream').PassThrough;
var getHeader = function (req) {
var ret = {};
for (var i in req.headers) {
if (!/^(host|connection|Access-|origin|referer|user-agent|user-doclever|path-doclever|url-doclever|method-doclever|headers-doclever|X-Requested-With)/i.test(i)) {
ret[i] = req.headers[i];
}
}
ret["accept"]="*/*";
var headers=req.headers["headers-doclever"];
if(headers)
{
headers=JSON.parse(headers);
for(var key in headers)
{
ret[key]=headers[key];
}
}
return ret
};
var filterResHeader = function (headers,res) {
var ret = {};
res.setHeader("Cache-Control", "no-cache,no-store");
res.setHeader("Pragrma", "no-cache");
res.setHeader("Expires", 0);
var resHeaders=res.getHeader("Access-Control-Expose-Headers")?res.getHeader("Access-Control-Expose-Headers").toLowerCase():"";
for (var i in headers) {
if (!/Access-/i.test(i)) {
if(/set-cookie/i.test(i))
{
for(let index=0;index<headers[i].length;index++)
{
headers[i][index]=headers[i][index].split(" ")[0];
}
ret[i]=headers[i];
}
else
{
ret[i] = headers[i];
}
}
if(!resHeaders)
{
res.setHeader("Access-Control-Expose-Headers",i);
}
else if(resHeaders.indexOf(i.toLowerCase()+",")==-1 && resHeaders.indexOf(","+i.toLowerCase())==-1)
{
res.setHeader("Access-Control-Expose-Headers",res.getHeader("Access-Control-Expose-Headers")+","+i);
}
}
return ret;
};
var getPath = function (req) {
var url = req.url;
if (url.substr(0, 7).toLowerCase() === 'http://') {
var i = url.indexOf('/', 7);
if (i !== -1) {
url = url.substr(i);
}
}
return url;
};
function getHost(req) {
var url=req.headers["url-doclever"];
url=url.replace(/^(http:\/\/|https:\/\/)/i,"");
var arr=url.split(":");
return arr[0];
}
function getPort(req) {
var url=req.headers["url-doclever"];
var defaultPort;
if(req.headers["url-doclever"].toLowerCase().startsWith("https://"))
{
defaultPort=443;
}
else
{
defaultPort=80;
}
url=url.replace(/^(http:\/\/|https:\/\/)/i,"");
var arr=url.split(":");
return arr.length>1?arr[1]:defaultPort;
}
var onProxy = function (req, res) {
handleHeader(req,res);
if(req.method=="OPTIONS")
{
return;
}
if(!req.headers["url-doclever"])
{
mock(req,res);
}
else
{
proxy(req,res);
}
};
function mock(req,res) {
var obj=url.parse(mockUrl);
var path=req.headers.path || url.parse(req.url).path;
var opt={
host: obj.hostname,
path: (obj.pathname=="/"?"":obj.pathname)+path,
method: req.method,
headers: getHeader(req),
port:obj.port?obj.port:80,
}
console.log("初次请求:method:"+opt.method+"host:"+opt.host+"port:"+opt.port+"path:"+opt.path)
if(opt.headers["content-length"])
{
delete opt.headers["content-length"]
}
var req2 = http.request(opt, function (res2) {
if(!realUrl || res2.headers["finish-doclever"]=="0")
{
console.log("接口开发中,返回mock数据");
res.writeHead(res2.statusCode, filterResHeader(res2.headers,res));
res2.pipe(res);
res2.on('end', function () {
});
}
else
{
if(res2.headers["finish-doclever"]=="1")
{
console.log("接口已完成,调用真实接口");
}
else
{
console.log("接口或者项目未找到,转调真实接口");
}
var headers=getHeader(req);
var objUrl=url.parse(realUrl);
var request1,opt1;
if(objUrl.protocol=="http:")
{
opt1={
host: objUrl.hostname,
path: (objUrl.pathname=="/"?"":objUrl.pathname)+path,
method: req.method,
port:objUrl.port?objUrl.port:80,
headers:headers
}
request1=http.request;
}
else
{
opt1={
host: objUrl.hostname,
path: (objUrl.pathname=="/"?"":objUrl.pathname)+path,
method: req.method,
port:objUrl.port?objUrl.port:443,
headers:headers,
rejectUnauthorized: false,
requestCert: true,
}
request1=https.request;
}
console.log("调用真实接口:method:"+opt1.method+"host:"+opt1.host+"port:"+opt1.port+"path:"+opt1.path)
var req3=request1(opt1,function (res3) {
console.log("真实接口调用完成。status:"+res3.statusCode)
res.writeHead(res3.statusCode, filterResHeader(res3.headers,res));
res3.pipe(res);
res3.on('end', function () {
});
})
if (/POST|PUT/i.test(req.method)) {
stream.pipe(req3);
} else {
req3.end();
}
req3.on('error', function (err) {
res.end(err.stack);
});
}
});
var stream;
if (/POST|PUT|PATCH/i.test(req.method))
{
stream=new pass();
req.pipe(stream);
req.pipe(req2);
}
else
{
req2.end();
}
req2.on('error', function (err) {
res.end(err.stack);
});
}
function handleHeader(req,res) {
if(!req.headers.origin)
{
return;
}
res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE");
res.setHeader("Access-Control-Allow-Credentials","true");
if(req.headers["access-control-request-headers"])
{
res.setHeader("Access-Control-Allow-Headers",req.headers["access-control-request-headers"])
}
res.setHeader("Access-Control-Expose-Headers","connection,content-length,date,x-powered-by,content-encoding,server,etag,accept-ranges,allow,content-language,set-cookie,doclever-request");
if(req.method=="OPTIONS")
{
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end();
return;
}
}
function redirect(res,bHttps,opt,location) {
var urlRedirect=location;
if(urlRedirect.startsWith("/"))
{
urlRedirect=(bHttps?"https://":"http://")+opt.host+":"+opt.port+urlRedirect;
}
var objUrl=url.parse(urlRedirect);
var request1,opt1;
if(objUrl.protocol=="http:")
{
opt1={
host: objUrl.hostname,
path: objUrl.path,
method: "GET",
port:objUrl.port?objUrl.port:80,
}
request1=http.request;
bHttps=false;
}
else
{
opt1={
host: objUrl.hostname,
path: objUrl.path,
method: "GET",
port:objUrl.port?objUrl.port:443,
rejectUnauthorized: false,
requestCert: true,
}
request1=https.request;
bHttps=true;
}
var req3=request1(opt1,function (res3) {
if(res3.statusCode==302)
{
redirect(res,bHttps,opt,res3.headers.location)
}
else
{
var resHeader=filterResHeader(res3.headers,res)
resHeader["doclever-request"]=JSON.stringify(handleSelfCookie(req3));
res.writeHead(res3.statusCode, resHeader);
res3.pipe(res);
res3.on('end', function () {
});
}
})
req3.end();
req3.on('error', function (err) {
res.end(err.stack);
});
}
function handleSelfCookie(req) {
var arr=req._headers;
arr["url"]=req.method+" "+req.path;
var cookie=arr["cookie"];
if(!cookie)
{
return arr;
}
var arrCookie=cookie.split(";");
var keys=["id","name","photo","qq","sex","company","phone","loginCount","age","email"];
arrCookie=arrCookie.filter(function (obj) {
obj=obj.trim();
for(let key of keys)
{
if(obj.startsWith(key+"="))
{
return false;
}
}
return true;
})
arr["cookie"]=arrCookie.join(";");
return arr;
}
function proxy(req,res) {
var bHttps=false;
if(req.headers["url-doclever"].toLowerCase().startsWith("https://"))
{
bHttps=true;
}
var opt,request;
if(bHttps)
{
opt= {
host: getHost(req),
path: req.headers["path-doclever"],
method: req.headers["method-doclever"],
headers: getHeader(req),
port:getPort(req),
rejectUnauthorized: false,
requestCert: true,
};
request=https.request;
}
else
{
opt= {
host: getHost(req),
path: req.headers["path-doclever"],
method: req.headers["method-doclever"],
headers: getHeader(req),
port:getPort(req)
};
request=http.request;
}
var req2 = request(opt, function (res2) {
if(res2.statusCode==302)
{
redirect(res,bHttps,opt,res2.headers.location)
}
else
{
var resHeader=filterResHeader(res2.headers,res)
resHeader["doclever-request"]=JSON.stringify(handleSelfCookie(req2));
res.writeHead(res2.statusCode, resHeader);
res2.pipe(res);
res2.on('end', function () {
});
}
});
if (/POST|PUT|PATCH/i.test(req.method)) {
req.pipe(req2);
} else {
req2.end();
}
req2.on('error', function (err) {
res.end(err.stack);
});
}
var arguments = process.argv.splice(2);
var mockUrl=arguments[0];
var realUrl=arguments[1];
var port=arguments[2]?arguments[2]:36742;
var server = http.createServer(onProxy);
server.listen(port);
console.log(arguments.length>0?("内网测试,Mock数据正监听端口:"+port):"正在运行中,请用DOClever的接口测试页面进行内网测试!");

net.js的更多相关文章

  1. Vue.js 和 MVVM 小细节

    MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...

  2. js学习笔记:操作iframe

    iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. JS调用Android、Ios原生控件

    在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...

  5. jquery和Js的区别和基础操作

    jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...

  6. 利用snowfall.jquery.js实现爱心满屏飞

    小颖在上一篇一步一步教你用CSS画爱心中已经分享一种画爱心的方法,这次再分享一种方法用css画爱心,并利用snowfall.jquery.js实现爱心满屏飞的效果. 第一步: 利用伪元素before和 ...

  7. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  8. JS正则表达式常用总结

    正则表达式的创建 JS正则表达式的创建有两种方式: new RegExp() 和 直接字面量. //使用RegExp对象创建 var regObj = new RegExp("(^\\s+) ...

  9. 干货分享:让你分分钟学会 JS 闭包

    闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...

  10. JS核心系列:理解 new 的运行机制

    和其他高级语言一样 javascript 中也有 new 运算符,我们知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象. 但在 javascript 中,万物皆对象,为什么还要通过 ...

随机推荐

  1. ogg同步DDL时,源和目标端表空间名称不同的解决思路

    在OGG同步过程中,经常会碰上有创建表或表空间的同步,往往因为源和目标的平台不同,如aix->linux or linux->windows,这两个平台的表空间也经常不同,在目标端执行DD ...

  2. 系统管理--配置Gitlab

    很多教程都有配这个,但这个又不能用于”源码管理”模块拉取代码,我一直很困惑这个配置有什么用,然后就找到了该插件的github项目地址才弄明白,链接:https://github.com/jenkins ...

  3. 【Diary】

    [写日记是好习惯] 前记 很随意的日记.想什么写什么,没有限制. 希望以后看到曾经,努力的自己比摸鱼的自己多. 2019.3 2019.3.29 第24次请假打卡 xzh:那些理科男以后都会当IT工作 ...

  4. Angular 中的数据交互(get jsonp post)

    Angular get 请求数据 Angular5.x 以后 get.post 和和服务器交互使用的是 HttpClientModule 模块. import {HttpClientModule} f ...

  5. 【Django模板进阶007】

    本节主要讲 Django模板中的循环,条件判断,常用的标签,过滤器的使用 列表,字典,类的实例的使用 循环:迭代显示列表,字典等中的内容 条件判断:判断是否显示该内容,比如判断是手机访问,还是电脑访问 ...

  6. 关于新写的js在浏览器f12的时候看不到解决办法

    这是由于浏览器缓存导致的,谷歌浏览器ctrl+shift+delete快捷键到清除浏览器数据清除即可.平时经常会遇到的,所以记录下.

  7. express之req res

    request对象和response对象 Request req.baseUrl 基础路由地址 req.body post发送的数据解析出来的对象 req.cookies 客户端发送的cookies数 ...

  8. C# 将对应的xml文档赋值给指定模型(对象)

    public static IList<T> XmlToEntityList<T>(string xml) where T : new()        {           ...

  9. Xilinx FPGA DPR技术

    动态部分重配置技术 DPR(Dynamic Partial Reconfiguration)可以使得PL的一个部分或几个部分在运行时刻被完全地重新配置.这些部分需要被指定为可重配置分区(Reconfi ...

  10. IntelliJ IDEA 和 Pycharm 破解

    关键网址:http://idea.lanyus.com/ 步骤: 1. 在http://idea.lanyus.com/上下载:JetbrainsCrack-2.9-release-enc.jar . ...