Server proxy with Node JS - javascript

I want to build a proxy with node.js to use in my browser.
I searched at google and saw that example, but some Apis are deprecated.
So I changed the code following:
var http = require('http');
http.createServer(function(request, response) {
console.log("req for:"+ request.headers['host'] + "\nmethod: "+ request.method);
var options = {
host : request.headers['host'],
method : request.method,
headers : request.headers
}
var callback = function(res){
// get the proxyclient response and write to the original response
res.addListener('data', function(chunk){
console.log("writing response");
response.write(chunk, 'binary');
});
res.addListener('end', function(){
console.log("end response");
response.end();
});
};
// send the original request
var proxy = http.request(options, callback);
// intercept the request and write to proxyclient
request.addListener('data', function(chunk){
console.log("new request");
proxy.write(chunk, 'binary');
});
request.addListener('end', function(){
console.log("end request");
proxy.end();
});
}).listen(3333);
After that, I changed my browser proxy settings to use localhost:3333.
My problem is that event "data" isn't fired.
This should work as I thought?

Maybe if you write this code;
response.writeHead(res.statusCode, res.headers); after res.addListener('end', function(){
console.log("end response");
response.end();
});

Related

node.js url search/query portion is empty

I am developing a website (client + server) that runs from the same machine.
I haven't found any errors in chrome's developer tools, so I don't know where the problem is.
I try to POST a string from the client to the Node back-end, but upon performing
url.parse(request.url, true).query
the result is empty.
Here is my client:
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://localhost:8080/newComment", true);
xhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhttp.send("val=" + commentString);
My commentString is "hey there"
Here is my server:
var path = url.parse(request.url).pathname;
else if (path == "/newComment") {
console.log("query: " + url.parse(request.url, true).body);
//setNewComment(comment);
response.writeHead(200, {
'Content-Type': 'text/plain',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
}); // enable cors
response.write("Recieved request");
response.end();
}
And I am at the website
file:///C:/Users/.../website.html?name=hey+there
So I'd like my Node server to print out "query: hey there" but instead it prints "query undefined"
You are trying to access the body, and this is right, yet the url doesn't hold the body's content, you should either accumulate it by listening to 'data' events:
let body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
body = Buffer.concat(body).toString();
// at this point, `body` has the entire request body stored in it as a string
});
or use "express" and "body-parser".
1.Go to the request body section: https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

express.js: how to use value returned by http.request in app.get

I want to use app.get to deliver the data from an API on another domain. I can write the data to the console, but nothing is appearing on the page ('~/restresults').
This is the code I have so far:
app.get('/restresults', function (req, res) {
var theresults;
var http = require('http');
var options = {
port: '80' ,
hostname: 'restsite' ,
path: '/v1/search?format=json&q=%22foobar%22' ,
headers: { 'Authorization': 'Basic abc=='}
} ;
callback = function(res) {
var content;
res.on('data', function (chunk) {
content += chunk;
});
res.on('end', function () {
console.log(content);
theresults = content ;
});
};
http.request(options, callback).end();
res.send(theresults) ;
});
how can I bind the result of the http.request to a variable and return it when 'restresults/' is requested?
Move res.send(theresults); to here:
callback = function(res2) {
var content;
res2.on('data', function (chunk) {
content += chunk;
});
res2.on('end', function () {
console.log(content);
theresults = content ;
res.send(theresults) ; // Here
});
};
Note: You'll have to change res to something else as you want the express res, no the request res.
The callback is an asynchronous call. You're sending the response before you get a result from the request.
You'll also want to handle the case in which there is an error, otherwise the client's request may hang.
You are currently sending the response before the callback (from the http request) is done.
The http.request is async, the script will not wait til its done and then send the data back to client.
You will have to wait for the request to be done and then send the result back to the client (preferably in the callback function).
Example:
http.request(options, function(httpRes) {
// Notice that i renamed the 'res' param due to one with that name existing in the outer scope.
/*do the res.on('data' stuff... and any other code you want...*/
httpRes.on('end', function () {
res.send(content);
});
}).end();

Read raw http message in Nodejs

