2017-07-26 50 views
5

我已经在节点中放置了一个代理服务器,需要能够通过tls传输https请求并且所有工作。使用以下两个软件包,这是非常容易设置:proxyhttps-proxy-agent。我的问题是,我试图捕捉使用connect作为一个中间件层HAR文件和我得到了以下错误:Node.js代理与自定义Http代理和Connect.js中间件

_http_outgoing.js:357 
throw new Error('Can\'t set headers after they are sent.'); 
^ 
Error: Can't set headers after they are sent. 
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:357:11) 
at ServerResponse.writeHead (_http_server.js:180:21) 
at ClientRequest.<anonymous> (/.../node_modules/proxy/proxy.js:233:11) 
at emitOne (events.js:96:13) 
at ClientRequest.emit (events.js:188:7) 
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:473:21) 
at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23) 
at Socket.socketOnData (_http_client.js:362:20) 
at emitOne (events.js:96:13) 
at Socket.emit (events.js:188:7) 

的很简单,只要以下和似乎只有当我发生m使用connect并通过本地浏览器进行代理(该代理实际上与BrowserStackLocal一起使用)。当我从本地机器浏览器以外的任何地方通过代理时,就像它甚至不知道中间件存在。

所以基本上,我只需要在这种情况下连接工作,我不知道如果我需要暂停和恢复,或什么...任何想法将不胜感激。基本代码如下:

const path = require('path'); 
const http = require('http'); 
const proxy = require('proxy'); 
const Agent = require('https-proxy-agent'); 
const connect = require('connect'); 
const har = require('./har'); 

const middleware = connect(); 

middleware.use(har({ 
    harOutputDir: path.resolve(process.cwd(), 'har/') 
})); 

const server = proxy(http.createServer(middleware)); 
server.agent = new Agent('http://localhost:8081'); 

server.listen(8081) 

谢谢!

编辑:只是说明:har中间件根本不修改标头。

+0

是./har中间件响应对象上发送数据?如果是这样,将设置一个头文件,并且错误发生在第二个setHeader – Myonara

+0

@Myonara no - 它所做的只是从响应和“next()”中读取数据,即使没有“./har”中间件地点。 – mike

+0

在客户端,您能识别发送的内容,而不是第二个标题答案吗? – Myonara

回答

1

proxy一直没有保持。构建不通过,最后一次提交不通过测试。你所放置的堆栈跟踪的来源是here in Line 233 - 有问题的库代码。

写一个类似的代理是微不足道的。以下代码说明了如何创建一个。

const http = require('http'); 
const urlP = require('url'); 

const proxiedServer = 'http://localhost:8888'; 

// Proxy server 
http.createServer((req, res) => { 
    console.log(`Proxy: Got ${req.url}`); 

    const _r = http.request(
    Object.assign(
     {}, 
     urlP.parse(proxiedServer), 
     { 
     method: req.method, 
     path: req.url 
     } 
    ), 
    _res => { 
     res.writeHead(_res.statusCode, _res.headers); 
     _res.pipe(res); 
    } 
); 

    req.pipe(_r); 

}).listen(3124,() => { 
    console.log("Listening on 3124"); 
}); 


// Regular server. Could be Express 
http.createServer((req, res) => { 
    console.log('Proxied server: ', req.url); 
    let b = ''; 
    req.on('data', c => { 
    b += c; 
    }); 
    req.on('end',() => { 
    console.log('Proxied server: ', b); 
    }); 
    res.writeHead(200); 
    res.end('ok'); 
}).listen(8888,() => { 
    console.log('proxied server listening on 8888'); 
}); 

使用自己的自定义代理服务器看起来就像下面您的代码:

const urlP = require('url'); 
const path = require('path'); 
const http = require('http'); 
const connect = require('connect'); 
const har = require('./har'); 

const proxiedServer = 'http://localhost:8888'; 

// Proxy server 
http.createServer((req, res) => { 
    console.log(`Proxy: Got ${req.url}`); 

    const _r = http.request(
    Object.assign(
     {}, 
     urlP.parse(proxiedServer), 
     { 
     method: req.method, 
     path: req.url 
     } 
    ), 
    _res => { 
     res.writeHead(_res.statusCode, _res.headers); 
     _res.pipe(res); 
    } 
); 

    req.pipe(_r); 

}).listen(3124,() => { 
    console.log("Listening on 3124"); 
}); 

const middleware = connect(); 
middleware.use(har({ 
    harOutputDir: path.resolve(process.cwd(), 'har/') 
})); 

middleware.use((req, res) => { 
    console.log('Proxied server: ', req.url); 
    let b = ''; 
    req.on('data', c => { 
    b += c; 
    }); 
    req.on('end',() => { 
    console.log('Proxied server: ', b); 
    }); 
    res.writeHead(200); 
    res.end('ok'); 
}); 


http.createServer(middleware).listen(8888,() => { 
    console.log('proxied server listening on 8888'); 
}); 
+0

好的,谢谢你的帮助......我开始写自己的东西,但遇到了很多问题,通过http隧道https。我发现代理是解决这个问题的方法,并试图为通过代理的任何事情创建证书。谢谢你的帮助! – mike

+0

答案中的代码段是否有帮助? –

+0

是的,我真的看着它,并计划清理它一点,并提交一个PR,但最终刚刚开始写我自己的建议...这是一个更多的参与,因为我需要代理商和必要时交换到TLS,但希望它可以帮助某人。我基本上是在编写一个JavaScript解决方案来替换。 BrowserMobb Procy。谢谢您的帮助! – mike