首页 > 代码库 > [前端]代理知识入门介绍

[前端]代理知识入门介绍


主要目的是帮助我们了解代理和反向代理,以及熟悉它们的工作原理,帮助我们更好的在开发过程中进行使用,提高工作效率。

本内容主要围绕Http反向代理进行介绍,其他不常用的代理大家可自行了解。

什么是代理?代理有哪些类型?

代理(英语:Proxy),也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。

协议

  • HTTP RFC 7230 - HTTP/1.1: Message Syntax and Routing
  • SOCKET Tunneling TCP based protocols through Web proxy servers

功能

  1. 提高访问速度: 通常代理服务器都设置一个较大的缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
  2. 隐藏真实IP(网络安全)。
  3. FQ:允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。
  4. 负载均衡。

种类

根据协议区分

FTP代理服务器、HTTP代理服务器、SSL/TLS代理、RTSP代理、Telnet代理、POP3/SMTP代理、SOCKS代理

根据类型区分

正向代理、反向代理、透明代理、分布式代理等

什么是反向代理?

反向代理是代理服务器的一种。它根据客户端的请求,从后端的服务器(如Web服务器)上获取资源,然后再将这些资源返回给客户端。

功能

  • 加密和SSL加速
  • 负载平衡
  • 缓存静态内容
  • 压缩
  • 安全
  • 隔离内外网

和正向代理的区别

  1. 正向代理需要客户端进行设置,在网络请求中设置代理地址;而反向代理不需要客户端进行任何设置。
  2. 客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端;反向代理正好相反,对于客户端而言它就像是原始服务器。客户端向反向代理 的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容 原本就是它自己的一样。
  3. 正向代理允许客户端通过它访问任意网站并且隐藏客户端自身;反向代理对外都是透明的,访问者并不知道自己访问的是一个代理。

常见的反向代理

由于代理本身只是一种网络通信模式,所以只要遵循相应的协议规则,任何人都可以开发属于自己的反向代理服务;目前常用的功能完善的反向代理服务主要有nginx、apache httpd、Squid等。

Nginx 反向代理设置

轻量级,目前使用最广泛,Mac需要安装Nginx才可使用。

注:仅介绍反向代理相关内容,不研究nginx

proxy_pass http://127.0.0.1:88;   # 核心配置
proxy_redirect off;       # 后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header X-Real-IP $remote_addr; 
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
# 以下是一些反向代理的配置,可选。
proxy_set_header Host $host;
client_max_body_size 10m;    #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k;       #缓冲区代理缓冲用户端请求的最大字节数,
proxy_connect_timeout 90;      #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 90;      #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 90;    #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 4k;    #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k;   #proxy_buffers缓冲区,网页平均在32k以下的设置
proxy_busy_buffers_size 64k;     #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 64k;    #设定缓存文件夹大小,大于这个值,将从upstream服务器传

Apache 反向代理设置

重量级,功能强大,历史悠久,但Mac自带Apache服务,启动就好!

MAC中的目录:/etc/apache2
启动命令:sudo apachectl start 或 sudo apachectl restart

#off表示开启反向代理,on表示开启正向代理ProxyRequests Off
 ProxyMaxForwards 100
 ProxyPreserveHost On

 ProxyPass / http://www.junjunfudao.com/
 ProxyPassReverse / http://www.junjunfudao.com/

前端与反向代理

前端开发本来并不关心反向代理问题,但如果为了提高前端代码的运行效率和开发体验。非常有必要加深对服务器端web容器配置的了解。而反向代理的应用对于提高前端工程的开发效率有很大帮助。

