WHAT - 前端代理(二)- 正向代理和反向代理

发布于:2024-06-06 ⋅ 阅读:(91) ⋅ 点赞:(0)

一、正向代理和反向代理

正向代理和反向代理是两种常见的代理服务器工作模式。

正向代理(Forward Proxy)是代理服务器位于客户端和目标服务器之间的一种代理方式。客户端向代理服务器发送请求,代理服务器再将请求转发给目标服务器,并将响应返回给客户端。在这种情况下,目标服务器并不知道请求的真实客户端是谁,只能感知到代理服务器。正向代理常用于帮助客户端绕过网络限制,访问被封锁的资源,或者提供匿名性。

反向代理(Reverse Proxy)是代理服务器位于目标服务器和客户端之间的一种代理方式。客户端向反向代理服务器发送请求,反向代理服务器根据配置的规则将请求转发给后端的目标服务器,并将响应返回给客户端。在这种情况下,客户端并不知道真实的目标服务器是谁,只能感知到反向代理服务器。反向代理常用于负载均衡,提供高可用性和性能优化,同时还可以提供安全性和缓存等功能。

综上所述,正向代理和反向代理的主要区别在于代理服务器的位置和作用。正向代理是位于客户端和目标服务器之间,用于客户端访问目标服务器;而反向代理是位于目标服务器和客户端之间,用于客户端访问后端的目标服务器。

二、正向代理

首先我们需要启动一个node服务监听请求:

// hello.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {

  console.log('server get request...');

  // http.IncomingMessage (in http.Server)
  // 获取 http 请求的正文数据
  // request 对象在这里是一个流 因此必须监听要处理的主体内容,并且其是按数据块处理的
  let data = '';
  req.on('data', (chunk) => {
    console.log(`可用的数据块: ${chunk}`);
    data += chunk;
  })
  req.on('end', () => {
    console.log('req end');
  })
  console.log('req method', req.method);
  console.log('req httpVersion', req.httpVersion);

  // http.ServerResponse
  res.statusCode = 200;
  // response.statusCode = 500
  // response.statusMessage = '内部服务器错误'
  res.setHeader('Content-Type', 'text/plain');
  console.log('res headers: ', res.getHeaderNames());

  res.end('Welcome');
})
server.listen(port, hostname, () => {

  console.log(`server running at http://${hostname}:${port}`);

  // process env
  // console.log('process env: ', process.env);
  
  // process argv
  process.argv.forEach((val, index) => {
    console.log(`${index}: ${val}`);
  })
  const args = process.argv.slice(2);
  // 1.
  // node app.js joe
  // console.log('user argvs: ', args[0]);
  // 2.
  // node app.js --name=joe
  // node app.js --name joe
  // const argsMap = require('minimist')(args)
  // console.log('user argvs: ', argsMap['name']);
})

// 使用进程信号句柄来终止
// process.on('SIGTERM', () => {
//   server.close();
// })
// setTimeout(() => {
//   process.kill(process.pid, 'SIGTERM');
// }, 3000);

正向代理代码示例:

var http = require('http');
var url = require('url');

const hostname = '127.0.0.1';
const port = 8080;

http.createServer((req, res) => {

  var u = url.parse(req.url);
  var options = {
    hostname: '127.0.0.1',
    port: 3000,
    path: u.path,
    method: req.method,
    headers: req.headers
  };

  var proxyRequest = http.request(options, function(proxyResponse) {

    // 收到真实服务返回的 数据
    let data = '';
    proxyResponse.on("data", function(chunk) {

      console.log("proxy response: ", chunk);
      data += chunk;
    });
    proxyResponse.on("end", function() {

        console.log("proxy request ended");
        res.end(data);
    })

    console.log('write header status code: ', proxyResponse.statusCode);
    res.writeHead(proxyResponse.statusCode, proxyResponse.headers);
  });

  let data = '';
  req.on("data", function(chunk) {
    
    console.log(`可用的数据块: ${chunk}`);
    data += chunk;
    
    // 转发到代理请求
    proxyRequest.write(chunk, "binary");
  })

  req.on("end", function() {

    console.log("original request end");
    proxyRequest.end();
  })

  console.log('req method', req.method);
  console.log('req httpVersion', req.httpVersion);
}).listen(port, hostname, () => {

  console.log(`server running at http://${hostname}:${port}`);
});

三、反向代理

目前常用的功能完善的反向代理服务主要有 nginxapache httpdSquid 等。

代码示例:



var http = require('http'),
    httpProxy = require('http-proxy'),
    proxy = httpProxy.createProxyServer({}),
    fs = require('fs'),
    path = require('path');

const hostname = '127.0.0.1';
const port = 3000;

var getContentType = 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;
    var _file = _url.replace(/\?.*/ig, '');

    var _localPath,
        _localFile,
        _stream;

    var _ext = path.extname(_file);
    // http://127.0.0.1:3000/hello.js
    console.log('request _ext:', _ext);

    if(_ext) {

        // 1. 如果是静态资源文件,则本地读取

        // 转换成本地路径
        _localPath = '/Users/pharaoh.hong/Documents/pharaoh-project/documents/前端代理';
        _localFile = _localPath + _file;
        console.log('request file path: ', _localFile);
        if(fs.existsSync(_localFile)) {

            res.writeHead(200, { 'Content-Type': getContentType(_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>');
            });

            // 连接文件流和http返回流的管道
            _stream.pipe(res);

            _stream.on('end',function(){
                _stream = null;
            })
        } else {
            res.writeHead(404, {'Content-Type': 'text/html'});
            res.end('<h1>404 Not Found</h1>');
        }
    } else {

        // 如果不是静态资源文件,则发起请求
        proxy.web(req, res, { target: 'http://www.target.com' });
    }
});

server.listen(port, hostname, () => {

  console.log(`server running at http://${hostname}:${port}`);
})


网站公告

今日签到

点亮在社区的每一天
去签到