Want to write capture and re-transmit http/https request to Browser? - node.js

I want to write a simple Node Js application which will capture and re-transmit http/https request to Browser?
I have written the below code, but it works only for http request.
var server = http.createServer(function (req,res) {
console.log("start request:", req.url);
var option = url.parse(req.url);
option.headers = req.headers;
var proxyrequest = http.request(option, function (proxyresponce) {
proxyresponce.on('data', function (chunk) {
console.log("proxy responce length" ,chunk.length);
res.write(chunk,'binary');
});
proxyresponce.on('end',function () {
console.log("proxy responce ended");
res.end();
});
res.writeHead(proxyresponce.statusCode, proxyresponce.headers);
});
});

Related

NodeJS server results in timeout

I have a NodeJS server script, which works like a charm on my local dev environment. But in (beta) production the webserver times out at every request. I've set this up fairly straight forward but I'm unsure how to fix it - or even where to look for a solution. Below is a simplified implementation, my logic for handling post request has been removed. What am I overlooking?
var requestListener = '';
// define the request listener, to handle incoming requests
requestListener = function (req, res) {
try {
if (req.method == 'POST') {
var queryString = '';
req.on('data', function (data) {
queryString += data;
});
req.on('end', function () {
// my logic is in here
res.end(JSON.stringify({ err: false, msg: 'all fine' }));
});
}
res.writeHead(200);
res.end();
} catch (error) {
res.writeHead(400);
res.end(error);
}
}
// boot the webserver
server = http.createServer(requestListener);
server.listen(8080);

Forward request to ws client and wait for response Express

I'm trying to build an endpoint that will receive a request, emit the request data to a WebSocket client, wait for an event, then send back the response using express + socketio. This question is similar to it: Wait for socketio event inside express route
1) Receive request at http://localhost:3000/endpoint
2) Emit the event to web sockets as 'req'
3) Wait for 'res' event from ws
4) Send the received events details as the response of express.
Here is how I'm implemented:
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
var socket;
io.on('connection', function (s) {
socket = s;
});
http.listen(3000);
app.get('/endpoint', function (req, res) {
console.log('new request')
io.emit('req', { data: 'hello' });
socket.on('res', function (data) {
res.status(200).json(data);
});
});
index.html
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('req', (data) => {
console.log(data)
socket.emit('res', data);
});
</script>
The script works fine for the first request on /endpoint. But if i hit the url again, it says
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent
to the client
Please note that:
socket.on('res', function (data) {
res.status(200).json(data);
});
Is being called each time a socket is sending a response, thus showing the above error. You should unbind the listener inside the callback function.
Keep an array of express responses and set an id to each request. So it can be used later and delete if needed.
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var timeout = require('connect-timeout');
var uuid = require('uuidv4');
var _ = require('lodash');
app.use(timeout('10s'));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
let responses = []
io.on('connection', (socket) => {
socket.on('res', (e) => {
var obj = _.find(responses, r => r.id === e.id);
obj.res.send(e)
_.remove(responses, r => r.id === e.id);
})
})
app.get('/endpoint', (req, res) => {
const id = uuid()
io.emit('req', { id, ip: req.ip, header: req.headers, method: req.method });
responses.push({ id, res })
});
http.listen(3000);
You're trying to do two different async tasks for the same data.
First, take your socket.on('res'...) out of the app.get().
Send back res.status(200) immediately with express to say you received the request and it is processing. Then send the socket message to the client using socket.io when it's complete. You'll want to save the connected users socket client ID and use io.to(socketId).emit(...data...) to do this
the other option is what I always do (assuming it's not a crazy large payload of data you're sending) Just use socket.io for the whole process.
client
function makeRequest () {
socket.on('data-complete--error', function ( error ) {
// ... message to user :(
// also remove these handlers when finished
socket.off('data-complete--error');
socket.off('data-complete--success');
});
socket.on('data-complete--success', function ( data ) {
// ... message to user :)
// ... handle data
// also remove these handlers when finished
socket.off('data-complete--error');
socket.off('data-complete--success');
});
socket.emit('request-data');
}
makeRequest();
server
move your stuff out and handle without using express at all

Node.js Simple Server Request End Event Issue

