Write the http response to a file - node.js

I'm trying to write a simple node.js program that proxies requests and writes the response to a file. I'm using http-proxy to do the proxying.
When I try to pipe the response to a file (or the process.stdout for testing), it's empty / zero bytes. I'm not sure why but I think it might be because the stream has been closed since the response has been sent back to the client.
How can I get this to work?
var httpProxy = require('http-proxy');
var fs = require('fs');
var server = httpProxy.createServer(function (req, res, proxy) {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 80
});
});
server.proxy.on('end', function (response) {
response.pipe(process.stdout); // NOTHING IS WRITTEN TO THE STDOUT
});
server.listen(8000);

Try something like
var http = require('http'),
httpProxy = require('http-proxy');
var proxy = new httpProxy.RoutingProxy();
http.createServer(function (req, res) {
var _write = res.write;
res.write = function(data){
process.stdout.write(data); // here we get all incoming data
_write.apply(this, arguments);
}
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 80
});
}).listen(8000);

Related

Intercept websocket request to get handshake data before proxying it to server via http-proxy

Here is my code for proxying the websocket request to the targer server. I'm using http-proxy module in nodejs to proxy my request https://github.com/http-party/node-http-proxy What I want to achieve is that like in case of REST requests in http-proxy, we use proxyReq event to modify the request if we want by accessing headers and req.body, I want to do the same for weboscket request as I want to access the auth middleware data that is passed from the socket client. I don't want to log or intercept the traffic sent or received after the weboscket connection, instead I want to intercept (not modify) the actual request that contains auth middleware data on proxyReqws event. Any help & guidance would be appreciated.
var app = express();
const fs = require('fs')
var https = require('https')
var httpProxy = require('http-proxy');
const credentials = { key: fs.readFileSync("localhost.key"), cert: fs.readFileSync("localhost.cert") };
var proxy = httpProxy.createProxyServer({ ws: true });
var server = https.createServer(credentials, app).listen(8080)
proxy.on('proxyReqWs', (proxyReq, req, socket, options, head) => {
//before the request is actually proxyed to the target server
//access websocket request here
});
app.use('/socket.io', function (req, res) {
proxy.on('proxyRes', function (proxyRes, req, res) {
//on response, do something
});
proxy.on('error', function (err, req, res) {
console.log(err)
})
proxy.web(req, res, { target: { host: address.host, port: address.port, path: '/socket.io' } })
})
server.on('upgrade', function (req, socket, head) {
console.log("Upgraded to websockets")
proxy.ws(req, socket, head, { target: { host: address.host, port: address.port, path: '/socket.io' } });
});

Node.js server just keeps loading with no result

server.js
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3000;
const server = http.createServer();
server.listen(port);
app.js
const express = require('express');
const app = express();
const productRoutes = require('./api/routes/products');
app.use('/products', productRoutes);
module.exports = app;
so when i just run the code node server.js it just keep looping without any result.
Check out this link It gives a bit more detail on how that works.
const http = require('http');
const net = require('net');
const url = require('url');
// Create an HTTP tunneling proxy
const proxy = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
// connect to an origin server
const srvUrl = url.parse(`http://${req.url}`);
const srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n');
srvSocket.write(head);
srvSocket.pipe(cltSocket);
cltSocket.pipe(srvSocket);
});
});
// now that proxy is running
proxy.listen(1337, '127.0.0.1', () => {
// make a request to a tunneling proxy
const options = {
port: 1337,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80'
};
const req = http.request(options);
req.end();
req.on('connect', (res, socket, head) => {
console.log('got connected!');
// make a request over an HTTP tunnel
socket.write('GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n');
socket.on('data', (chunk) => {
console.log(chunk.toString());
});
socket.on('end', () => {
proxy.close();
});
});
});
const http = require('http');
const app = require('./app');
const port = process.env.PORT || 3000;
const server = http.createServer();
server.listen(port);
As far I could extract from code, the thing that is most probably happening in your server.js is that your server is waiting for some request. And you have nothing in your code handle requests.
I think you have to call the require function to return the actual router object, try to change this line
from: const productRoutes = require('./api/routes/products');
to: const productRoutes = require('./api/routes/products')();

Node Http Proxy Web Socket Balance

