nodejshttp不走系统代理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nodejshttp不走系统代理相关的知识,希望对你有一定的参考价值。

现在使用的代理大部分为HTTP和Socket代理。 Socket代理更底层,需要本地解析域名,而HTTP代理则是基于HTTP协议之上的,不需要本地解析域名。下面我讲讲HTTP(S)代理的设计思路以及NodeJS代码实现。
<br/>
<br/><strong>HTTP协议</strong>
<br/>
<br/>HTTP协议简单说来就是浏览器把一串字符串发送到目标服务器,然后把目标服务器返回回来的一串字符串显示给用户。
<br/>
<br/>浏览器发送的这串字符主要分为两个部分,一部分是头,里面包含目标服务器域名,当前请求的文件路径等信息。另一部分是正文,一般的GET请求没有正文。
<br/>
<br/>服务器返回来的字符串也分为头和正文。
<br/>
<br/><strong>HTTP代理原理</strong>
<br/>
<br/>HTTP代理需要做的事情就是接收浏览器发来的请求字符串,再从请求字符串的头部分找出浏览器请求的目标主机,然后直接把这串请求字符串发给目标主机,再把目标主机返回的数据发给浏览器。 “什么?就这么简单?” “呃。。是啊,但这还没完。。”
<br/>
<br/>现代浏览器一般都是默认采用HTTP/1.1版本,并且默认会发送Connection: keep-alive请求。 这些信息是写在请求的头部的,意思是通知目标服务器采用keep-alive技术继续处理后续的请求。 但是我们做的代理程序要想支持keep-alive是比较麻烦的。所以干脆就把这个篡改成Connection: close。 这样就可以保证浏览器请求的每个文件都会单独发送一个HTTP请求。
<br/>
<br/><strong>下面是NodeJS代码实现</strong>
<br/><pre escaped=“true” lang=“javascript”>var net = require(‘net’);
<br/>var local_port = 8893;
<br/>
<br/>//在本地创建一个server监听本地local_port端口
<br/>net.createServer(function (client)
<br/>
<br/>
<br/> //首先监听浏览器的数据发送事件,直到收到的数据包含完整的http请求头
<br/> var buffer = new Buffer(0);
<br/> client.on(‘data’,function(data)
<br/>
<br/> buffer = buffer_add(buffer,data);
<br/> if (buffer_find_body(buffer) == -1) return;
<br/> var req = parse_request(buffer);
<br/> if (req === false) return;
<br/> client.removeAllListeners(‘data’);
<br/> relay_connection(req);
<br/> );
<br/>
<br/> //从http请求头部取得请求信息后,继续监听浏览器发送数据,同时连接目标服务器,并把目标服务器的数据传给浏览器代理的出现是因为浏览器同源策略的存在
服务端实现代理的例子和方法很多 比如nginx 反向代理解决生产环境的跨域问题
再有http-server等一些第三方的包帮我处理 基本达到了开箱即用的体验
通常我们所说的代理来源于http1.1的定义,代理扮演的是「中间人」角色,对于连接到它的客户端来说,它是服务端;对于要连接的服务端来说,它是客户端。它就负责在两端之间来回传送 HTTP 报文
假如我通过代理访问A网站,对于A来说,它会把代理当做客户端,完全察觉不到真正客户端的存在,这实现了隐藏客户端IP的目的。
但是他们到底是如何实现的 ,值得一探究竟,下面是用原生nodejs 写个以后个代理

const http = require("http");
const url = require("url");
//首先启动本地服务器
http.createServer(function(req, res)
//客户端请求有两种方式,可以是对象,也可以是url字符串
//1.这里采取的是对象形式,包括url对象以及headers
var options = url.parse(req.url);
options.headers = req.headers;
//2.如果采取字符串形式,就传入一个完整的url字符串,node会自动解析成url对象

//通过客户端请求新建一个代理服务器
//代理请求仿照本地请求头的数据
var proxyRequest = http.request(options, function(proxyResponse) //代理请求获取的数据再返回给本地res
proxyResponse.on('data', function(chunk)
console.log('proxyResponse length:', chunk.length);
res.write(chunk, 'binary');
);
//当代理请求不再收到新的数据,告知本地res数据写入完毕。
proxyResponse.on('end', function()
console.log('proxied request ended');
res.end();
);

res.writeHead(proxyResponse.statusCode, proxyResponse.headers);
);

//data只有当请求体数据进来时才会触发
//尽管没有请求体数据进来,data还是要写,否则不会触发end事件
req.on('data', function(chunk)
console.log('in request length:', chunk.length);
proxyRequest.write(chunk, 'binary');
);

req.on('end', function()
//向proxy发送求情,这里end方法必须被调用才能发起代理请求
//所有的客户端请求都需要通过end来发起
proxyRequest.end();
);

).listen(8080);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
以上代码的核心思想就是用http.request充当了中间人的角色 帮我们去目标地址取数据然后在把得到的数据传回去。可以看作是设计模式中代理模式的一种实践
参考技术A 原因是我们的网络使用的是一个NTLM代理,它需要ISA客户端在我们的机器上运行,但它没有在另一台机器上运行。在该计算机上安装ISA客户端允许流量正常通过代理。

问题 C: 小灰才不走迷宫

题目描述

“你以为小灰要去走迷宫?我小灰才不走迷宫!作为一个长期潜伏在逸夫楼管道系统里的灰鼠,我才不会在管道里迷路·……迷路…·路········….天哪!
我在哪∑( 口 ||!!!我在管道里迷路啦∑( 口 ||!!!!!!!!!!!谁来救救我!!!!!!!!!!!!!!!“

以上是我们和拥有灰数的灰鼠小灰失去联系之前所收到的最后一段通讯。现在,我们只知道小灰被困在了逸夫楼的网状管道中,但是却不知道他的位置,所以只能展开地毯式搜索!营救小灰刻不容缓!

要知道,管道的环境极其恶劣,小灰怕是撑不了多久,所以我们必须迅速采取行动,营救小灰迫在眉睫!但是,只是着急是没有用的,想要拯救小灰,必须要动脑子!管道实在太窄了,直接进去显然不可能,所以我们从隔壁社团借来了救援机器人,这种机器人可以深入管道内部,探测管道内部的情况。

经过一番勘探,我们大致摸清了管道内部的情况,原来,管道有许多的岔路,列如形如“丄ㄒ”的丁字路,形如“十”的十字路,,形如“7「”的转弯,还有形如“I-”的直路,最神奇的是,最神奇的是,管道中竟然还有灰鼠用灰数制作的形如“O Q”传送

尽管情况复杂,但是这可难不倒聪明的ACMers,经过一番讨论,我们抽象出了管道情况的表示方式:

一、数字1表示该点为不能向右通行的丁字路口,即在该点只能向上向左和向下移动,不能向右移动,也不能从右侧移动到该点。

二、数字2表示该点为不能向左通行的丁字路口

三、数字3表示该点为不能向上通行的丁字路口

四、数字4表示该点为不能向下通行的丁字路口

五、数字5表示该点为可以向四个方移动的十字路口

六、数字6表示该点为能向左右移动的管道

七、数字7表示该点为能向上下移动的管道

八、数字0表示此路不通

九、数字c表示该点为能向左和向下移动的弯道

十、数字d表示该点为能向右和向下移动的弯道

十一、字母a表示该点为能向上和向左移动的弯道

十二、字母b表示该点为能向上和向右移动的弯道

十三、字母O和Q表示两个可以互相传送的传送门(地图上保证有且只有一组传送门),进入传送门后必定会被传送,可以从任意方向进入传送门,传送结束后将到达另一传送门,
之后可以从传送门向任意可移动的方向移动。

十四、字母s表示救援队的出发点

十五、字母t表示小灰的位置

假设救援机器人在管道中每移动一个格子需要消耗的时间为1,每使用一次传送门所需要的时间为1,情况紧急,现在请你计算出救出小灰最少需要多长时间。

输入格式

每个测试点包含一组数据,每组数据的第一行包含两个用空格隔开的整数n,m,表示网格的大小为n行m列,
接来n行,有一个n行m列的地图,其中第i行j列的符号表示地图中第i行j列的位置的物体种类。

输出格式

请你输出营救小灰所需要的最短时间。(题目保证一定能救出小灰!)

输入样例

5 5
s333c
0ba77
d5Oa7
2555a
b4Q5t

输出样例

9

解题思路

一道模拟加广搜的题,模拟重点在管道的连通上,画图比较清楚,比赛的时候没画图,没写函数,四个方向全写在了bfs里,if里面套for,for里面套if//着实是看吐了

AC代码

#include <bits/stdc++.h>
#define fr(i,p) for(int i=0;i<p;i++)
using namespace std;
int dir[][2]=1,0,-1,0,0,1,0,-1;//下 上 右 左
const int maxn=1e2+5;
char mp[maxn][maxn];
int n,m,s_x,s_y,Q_x,Q_y,O_x,O_y;
struct cpint x,y,s;cp(int xx,int yy,int ss):x(xx),y(yy),s(ss);
queue <cp> myq;
bool book[maxn][maxn];
void init()//初始化

    fr(i,n)fr(j,m)
    
        book[i][j]=0;//clear标记数组
        if(mp[i][j]=='s')s_x=i,s_y=j;//找营救队的位置
        else if(mp[i][j]=='Q')Q_x=i,Q_y=j;//找Q的位置
        else if(mp[i][j]=='O')O_x=i,O_y=j;//找O的位置
    

/*****************左左左左左**********************/
void run_left(int tx,int ty,cp temp)

    //当前这个点能否往左走
    if(mp[temp.x][temp.y]=='2'||mp[temp.x][temp.y]=='7'
       ||mp[temp.x][temp.y]=='d'||mp[temp.x][temp.y]=='b')
        return ;
    //当前这个点能否从左边过来
    if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
        mp[tx][ty]=='1'||mp[tx][ty]=='7'||mp[tx][ty]=='0'
        ||mp[tx][ty]=='a'||mp[tx][ty]=='c')
        return ;
    else
        myq.push(cp(tx,ty,temp.s+1));

/******************下下下下下*********************/
void run_down(int tx,int ty,cp temp)

    //当前这个点能否往下走
    if(mp[temp.x][temp.y]=='4'||mp[temp.x][temp.y]=='6'
       ||mp[temp.x][temp.y]=='a'||mp[temp.x][temp.y]=='b')
        return ;
    //当前这个点能否从下边过来
    if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
        mp[tx][ty]=='3'||mp[tx][ty]=='6'||mp[tx][ty]=='0'
        ||mp[tx][ty]=='c'||mp[tx][ty]=='d')
        return ;
    else
        myq.push(cp(tx,ty,temp.s+1));

/***************上上上上上************************/
void run_up(int tx,int ty,cp temp)

    //当前这个点能否往上走
    if(mp[temp.x][temp.y]=='3'||mp[temp.x][temp.y]=='6'
        ||mp[temp.x][temp.y]=='c'||mp[temp.x][temp.y]=='d')
        return ;
    //当前这个点能否从上面过来
    if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
        mp[tx][ty]=='4'||mp[tx][ty]=='6'||mp[tx][ty]=='0'
        ||mp[tx][ty]=='a'||mp[tx][ty]=='b')
        return ;
    else
        myq.push(cp(tx,ty,temp.s+1));