I'm new to node.js. Trying to get a console to print when the request ends. I try to go to localhost:8080 and also localhost:8080/ but nothing prints in the terminal. Any idea why? Doing this because when I run this example because when I try to run the demo at http://tutorialzine.com/2012/08/nodejs-drawing-game/ the terminal says socket started but it does not render the index.html page. So I can't figure out why this code to serve static files for other is not working for me.
var static = require('node-static');
//
// Create a node-static server instance to serve the './public' folder
//
// var file = new(static.Server)('./');
require('http').createServer(function (request, response) {
request.addListener('end', function () {
console.log("ended");
});
}).listen(8080);
It seems that your are using Node.js 0.10.x and in the new version you have to resume the readable streams to make them emit events:
require('http').createServer(function (request, response) {
var body = '';
request.setEncoding('utf8');
request.on('readable', function () {
body+= this.read();
}
request.on('end', function () {
console.log('ended');
console.log('Body: ' + body);
});
request.resume();
}).listen(8080);
You should be call node-static serve inside the request handler so that you can get index.html
var static = require('node-static');
var fileServer = new static.Server('./');
require('http').createServer(function (request, response) {
fileServer.serve(request, response); //add this line
request.addListener('end', function () {
console.log("ended");
});
}).listen(8080);

Get response from proxy server

I created a proxy server in node.js using the node-http-proxy module.
Looks like this:
var http = require('http'),
httpProxy = require('http-proxy'),
io = require("socket.io").listen(5555);
var proxy = new httpProxy.RoutingProxy();
http.createServer(function (req, res) {
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 1338
});
}).listen(9000);
So, I need, before sending the response back to the client to get the body from the server that I proxy and analyze it.
But I can't find event or attribute, where I can get this data. I tried:
proxy.on('end', function (data) {
console.log('end');
});
But I can't figure our how to get the mime body from it.
If all you want to do is examine the response (read-only) , you could use :
proxy.on('proxyRes', function(proxyRes, req, res){
proxyRes.on('data' , function(dataBuffer){
var data = dataBuffer.toString('utf8');
console.log("This is the data from target server : "+ data);
});
});
But , note that the 'proxyRes' event is emitted after the response is sent.
Reference in :
https://github.com/nodejitsu/node-http-proxy/issues/382
I found answer:
I rewrite response function for body -
var http = require('http'),
httpProxy = require('http-proxy'),
io = require("socket.io").listen(5555);
var proxy = new httpProxy.RoutingProxy();
http.createServer(function (req, res) {
console.log(req.url);
res.oldWrite = res.write;
res.write = function(data) {
/* add logic for your data here */
console.log(data.toString('UTF8'));
res.oldWrite(data);
}
proxy.proxyRequest(req, res, {
host: 'localhost',
port: 1338
});
}).listen(9000);
This code will console all url request and response form this endpoint.
Based on the answer of #Psycho, following code can be used to modify headers as well
var server = http.createServer(function(req, res) {
res.oldWrite = res.write;
res.write = function(data) {
console.log(data.toString('UTF8'));
res.oldWrite(data);
}
res.oldSetHeader = res.setHeader
res.setHeader = function(k,v) {
console.log(k,v)
res.oldSetHeader(k,v)
}
proxy.web(req, res, { target: proxyPool[key]}); })

Difficulties with node.js proxy

I am attempting to make a GET request for a single image on another server from node.js.
var http = require('http');
var site = http.createClient(80, '192.168.111.190');
var proxy_request = site.request('/image.png');
proxy_request.on('response', function (proxy_response) {
console.log('receiving response');
proxy_response.on('data', function (chunk) {
});
proxy_response.on('end', function () {
console.log('done');
});
});
And even with this code, I can't get the "receiving response" message to print out. Outside of node, I can do a curl http://192.168.111.190/image.png just fine, but is there something else I might be missing?
for get requests try the http.get API http://nodejs.org/docs/v0.4.9/api/http.html#http.get
var http = require('http');
var options = {
host: '192.168.111.190',
port: 80,
path: '/image.png'
};
http.get(options, function(res) {
console.log("Got response: " + res.statusCode);
}).on('error', function(e) {
console.log("Got error: " + e.message);
});

Resources