重写Node.js HTTPparsing器

我在正常的HTTP服务器上使用Node的基本http.request()函数没有问题。 我需要使用SHOUTcast服务器的http.request() (或类似的)。 SHOUTcast“协议”与HTTP完全兼容,除了一个细节…第一个响应行。

正常的HTTP服务器响应:

 HTTP/1.1 200 OK 

SHOUTcast服务器回应:

 ICY 200 OK 

再次,协议的其余部分是相同的。 唯一的区别是HTTP/1.xICY

我想扩展,子类或以某种方式修改Node的http.request()函数,这样我就可以使它与SHOUTcast服务器一起工作。 连接到带有节点的SHOUTcast 之前已经完成了 ,但是只能通过重新发明整个车轮。 我宁愿不这样做,因为这是一个小的协议差异。

我的问题:有没有办法做到以下一种?

  1. 扩展或覆盖 Node的HTTPparsing器的相关部分。 (我怀疑这是可能的,因为它似乎parsing器是本地代码 。)

  2. 创build我自己的一小段代码,用于parsingHTTP的相关部分,但重复使用尽可能多的HTTP现有Node组件。

  3. 创build一个简单的内部代理 (或以某种方式中继数据),以便我可以在到达Node的HTTP分析器之前修改第一个服务器响应行。

  4. 别的东西?

我也考虑过使用Shred ,但是它没有提供stream式响应的选项。 (在启动事件之前,它会等待整个服务器响应完成,这对于数据可以无限运行的stream式服务器来说是无效的)。沿着同样的路线,我尝试了Request ,但它使用Node自己的HTTP分析器,所以我得到了和本地HTTP客户端一样的parsing错误。

3。 创build一个简单的内部代理

砰。 你说对了。

使用Node.js net对象创build一个实际位于用户和http服务器之间的TCP服务器。 如上所述replace所有请求和响应的第一行,并且可以继续基本上按原样使用http服务器。 (你在一个非标准端口上创build一个内部http服务器,在另一个端口上的networking服务器,然后在两者之间链接stream,用一些代码拦截来自请求用户的第一个数据块,第一个块来自响应服务器的数据。)

所有你的代码在Javascript中,它是所有stream(几乎)没有bufferbloat。

编辑,似乎我误解了你的post。 我发现你并没有试图实现一个Node.js shoutcast服务器,而是试图访问它的数据。 net对象应该仍然工作,但不完全相同的方式。

您将需要使用net.connect与指定的shoutcast服务器进行通信,并使用一个知道net.connectstream的新net服务器来代理它与您的http.request() 。 所以,它会像这样工作:

 +---------------+ +----------+ +-----------+ +----------------+ | http.request()|--->|net.Server|--->|net.connect|--->|SHOUTcast Server| | |<---| |<---| |<---| | +---------------+ +----------+ +-----------+ +----------------+ TCP JS TCP 

这是关于如何构造它。

我已经想出了另外一种方法来做到这一点,类似于内部代理,但没有额外的连接。 似乎可以重写HTTP客户端的内部使用的套接字。 完成后,在将数据传递给原始的内部套接字ondata函数之前,很容易挂接和修改数据。

用法

 var httpicy = new HttpIcyClient(); httpicy.request(/* your normal request parameters here */); 

资源

 var http = require('http'); var HttpIcyClient = function () {}; HttpIcyClient.prototype.request = function (options, callback) { var req = http.request(options, callback), originalOnDataFunction, receiveBuffer = new Buffer(0); req.on('socket', function (socket) { originalOnDataFunction = socket.ondata; socket.ondata = function (d, start, end) { receiveBuffer = Buffer.concat([receiveBuffer, d.slice(start, end)]); if (receiveBuffer.length >= 4) { socket.ondata = originalOnDataFunction; if (receiveBuffer.toString('ascii', 0, 4) === 'ICY ') { receiveBuffer = Buffer.concat([new Buffer('HTTP/1.0 ', 'ascii'), receiveBuffer.slice(4)]); } socket.ondata.apply(this, [receiveBuffer, 0, receiveBuffer.length]); } }; }); return req; }