JS如何实现代理

  • 正向代理实现方式

    /**
     * 正向代理示例
     */
    var http = require(‘http‘);
    var url = require(‘url‘);
    function request(cReq, cRes) {
        var u = url.parse(cReq.url);
        var options = {
            hostname: ‘http://www.junjunfudao.com‘,
            port: u.port || 80,
            path: u.path,
            method: cReq.method,
            headers: cReq.headers
        };
        
        var pReq = http.request(options, function(pRes) {
            cRes.writeHead(pRes.statusCode, pRes.headers);
            pRes.pipe(cRes);
        }).on(‘error‘, function(e) {
            cRes.end();
        });
        cReq.pipe(pReq);
    }
    http.createServer().on(‘request‘, request).listen(8080, ‘0.0.0.0‘);

     

  • 反向代理实现方式(使用http-proxy包来实现)

    /**
     * 反向代理示例
     */
    var http = require(‘http‘),
        httpProxy = require(‘http-proxy‘),     //http-proxy
        proxy = httpProxy.createProxyServer({}),
        fs = require(‘fs‘),
        path = require(‘path‘)
    var getConType = function (ext) {
        switch(ext){
            case ‘.html‘:
                return ‘text/html‘;
            case ‘.js‘:
                return ‘text/javascript‘;
            case ‘.css‘:
                return ‘text/css‘;
            case ‘.gif‘:
                return ‘image/gif‘;
            case ‘.jpg‘:
                return ‘image/jpeg‘;
            case ‘.png‘:
                return ‘image/png‘;
            case ‘.ico‘:
                return ‘image/icon‘;
            default:
                return ‘application/octet-stream‘;
        }
    };
    var server = http.createServer(function(req, res) {
        var _url = req.url; //获取请求的url
        var _file = _url.replace(/\?.*/ig,‘‘);
        var _localPath,
            _localFile,
            _stream;
        var _ext = path.extname(_file); // 文件扩展
        if(_ext){    // 如果是静态资源文件,则总本地读取
            //转换成本地路径
            _localPath = ‘/Users/yangyang.zhang/Work/wenba/fudao_activity/static/‘;
            _localFile = _localPath+_file;
            //判断文件是否存在
            if(fs.existsSync(_localFile)){//如果文件存在
                res.writeHead(200, {‘Content-Type‘: getConType(_ext) });
                _stream = fs.createReadStream(_localFile, {flags : ‘r‘, encoding : null});//只读模式 读取文件内容
                _stream.on(‘error‘,function(){//如果读取错误 返回404
                    res.writeHead(404, {‘Content-Type‘: ‘text/html‘});
                    res.end(‘<h1>404 Read Error</h1>‘);
                });
                _stream.pipe(res);//连接文件流和http返回流的管道,用于返回实际Web内容
                _stream.on(‘end‘,function(){
                    _stream = null;
                })
            }else{//返回404错误
                res.writeHead(404, {‘Content-Type‘: ‘text/html‘});
                res.end(‘<h1>404 Not Found</h1>‘);
            }
        }else{
            proxy.web(req, res, {target: ‘http://www.junjunfudao.com‘});
        }
    });
    console.log(‘listening on port 8080‘)
    server.listen(8080);

     

  • 反向代理实现  (使用request模块来实现)

    /**
     * 反向代理示例:使用request模块来实现反向代理
     */
    var nodeStatic = require(‘node-static‘).Server;
    var request = require("request");
    var fs = require(‘fs‘);
    var fileServer = new nodeStatic(fs.realpathSync("/Users/yangyang.zhang/Work/wenba/fudao_activity/static/"));
    var http = require("http");
    var httpServer = http.createServer(function(req, res) {
        var body =‘‘;
        req.addListener(‘data‘, function(chunk){
            body += chunk;
        })
        req.addListener(‘end‘, function() {
            fileServer.serve(req, res, function(err, result) {
                if (err && (err.status === 404)) {
                    var p = ‘http://qa01-activity.xuebadev.com‘+req.url;
                    req.headers[‘Host‘] = ‘qa01-activity.xuebadev.com‘;
                    request({
                        method: req.method,
                        url: p,
                        headers: req.headers,
                        body: body
                    }).pipe(res);
                }
            });
        }).resume();
    });
    httpServer.listen(8080);
    console.log(‘proxy listen in 8080‘);
    
    
    

     

参考文献

  1. 代理服务器-维基百科
  2. 正向代理与反向代理的区别
  3. NodeJS实现反向代理
  4. Nodejs实现一个http反向代理
  5. 用 nodejs 做反向代理服务器
  6. Nginx 配置介绍

[前端]代理知识入门介绍