2017-07-26 36 views
5

Złożyłem serwer proxy w węźle, który wymaga możliwości tunelowania żądań https przez tls i że wszystko działa. Korzystanie z następujących dwóch pakietów było bardzo łatwe do skonfigurowania: proxy, https-proxy-agent. Mój problem jest to, że staram się uchwycić za pomocą plików HAR connect jako warstwy middleware i dostaję następujący błąd:Serwer Node.js z niestandardowym agentem Http i oprogramowaniem Connect.js Middleware

_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) 

IS tak proste, jak następujące i wydaje się tylko zdarzyć się podczas I” m za pomocą connect i proxy za pośrednictwem mojej lokalnej przeglądarki (to proxy jest aktualnie używane z BrowserStackLocal). Kiedy przechodzę przez proxy z innej niż moja lokalnej przeglądarki maszyn, to tak jakby nie wiedział nawet, że istnieje oprogramowanie pośrednie.

Tak więc, po prostu muszę połączyć pracę w tym scenariuszu i nie jestem pewien, czy muszę coś zatrzymać i wznowić, czy jak ... wszelkie pomysły będą mile widziane. Podstawowy kod znajduje się poniżej:

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) 

Dzięki!

EDYCJA: Tylko uwaga: oprogramowanie pośrednie har w ogóle nie modyfikuje nagłówków.

+0

jest middleware ./har wysyłania danych na obiekcie odpowiedzi? Jeśli tak, zostanie ustawiony nagłówek, a błąd wystąpi dla drugiego setHeader – Myonara

+0

@Myonara - wszystko, co robi, to odczyt danych z odpowiedzi i "next()" problem jest obecny nawet bez pośrednika "./har" w miejsce. – mike

+0

Po stronie klienta możesz określić, co zostało wysłane zamiast drugiej odpowiedzi w nagłówku? – Myonara

Odpowiedz

1

proxy nie był przez jakiś czas utrzymywany. Budowy nie przechodzą, ostatnie zatwierdzenia nie przechodzą testów. Źródło śledzonego stosu pochodzi z here in Line 233 - błędnego kodu biblioteki.

Pisanie podobnego proxy jest banalne. Poniższy kod ilustruje, jak go utworzyć.

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'); 
}); 

kodzie korzystając swój własny serwer proxy będzie wyglądać następująco:

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

Ok- dzięki za pomoc ... Właściwie to zacząłem pisać własne, ale natknąłem się na zbyt wiele problemów z tunelowaniem https przez http. Doszedłem do wniosku, że agent jest rozwiązaniem tego problemu i próbuje tworzyć certyfikaty dla wszystkiego, co przechodzi przez serwer proxy. Dzięki za pomoc! – mike

+0

Czy fragment w odpowiedzi pomógł? –

+0

Tak, faktycznie to sprawdziłem i planowałem trochę posprzątać i zgłosić PR, ale skończyło się, że zacząłem pisać własne, jak sugerowałeś ... jest trochę bardziej zaangażowany z powodu potrzeby, którą mam dla agentów i zamiana na TLS w razie potrzeby, ale miejmy nadzieję, że pomaga komuś. Zasadniczo piszę rozwiązanie JavaScript do zastąpienia. BrowserMobb Procy. Dzięki za pomoc! – mike