nodejs中http-proxy使用小结

最近在写xmocker的工具,用于开发前期的mock数据,不可避免的用到了代理的中间件。当然,github上有关于http-proxy封装的中间件。毕竟是自己练手的项目,就自己写了个中间件,方便定制功能。

http-proxy库用于koa中,是使用它的 proxy.web方法。常规的用法是:

proxy.web(req, res, { target: ‘http://mytarget.com:8080‘ }, function(e) { ... });

项目中的要求是将API代理到用户填写的网址上去。Koa提供了req和res,用户提供了网址,这样中间件就很容易写了

function proxyTo({ status }) {
  return async function (ctx, next) {
    return next().then(async () => {
      if (status === undefined || ctx.status === status) {
        let data
        try {
          data = await proxy.web(ctx.req, ctx.res)
        } catch (e) {
          if (err) console.log(err)
          return
        }
      }
    })
  }
}

  设置访问结果为404则进行代理,否则不进行代理。然后在koa的中间件中use这个函数就可以了。

  基础应用这样自然就可以了,可是遇到POST的时候就不行了,因为用到了koa-bodyparser,导致post的请求没法发给服务器。在http-proxy的issue中到处找解决办法,终于找到了让req重新stream的方法。

proxy.on(‘proxyReq‘, function (proxyReq, req, res, options) {
    if (req.body) {
      let bodyData = JSON.stringify(req.body)
      // incase if content-type is application/x-www-form-urlencoded -> we need to change to application/json
      proxyReq.setHeader(‘Content-Type‘, ‘application/json‘)
      proxyReq.setHeader(‘Content-Length‘, Buffer.byteLength(bodyData))
      // stream the content
      proxyReq.write(bodyData)
    }
  })

  嗯,这样基本就完成了一个Proxy的中间件。

  刚开始用起来还不错,至少普通的API都可以转发了。于是试着代理到公司的API系统,网页端也没发现什么问题。然后用fiddler代理安卓客户端,用正则代理链接至自己的服务,出现了乱码。。。客户端用的是okhttp发出的请求,fiddler上看转发回来的json数据明明是正常的,结果在手机上中文就是不正确,都是十六进制代码,根本没解析。仔细对比:编码?都是utf-8,这个没问题。gzip?我明明是用的pipe过去,代码原封不动啊。我试中捕获了所有数据,用gzip解码后,也是正确的,那为什么会出错呢?

  和别人交流了好久也没找到问题。没办法,到代码中找找。对于请求的header,发现cookie貌似少了一条,就看看header转发时候怎么处理的。结果发现,header全是进行转换的。issue中有提到set-cookie多条的问题,我这也是这个情况,尝试着看看这个文件改动记录,意外发现了一个Option项 :preserveHeaderKeyCase。

  nodejs中header都是小写的形式,所以http-proxy中就进行了转换,将请求全部header转为小写。于是改了了true,这样就不再转换了。然后,客户端正常了!!!哈哈,仔细一看,cookie还是不是多条。算了,先不管cookie了,至少普通登录没啥问题了。

  另外加个changeOrigin为true可以防止有些服务器path取的是初始域名,出现404的问题。暂时就这么多啦。proxy插件的地址在:

https://github.com/wenlonghuo/xmocker/blob/master/app/plugin/proxy.js

欢迎试用我的Mock工具:

https://github.com/wenlonghuo/xmocker-cli

时间: 2024-11-09 02:02:18

nodejs中http-proxy使用小结的相关文章

Etag缓存在PHP和NodeJS中的实现

HTTP 提供了许多页面缓存的方案,其中属 Etag 和 Last-Modified 应用最广.本文会先介绍 Etag 的应用场景,然后说说他在 php 和 node 中的使用. 本文地址:http://www.cnblogs.com/hustskyking/p/etag-in-node.html,转载请注明源地址. 一.Etag的使用 客户端和浏览器之间的交互: +---------+ 1 +---------+ | |---------------->| | | | 2(200,OK) |

Node.js(十二)——NodeJs中的Promise

爬虫基于回调和事件的方式去实现,回调也是被诟病已久的问题尤其是callback这种,无论是阅读还是调试都很费劲,甚至我们连代码的堆栈都看不到,这是一种反人类的写法,Promise来拜托这种痛苦的方式 传统方式实现动画效果: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Promise animation</title> <style&g

eclipse中使用javap工具小结

关于javap的功能,百度百科上是这么解释的: javap javap是jdk自带的一个工具,可以反编译,也可以查看java编译器生成的字节码,是分析代码的一个好工具. 简单明了,大多时候真正的开发环境为linux系统,但是在windows下开发的时候又不习惯dos窗口的化,eclipse为我们提供了 javap的详细使用: 我们能够在eclipse中使用javap工具,我们有必要了解一下在eclipse中的Variables这个东西.这个英文单词的意思是变量集合的意思,意思就是我们以某些简短的

[转]nodejs中的process模块--child_process.exec

1.process是一个全局进程,你可以直接通过process变量直接访问它. process实现了EventEmitter接口,exit方法会在当进程退出的时候执行.因为进程退出之后将不再执行事件循环,所有只有那些没有回调函数的代码才会被执行. 在下面例子中,setTimeout里面的语句是没有办法执行到的. 1 process.on('exit', function () { 2 setTimeout(function () { 3 console.log('This will not ru

nodejs中aes-128-cbc加密和解密

和java程序进行交互的时候,java那边使用AES 128位填充模式:AES/CBC/PKCS5Padding加密方法,在nodejs中采用对应的aes-128-cbc加密方法就能对应上,因为有使用向量(iv),所以nodejs中要用createCipheriv方法,而不是createCipher. 在这类加密和解密的计算中,最最要注意的就是中文编码问题,不然铁定采坑.我踩完坑了,把能跑的代码发上来下,运行环境nodejs 4.4.6. var crypto = require('crypto

nodeJS中npm常见的命令

常用的nodeJS中npm的命令:npm主要是node包管理和发布的工具.npm常用的命令:1:npm install <name> //(下载包) 下载后的包放在当前路径下面 npm install express 下载express模块2:npm install <name> -g //-g 将包安装到全局环境中,我PC的全局环境是:C:\Users\qinbb\AppData\Roaming\npm,但是在代码中直接通过require()的方式是没有办法调用全局安装的包的3:

在NodeJS中玩转Protocol Buffer

Protocol Buffer入门教程 Protocol Buffer是个什么鬼 NodeJS开发者为何要跟Protocol Buffer打交道 在NodeJS中实践Protocol Buffer协议 选择支持protobuf的NodeJS第三方模块 一个栗子 书写proto文件 编译 proto 文件 编写 Writer 编写Reader 运行结果 再举一个栗子 编写proto 编写client 书写server 运行结果 其他高级特性 嵌套Message Import Message 总结一

通读cheerio API ——NodeJs中的jquery

通读cheerio API ——NodeJs中的jquery 所谓工欲善其事,必先利其器,所以通读了cheerio的API,顺便翻译了一遍,有些地方因为知道的比较少,不知道什么意思,保留了英文,希望各位不吝告诉我,然后一起把这个翻译完成. ###cheerio 为服务器特别定制的,快速.灵活.实施的jQuery核心实现. ###Introduction 将HTML告诉你的服务器 var cheerio = require('cheerio'), $ = cheerio.load('<h2 cla

【前端学习笔记】2015-09-09~~~~nodejs中的require()和module.exports

nodejs中一个js文件就可以看做是一个模块 在node环境中,可以直接var a=require('模块路径以及不带扩展名的模块名') exports---module.exports 其中node准备好了module变量, var module={ id:'hello', exports:{} }; 输出模块变量,最好都用module.exports=''或者函数;当赋值不是函数或者数组时,可以对exports直接赋值,建议统一使用module.exports=进行赋值