/**************右右右右右*************************/
void run_right(int tx,int ty,cp temp)

    //当前这个点能否往右走
    if(mp[temp.x][temp.y]=='1'||mp[temp.x][temp.y]=='7'
       ||mp[temp.x][temp.y]=='c'||mp[temp.x][temp.y]=='a')
        return ;
    //当前这个点能否从右过来
    if(tx<0||tx>=n||ty<0||ty>=m||book[tx][ty]==1||
        mp[tx][ty]=='2'||mp[tx][ty]=='7'||mp[tx][ty]=='0'
        ||mp[tx][ty]=='b'||mp[tx][ty]=='d')
        return ;
    else
        myq.push(cp(tx,ty,temp.s+1));

void bfs()

    myq.push(cp(s_x,s_y,0));
    while(!myq.empty())
    
        cp temp=myq.front();
        if(mp[temp.x][temp.y]=='t')//营救出口
        
            cout<<temp.s<<endl;
            return ;
        
        if(mp[temp.x][temp.y]=='Q'&&book[O_x][O_y]==0)//传送
            myq.push(cp(O_x,O_y,temp.s+1));
        if(mp[temp.x][temp.y]=='O'&&book[Q_x][Q_y]==0)//传送
            myq.push(cp(Q_x,Q_y,temp.s+1));
        fr(i,4)// 下 上 右 左
        
            int tx=temp.x+dir[i][0];
            int ty=temp.y+dir[i][1];
            switch(i)
            
                case 0:run_down(tx,ty,temp);break;
                case 1:run_up(tx,ty,temp);break;
                case 2:run_right(tx,ty,temp);break;
                case 3:run_left(tx,ty,temp);break;
            
        
        book[temp.x][temp.y]=1;
        myq.pop();
    

int main()

    while(cin>>n>>m)
    
        fr(i,n)fr(j,m)cin>>mp[i][j];
        init();
        bfs();
    
    return 0;

以上是关于nodejshttp不走系统代理的主要内容,如果未能解决你的问题,请参考以下文章

如何让app不走系统代理?

Mac 命令行 Command Line 配置代理, 配置白名单

抓包代理与软件代理产生冲突

火狐浏览器代理服务器拒绝连接的解决方案

android WIFI 设置代理代码 4.4.3——5.0

Privoxy 安装配置