一、简介,用nodejs实现简单的http代理案例

步骤1:新建文件夹、在当前路径打开命令行输入 npm init 回车初始化项目,然后就有了 package.json 文件

步骤2:安装express,搭建简易服务器

安装express:npm i express -S

安装完成后,新建 index.js 文件,代码如下:

const express = require('express');
const app = express();
const port = 3000;    //端口号

//监听请求 *代表所有的请求路径。
//也可指定请求路径,如/text,则只能接收http://localhost:3000/text的请求
app.get('*', (req, res) => {
  res.send('Hello World!');
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

  然后命令行执行 node index.js, 看到打印 Example app listening at http://localhost:3000,就说明服务已经跑起来了

  在浏览器访问 http://localhost:3000,看到 Hello World!,说明运行的服务收到请求并且正常返回结果了

步骤3:使用request模块转发http请求,得到结果并返回

安装request:npm i request -S

const express = require('express');
const app = express();
const port = 3000;    //端口号
const request = require('request');

//监听请求 *代表所有的请求路径。
//也可指定请求路径,如/text,则只能接收http://localhost:3000/text的请求
app.get('*', (req, res) => {
  //接收要转发的http地址
  let url = req.url.substr(1);
  if(url.startsWith('http')){
    const options = {
      url,
      method:"GET",
      //headers: req.headers    //如果需要设置请求头,就加上
    }
    request(options, function (error, response, body) {
      if (!error && response.statusCode === 200) {
        //拿到实际请求返回的响应头,根据具体需求来设置给原来的响应头
        let headers = response.headers;
        res.setHeader('content-type',headers['content-type']);
        res.send(body);
      } else {
        res.send(options);
      }
    });
  }
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

在命令行重新运行 index.js,ctrl + c 终止运行再 node index.js 。

然后在浏览器访问 http://localhost:3000/https://www.baidu.com/,看到 百度搜索的界面,说明代理请求成功了 

到了这里,相信读者应该可以看出具体用法了,http://localhost:3000/https://www.baidu.com/后面红色部分就是具体要转发的请求

需要注意的是,这个代码是用来代理ajax请求的,像上面的例子请求的是百度的界面,这个是为了测试,有些网页可能无法打开。

还有就是,需要根据你的实际情况来修改,比如你请求的接口需要修改请求头如content-type之类的

 步骤4:代理post请求

前面只实现了get请求代理,要代理post请求还需要安装一个模块(body-parser)来获取请求体

安装body-parser: npm i body-parser -S

const express = require('express');
const app = express();
const port = 3000;    //端口号
const request = require('request');
var bodyParser = require('body-parser')
//只要加入这个配置,在req请求对象上会多出来一个属性
//parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
//parse application/json
app.use(bodyParser.json())

//监听请求 *代表所有的请求路径。
//也可指定请求路径,如/text,则只能接收http://localhost:3000/text的请求
app.get('*', (req, res) => {
  //接收要转发的http地址
  let url = req.url.substr(1);
  if(url.startsWith('http')){
    const options = {
      url,
      method:"GET",
      //headers: req.headers    //如果需要设置请求头,就加上
    }
    request(options, function (error, response, body) {
      if (!error && response.statusCode === 200) {
        //拿到实际请求返回的响应头,根据具体需求来设置给原来的响应头
        let headers = response.headers;
        res.setHeader('content-type',headers['content-type']);
        res.send(body);
      } else {
        res.send(options);
      }
    });
  }
})

app.post('*', (req, res) => {
  console.log(req.headers)
  console.log(req.body)
  let url = req.url.substr(1);
  if(url.startsWith('http')){
    const options = {
      url,
      method: 'POST',
      json: req.body,    //content-type是application/json的时候使用,其它请查看requiest用法
      headers: {
        token: req.headers.token,
        'content-type': req.headers['content-type']
      }
    }
    request(options, function (error, response, body) {
      console.log(body,response,error)
      if (!error) {
        let headers = response.headers;
        res.setHeader('content-type',headers['content-type']);
        // for(let key in headers){
        //   res.setHeader(key,headers[key]);
        // }
        console.log(body)
        res.send(body);
      } else {
        res.send(options);
      }
    });
  }
  // res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

重新运行 index.js 就可以代理post请求了,用postMan测试通过

同样需要注意的是请求头和响应头,以及参数的传递

本案例是经过本地测试过的,但是毕竟接口要求可能不一样,所以有些需要修改才能使用

步骤5:如果遇到跨域 

加入以下代码允许跨域

// 允许跨域
app.all('*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", '*');
  res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
  res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
  res.header("Access-Control-Allow-Credentials","true");
  if(req.method === "OPTIONS") res.send(200);
  else  next();
});

完整代码:

const express = require('express');
const app = express();
const port = 3000;    //端口号
const request = require('request');
var bodyParser = require('body-parser')
//只要加入这个配置,在req请求对象上会多出来一个属性
//parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
//parse application/json
app.use(bodyParser.json())

// 允许跨域
app.all('*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", '*');
  res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
  res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
  res.header("Access-Control-Allow-Credentials","true");
  if(req.method === "OPTIONS") res.send(200);
  else  next();
});

//监听请求 *代表所有的请求路径。
//也可指定请求路径,如/text,则只能接收http://localhost:3000/text的请求
app.get('*', (req, res) => {
  //接收要转发的http地址
  let url = req.url.substr(1);
  if(url.startsWith('http')){
    const options = {
      url,
      method:"GET",
      //headers: req.headers    //如果需要设置请求头,就加上
    }
    request(options, function (error, response, body) {
      if (!error && response.statusCode === 200) {
        //拿到实际请求返回的响应头,根据具体需求来设置给原来的响应头
        let headers = response.headers;
        res.setHeader('content-type',headers['content-type']);
        res.send(body);
      } else {
        res.send(options);
      }
    });
  }
})

app.post('*', (req, res) => {
  console.log(req.headers)
  console.log(req.body)
  let url = req.url.substr(1);
  if(url.startsWith('http')){
    const options = {
      url,
      method: 'POST',
      json: req.body,    //content-type是application/json的时候使用,其它请查看requiest用法
      headers: {
        token: req.headers.token,
        'content-type': req.headers['content-type']
      }
    }
    request(options, function (error, response, body) {
      console.log(body,response,error)
      if (!error) {
        let headers = response.headers;
        res.setHeader('content-type',headers['content-type']);
        // for(let key in headers){
        //   res.setHeader(key,headers[key]);
        // }
        console.log(body)
        res.send(body);
      } else {
        res.send(options);
      }
    });
  }
  // res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