I need to able to balance websocket on application level. Lets say forward websocket request on the basis of message I received, decode it on proxy and then using that data send to another socket server using some logic.
But I am unable to do this. This is the initial code I wrote and trying to do that. This is the server
var http = require('http');
var httpProxy = require('http-proxy');
var WebSocket = require('ws');
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
var proxy = httpProxy.createServer({target: 'ws://localhost:8080', ws:true});
var server = httpProxy.createServer(function(req, res) {
//SOME LOGIC HERE TO PARSE WS DATA AND SEND TO WS SERVER
proxy.ws(req, res, { target: 'ws://localhost:8080'});
}).listen(8014);
CLIENT
var http = require('http');
var httpProxy = require('http-proxy');
var WebSocket = require('ws');
var ws = new WebSocket('ws://localhost:8014/');
ws.on('open', function () {
ws.send("CLIENT");
});
ws.on('message', function (msg) {
console.log(msg);
});
Here's an example. In this case the client connects directly to outer.js which then forwards connections to upstream servers (inner.js).
outer.js
var http = require('http');
var httpProxy = require('http-proxy');
var proxies = {
foo: new httpProxy.createProxyServer({
target: {
host: "foo.com",
port: 8080
}
}),
bar: new httpProxy.createProxyServer({
target: {
host: "bar.com",
port: 8080
}
})
// extend this...
};
var findUpstream = function(req){
// TODO return key for lookup in #proxies
};
var proxyServer = http.createServer(function (req, res){
var upstream = findUpstream(req);
proxies[upstream].web(req, res);
});
proxyServer.on('upgrade', function (req, socket, head) {
var upstream = findUpstream(req);
proxies[upstream].ws(req, socket, head);
});
proxyServer.listen(8014);
inner.js
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
In this example you'll need to fill in the findUpstream to return the key such as foo or bar based on data in the request. It'd also be worth putting some error handling in for when the proper upstream server isn't found, but this should illustrate the general idea.

NODE.JS: how to proxy to a host with the variable target DEPENDING on the data received in the req?

I need to use the node-http-proxy library to proxy to a host with the variable target DEPENDING on the data received in the req, let's suppose that I need to find a tag and basing on this tag route to a host. My code is:
var http = require('http'),
httpProxy = require('http-proxy'),
proxy = httpProxy.createProxyServer({});
var miTarget='web:CountryName';
var inicio = '<'+miTarget+'>';
var fin = '</'+miTarget+'>';
var server = http.createServer(function(req, res) {
var miTag = '';
req.on('data', function (data) {
miTag = data.toString().split(inicio)[1].split(fin)[0];
});
req.on('end', function () {
console.log('miTag!!!!!!:'+miTag);
if(miTag=='Portugal') {
proxy.web(req, res, {target: 'http://www.webservicex.net'});
}
else {
proxy.web(req, res, {target: 'http://localhost:1337'});
}
});
});
console.log("listening on port 80")
server.listen(80);
This code is not working... Can anyone help me to sort out this problem?
The most important for me is to execute thie proxy.web() AFTER the data is received miTag in the req: req.on('data', function (data) {}
I did something similar once for a little personal project. You can use res.locals as a safe place to store per-request context (much safer than using a global).
app.use('/proxy', function(req, res, next) {
// Do whatever you need to do to create targetUrl (a URL object)
var targetUrl = whatever(req);
// Save the targetUrl path so we can access it in the proxyReq handler
res.locals.path = targetUrl.path;
// Initiate the proxy
var options = {
prependPath: false,
target: targetUrl.format(),
changeOrigin: true,
hostRewrite: targetUrl.host,
protocolRewrite: targetUrl.protocol.replace(/:$/, '')
};
proxy.web(req, res, options);
});
Then setup a proxyReq handler that uses the saved targetUrl path.
proxy.on('proxyReq', function(proxyReq, req, res, options) {
if (res.locals.path) {
proxyReq.path = res.locals.path;
}
});

nodejs node-http-proxy setup with cache

I'm trying to setup node-http-proxy module with caching
node-http-proxy module. I've managed to configure node-http-proxy to do what I need to do in terms of proxying calls, but I would like to find a way to cache some of these calls.
My current code is as follows (omitted some config bootstrapping):
var http = require('http');
var https = require('https');
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
var fs = require('fs');
var handler = function(req, res) {
proxy.web(req, res, {target: 'http://localhost:9000'});
};
var server = http.createServer(handler).listen(config.children.http.port, function() {
console.log('Listening on port %d', server.address().port);
});
var secure = https.createServer(config.children.https.options, handler).listen(config.children.https.port, function() {
console.log('Listening on port %d', secure.address().port);
});
Inside the handler function, I would like to be able to somehow capture what the proxy is reading from "target" and stream it into a fs.createWriteStream('/somepath') before piping it out to res. Then I would modify my function to do look to something along the line:
var handler = function(req, res) {
var path = '/somepath';
fs.exists(path, function(exists) {
if(exists) {
console.log('is file');
fs.createReadStream(path).pipe(res);
} else {
console.log('proxying');
// Here I need to find a way to write into path
proxy.web(req, res, {target: 'http://localhost:9000'});
}
});
};
Does anyone know how to do this ?
The answer to the question ended up being very simple:
var handler = function(req, res, next) {
var path = '/tmp/file';
fs.exists(path, function(exists) {
if(exists) {
fs.createReadStream(path).pipe(res);
} else {
proxy.on('proxyRes', function(proxyRes, req, res) {
proxyRes.pipe(fs.createWriteStream(path));
});
proxy.web(req, res, {target: 'http://localhost:9000'});
}
});
};

Resources