I'm sending an http request using the http.request function, and I would like to read the whole http response like text; that is, the raw http protocol text. Is it possible? I've written the below code but it's not working.
// Set up the request
console.log('Sending request');
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
console.log('Response statusCode: ' + res.statusCode);
// res.on('data', function (chunk) {
// console.log('Response: ' + chunk);
// });
// res.on('end', function() {});
});
post_req.on('socket', function (socket) {
var response = "";
socket.on('data', function(chunk){
console.log(chunk);
});
});
// post the data
post_req.write(post_data);
post_req.end();
If you want access to the raw http message, I'd suggest using the net module instead, and writing the request yourself. Something like this for a simple GET request:
var net = require('net');
var host = 'stackoverflow.com',
port = 80,
socket = net.connect(port, host, function() {
var request = "GET / HTTP/1.1\r\nHost: " + host + "\r\n\r\n",
rawResponse = "";
// send http request:
socket.end(request);
// assume utf-8 encoding:
socket.setEncoding('utf-8');
// collect raw http message:
socket.on('data', function(chunk) {
rawResponse += chunk;
});
socket.on('end', function(){
console.log(rawResponse);
});
});
For a POST request sending application/x-www-form-urlencoded data, you could write the request using something like:
function writePOSTRequest (data, host, path) {
return "POST " + path + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: " + Buffer.byteLength(data) + "\r\n\r\n" +
data + "\r\n\r\n";
}
var data = "name1=value1&name2=value2",
request = writePOSTRequest(data, host, "/path/to/resource");
where I'm using Buffer.byteLength because Content-Length requires the length in bytes, not in characters. Also, remember that data must be URL encoded.
If you don't know much about the format of HTTP messages, then this is a decent place to start:
http://jmarshall.com/easy/http/
Also, if you don't know what the encoding of the response will be then you'll have to parse the headers first to find out, but UTF-8 is by far the most common so it's a pretty safe bet.
Streams2 and Streams1 not always able to inter-operate well, see "problem: streams1 and streams2 duality" in this video.
I tried to listen data at a bit lower level than streams and this code prints raw http response with headers for me:
var http = require('http');
var raw = '';
console.log('Sending request');
var req = http.request({host: 'stackoverflow.com'}, function(res) {
watch(res, 'res');
res.on('end', function() {
console.log(raw);
});
res.on('data', function(data) {
// if we don't attach 'data' handler here 'end' is not called
});
});
req.on('socket', function (socket) {
socket.resume();
var oldOndata = socket.ondata;
socket.ondata = function(buf, start, end) {
raw += buf.slice(start, end).toString();
oldOndata.call(socket, buf, start, end);
};
});
req.end();
Assuming these kind of tools are allowed in your environment, you could run up an HTTP debug proxy such as Fiddler http://www.fiddler2.com/, which enables you to inspect the HTTP calls and responses.

Node.js http request

I am a beginner with node.js, and I'm not seeming to get this to work.
function sleep(milliSeconds){
var startTime = new Date().getTime();
while (new Date().getTime() < startTime + milliSeconds);
}
var isRequestComplete = false;
while(isRequestComplete == false){
console.log("in make request");
var querystring = require('querystring');
var data = querystring.stringify({
username: 'username',
password: 'password',
action: 'convert',
voice: 'engfemale1',
text: 'stuff and things, this should take longer than one request.'
});
var options = {
host: 'ws.ispeech.org',
port: 80,
path: '/api/rest/1.5',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': data.length
}
};
var http = require('http');
var req = http.request(options, function(res) {
console.log("got response");
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
if(chunk.indexOf("finished") != -1){
isRequestComplete = true;
}
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(data);
req.end();
console.log("completed");
sleep(5000);
}
For whatever reason the http request does not send a response back, ever. Unless the code is fully finished, so in the while loop I never get a response back. Thus the loop never ends. The username and password in my program are inputted, here they are not for confidentiality. Thanks for reading.
this is NOT the way to get your code to sleep! A while loop isn't "sleeping" it's processing as fast as it can. In you case it's grabbing date after date after date trying to get to your destination.
take a look here to see how this *should work.
http://nodejs.org/api/http.html
Have a look at the very first http-server example on http://nodejs.org/.
You have to create an http-server that listens for requests from browsers that arrive at the specified IP-Address:Port. Once a request arrives, the server send the specified response to the browser.

Download Tar File via NodeJS

I have two nodejs http servers, one requests a tar file from the other. It works fine via browser testing, but I can never get the second server to glue the chunks together correctly. My attempts with fwrite has been as useless as this
// Receives File
var complete_file = '';
response.on('data', function(chunk){
complete_file += chunk
}).on('end', function(){
fs.writeFile('/tmp/test.tgz', complete_file, 'binary')
});
// Send File
fs.readFile('/tmp/test_send.tgz', function(err, data){
if (err) throw err;
response.writeHead('200', {
'Content-Type' : 'application/x-compressed',
'Content-Length' : data.length
});
response.write(data);
response.end();
});
I've managed to make it work but I use a writeable stream instead, this is the client code:
fs = require ('fs');
var http = require('http');
var local = http.createClient(8124, 'localhost');
var request = local.request('GET', '/',{'host': 'localhost'});
request.on('response', function (response) {
console.log('STATUS: ' + response.statusCode);
var headers = JSON.stringify(response.headers);
console.log('HEADERS: ' + headers);
var file = fs.createWriteStream('/tmp/node/test.gz');
response.on('data', function(chunk){
file.write(chunk);
}).on('end', function(){
file.end();
});
});
request.end();
This has changed in newer versions of Node.
Here is the latest, and I add more logic to try harder to finish downloading such as encouting 301,302...
function getFile(url, path, cb) {
var http_or_https = http;
if (/^https:\/\/(\w+:{0,1}\w*#)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%#!\-\/]))?$/.test(url)) {
http_or_https = https;
}
http_or_https.get(url, function(response) {
var headers = JSON.stringify(response.headers);
switch(response.statusCode) {
case 200:
var file = fs.createWriteStream(path);
response.on('data', function(chunk){
file.write(chunk);
}).on('end', function(){
file.end();
cb(null);
});
break;
case 301:
case 302:
case 303:
case 307:
getFile(response.headers.location, path, cb);
break;
default:
cb(new Error('Server responded with status code ' + response.statusCode));
}
})
.on('error', function(err) {
cb(err);
});
}
what about request package?
you can do this:
request(fileurl).pipe(fs.createWriteStream(savetohere))

Categories

Resources