用CBrother脚本实现的一个http代理服务器,解决跨域问题
之前做一个需求,需要帮用户管理几百个路由器的IP、用户名、密码,在网页上点击一个按钮后就要直接进入路由器并自动登录。
寻找了好多方案,大部门路由器都有跨域问题,非常头大。
后面想着必须把路由器的页面代理到同一个地址下面,然后在嵌到到ifram里面才能操作它的账号密码框与登录按钮,还是用cbrother解决了这个问题,记录一下。
import CBHttp.code
var g_selfurl = "192.168.1.100";//服务器自己的IP,所有中转都要把服务器IP换成对端IP
class ProxyAction //中转响应类
{
function DoAction(request,respon)
{
respon.addProperty("Access-Control-Allow-Origin","*");//添加跨域权限
var clientReq = new HttpClientRequest(); //请求目标的客户机对象
clientReq.setMethod(request.getMethod());
var targeturl = null;
var cookieCnt = request.getCookieCount();//添加cookie
if(cookieCnt > 0)
{
for(var i = 0 ; i < cookieCnt ; i++)
{
var cookie = request.getCookie(i);
if(cookie.getName() == "targeturl")//自己记录的目标IP不要添加
{
targeturl = cookie.getValue();
print "targeturl:" + targeturl;
continue;
}
clientReq.addCookie(cookie);
}
}
if(targeturl == null)//targeturl == null 为什么null有时候显示不出来?
{
respon.write("not find ip!");
respon.flush();
return;
}
var propertyMap = request.getAllProperty();
propertyMap.begin();
//添加所有头
do
{
var key = propertyMap.getKey();
var value = propertyMap.getValue();
value = strreplace(value,g_selfurl,targeturl);//替换服务器地址为对方地址
clientReq.addProperty(key,value);
} while(propertyMap.next());
var url = "http://" + targeturl + "/";
if(request.getUrl() != "index.html")
{
url += request.getUrl();
}
var allparm = request.getAllParm();//添加url后面的参数
if(allparm.size() > 0)
{
var isFirst = true;
url += "?";
allparm.begin();
do
{
if(!isFirst)
{
url += "&";
isFirst = false;
}
url += allparm.getKey();
url += "=";
url += allparm.getValue();
}while(allparm.next());
}
print url;
clientReq.setUrl(url);
var data = request.getData();
if(data != null)
{
clientReq.addData(data);
}
var clientRespon = clientReq.flush();//发起请求
respon.setStatus(clientRespon.getStatus());
var clientMap = clientRespon.getAllProperty();
//把对方返回头返回给浏览器
if(clientMap.size() > 0)
{
clientMap.begin();
do
{
var key = clientMap.getKey();
var value = clientMap.getValue();
// print key + ":" + value;
respon.addProperty(key,value);
} while(clientMap.next());
}
//把对方返回的cookie返回给浏览器
var resCookieCnt = clientRespon.getCookieCount();
for(var i = 0 ; i < resCookieCnt ; i++)
{
var cookie = clientRespon.getCookie(i);
respon.addCookie(cookie);
}
//返回数据
data = clientRespon.getData();
respon.write(data);
respon.flush();
}
}
class LoginAction
{
function DoAction(request,respon)
{
respon.addProperty("Access-Control-Allow-Origin","*");
var targeturl = request.getParm("ip");//获取要代理的地址
//如果地址写成自己了不支持
if(strfind(targeturl,g_selfurl) != null || strfind(targeturl,"127.0.0.1") != null)
{
respon.write("ip err!");
respon.flush();
return;
}
respon.addCookie(new Cookie("targeturl",targeturl));
var file = new File(GetRoot() + "webroot/login.html");//返回自己的网页,这个就和代理的网页在同一个域里面了,把它嵌到ifram里面想怎么操作就怎么操作
var size = file.size();
var readbuf = file.read(size);
respon.write(readbuf);
respon.flush();
file.close();
}
}
function main(parm)
{
var httpServer = new HttpServer();
httpServer.closeFileService(); //关闭文件下载服务,请求文件也要中转
httpServer.setThreadCount(50);
httpServer.setOutTime(5);
httpServer.addAction("proxy.cb",new ProxyAction());//添加代理接口
httpServer.addAction("remotelogin.cb",new LoginAction());//请求开始的接口
httpServer.set404Action("proxy.cb");//设置404接口名字,这样除了remotelogin.cb之外的所有连接都会走到这里
//httpserver.setHttpsCertFile("e:/aa.crt","e:/aa.key"); //也支持https,只是你要设置自己的证书
httpServer.startServer(80);
while(1)
{
Sleep(1000);
}
}
页面代码
<html lang="zh-CN">
<head>
<title>代理</title>
<iframe id="mywin" frameborder="0" align="left" width="1024" height="1024">
加载中
</iframe>
<script>
var iframe = document.getElementById("mywin");
iframe.src = "http://192.168.1.100";
iframe.onload = function()
{
iframe = document.getElementById("mywin");
var targetdiv = iframe.contentDocument.getElementById("main");
var html = "<div>我修改了你的网页<div>" + targetdiv.innerHTML;
targetdiv.innerHTML = html;
}
</script>
</head>
</html>
这样你再浏览器输入自己服务器IP http://192.168.1.100/remotelogin.cb?ip=www.cbrother.net
网页被我们修改了。
其实也可以不嵌入到ifram里面,在中转的时候抓住html添加进自己的js代码也是完全可以的。