I'd like to have a pair of Javascript client and server that communicate
using JSON without involving a Web Browser. I can get it going as long as
the client does not try to send anything to the server. When it does, I get
the error message (% node poster.js):
.../node_modules/xhr2/lib/xhr2.js:281
throw new NetworkError(`Unsupported protocol ${this._url.protocol}`);
Can somebody help me with this protocol issue please. What I have so far:
a server that I can start with "pm2 start jsonServer.js" -
var port = 62022
var http = require('http')
var srvr = http.createServer (function (req, res) {
console.log ('Request type: ' + typeof(req))
console.log (req)
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello World!\n');
res.write(req);
res.end();
})
var scriptName = __filename.split(__dirname+"/").pop();
console.log ('Script: ' + scriptName +'. Listening to port ' + port)
srvr.listen(port)
... and a client that is
var XMLHttpRequest = require('xhr2')
var serialize = function(object) {
return JSON.stringify(object, null, 2)
}
let xhr = new XMLHttpRequest();
xhr.open("POST", "localhost:62022");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onload = () => console.log(xhr.responseText);
let data = `{
"Id": 912,
"First Name": "Archibald",
"Last Name": "Haddock"
}`;
//console.log (serialize(data));
//xhr.send(serialize(data));
console.log (data);
xhr.send(data);
This is what is needed after posting 'Hello World!' on the server (res.end does not wait for the async data transfer):
let data = '';
req.on('data', chunk => {
data += chunk;
});
req.on('end', () => {
// do whatever with data
res.write ('Data: ' + data + '\n')
res.end()
});
Related
I a m kinda stuck. I made a request to a server. I want the server to computer a operation for me, and send me back the result.
Request :
ar http = require('http');
http.createServer(function(req, res){
var response = "Hello from " + req.client.remoteAddress + ":" + req.client.remotePort + "\n to " + req.client.localAddress + ":" + req.client.localPort;
console.log(response);
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const Http = new XMLHttpRequest();
console.log("start");
n = 15;
const urlfibo='http://172.22.0.4:8899';
Http.open("POST", urlfibo,false);
var params = 'value=15';
Http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
Http.send(params);
console.log(Http.responseText);
response += Http.responseText;
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write(response);
res.end();
On my server, i don't know where to find the parameter i passed. I've tryed the solution in the doc, but my code is never running into it :
```
response += "\n ON" + req.on
let body = [];
req.on('data', (chunk) => {
response += "bla"
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
});
My question is : on y server (second part of code), how do i get my params i passed when i sent the request ? I want to do it with nodejs without using frameworks
Thank you
chunk will have all informations because is an object, you just have to assign this values for a new object and look for the parameters. Bug make sure to have in your code:
const bodyParser = require('body-parser');
app.use(bodyParser);
I am trying to implement this (.net) example in Node.js using request and iconv-lite (its an HTTP web service that requires url requests are encoded in ISO-8859-1):
WebClient wc = new WebClient();
var encoding = Encoding.GetEncoding("iso-8859-1");
var url = new StringBuilder();
url.Append("https://url.com?");
url.Append("¶m=" + HttpUtility.UrlEncode(foo, encoding));
wc.Encoding = encoding;
return wc.DownloadString(url.ToString());
The problem is with encoding the URL (doesnt work). I am trying to do the same GET request, in which the URL must be encoded as ISO-8859-1. However, by doing something like this:
var options = {
url : iconv.encode(url, 'ISO-8859-1').toString(),
method: 'get',
headers : {
'Content-Type': 'application/x-www-form-urlencoded; charset=ISO-8859-1'
}
};
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}else {
console.log('err: ' + error);
}
});
It's still not sent as a ISO-8859-1 string. Any clues on how to get this to work like with the .NET example?
I think it's decoding the response, not encoding the url. Try this:
var https = require('https'),
qs = require('querystring');
// ...
var url = 'https://url.com/?' + qs.stringify({ param: 'foo' });
https.get(url, function(res) {
if (res.statusCode === 200) {
var bufs = [], bufsize = 0;
res.on('data', function(data) {
bufs.push(data);
bufsize += data.length;
}).on('end', function() {
var buffer = Buffer.concat(bufs, bufsize),
body = iconv.decode(buffer, 'iso-8859-1');
console.log('Body: ' + body);
});
return;
} else
console.log('Non-OK status code: ' + res.statusCode);
res.resume();
});
I want to evaluate round trip time between client and server. Here the user can choose how big the request/response size of the message (body) should be. At client side I used Ajax-Post method to send 100 messages in an interval of 100 ms to the http-server. Unfortunatley I got the problem in node.js, that the httpServer.js cannot handle client request sizes of bigger than 8 kb. In this case the variable responseSizeServer in httpServer.js gets the value "undefined" and the console throw an error: "Invalid Array length". The question is why the variable responseSizeServer has got the value undefined ins this case? I suppose that the http-Server.js handle the .end method faster than the incoming request from the client. What do you think and how can it be solved? Thanks in advance :)
Here is the code:
client:
var i = 0;
var iterations = 100;
function connectSpeed(){
run = window.setInterval("startSpeed()", 100);
}
function startSpeed()
{
//Variablen
var requestSizeClient = 8 *1024; // 8 kb request Size client
var responseSizeServer = 16 * 1024; // 16 kb response size server
var xmlhttp;
xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST","http://localhost:8000", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
var receiveTimeCl = new Date().getTime().toString();
//evaluate response from httpServer.js
var message = xmlhttp.responseText;
}
}
//send data to the server
xmlhttp.send(new Date().getTime().toString() + '#' + new Array((eval(requestSizeClient+1))-(new Date().getTime().toString().length+3)).join('X') + '#' + responseSizeServer);
i++;
if(i==iterations) {
window.clearInterval(run);
i=0;
}
}// end start-speed
server: (httpServer.js)
var http = require('http');
http.createServer(function (req, res) {
var receiveTimeServer;
var clientMsg;
var sendTimeClient;
var responseSizeServer;
var message;
req.on('data', function (chunk) {
receiveTimeServer = new Date().getTime().toString();
message = chunk.toString('utf8');
clientMsg = message.split('#');
responseSizeServer = parseInt(clientMsg[2]);
sendTimeClient = clientMsg[0];
res.writeHead(200, {'Content-Type': 'text/plain','Access-Control-Allow-Origin' : '*'});
res.end(receiveTimeServer + '#' + new Date().getTime().toString() + '#' + sendTimeClient + '#' + new Array(responseSizeServer).join('X'));
});
}).listen(8000);
console.log('Ajax_Server running');
Requests in Node.js are streams, and each data event corresponds to an incoming chunk. If the request is big, then multiple chunks are emitted: one can then handle a request while it is being sent, and don't have to wait for the full request to be received before handling it.
In your specific case, what you want is to buffer the full message and then handle it:
var message = '';
req.on('data', function (chunk) {
message += chunk; // concatenate all chunks
});
req.on('end', function() {
receiveTimeServer = new Date().getTime().toString();
message = message.toString('utf8');
clientMsg = message.split('#');
responseSizeServer = parseInt(clientMsg[2]);
sendTimeClient = clientMsg[0];
res.writeHead(200, {'Content-Type': 'text/plain','Access-Control-Allow-Origin' : '*'});
res.end(receiveTimeServer + '#' + new Date().getTime().toString() + '#' + sendTimeClient + '#' + new Array(responseSizeServer).join('X'));
});
You can find a thorough explanation with code samples in Node.js's streams documentation.
This question already has answers here:
How can I do Base64 encoding in Node.js?
(7 answers)
Closed 9 years ago.
I'm a node.js newbie stuck trying to implement base64 encoding. My server doesn't seem to receive/process the base64 message. Code below:
Server:
var http = require('http');
http.createServer(function (req, res) {
req.on('data',function(b) {
console.log("HEY!"); // <--- Never gets called
var content = new Buffer(b, 'base64').toString('utf8')
console.log("CLIENT SAID: "+content);
var msg = JSON.parse(content);
// do stuff and respond here...
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Client:
var http = require('http');
var options = {
hostname : 'localhost',
port : 1337,
method : 'POST'
};
var req = http.request(options, function(res) {
res.setEncoding('base64');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
var msg = {'name':'Fred','age':23};
var msgS = JSON.stringify(msg);
req.write(msgS,'base64');
req.end();
Any ideas what I'm doing wrong?
I came up with a fix. I noticed when using req.write(data, 'base64'); that the request never ended. I instead created a buffer that was base64 encoded, then wrote it to the request.
These exact snippets were tested localhost:
Client:
var http = require('http');
var options = {
hostname: 'localhost',
port: 1337,
method: 'POST'
};
var req = http.request(options, function (res) {
res.setEncoding('base64');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
var msg = {
'name': 'Fred',
'age': 23
};
var msgS = JSON.stringify(msg);
var buf = new Buffer(msgS, 'base64');
req.write(msgS);
req.end();
Server:
var http = require('http');
http.createServer(function (req, res) {
var content = '';
req.on('data', function (chunk) {
content += chunk;
});
req.on('end', function() {
content = content.toString('base64');
console.log(content);
//content returns {"name": "Fred","age": 23};
res.end();
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Aside from those things, I noticed these errors in your code.
req.on('data',function(b) {
var content = new Buffer(b, 'base64').toString('utf8')
});
Note that b in this case is actually already a buffer. You should use b.toString('base64');. Also note that b is actually only fragments of the data. You should instead collect the data of b, then listen to the end event to finally do something with the data. In your case with req.write(data, 'base64');, the end would never fire, leading to a hangup instead of the event firing.
This is how you'd collect data:
var content = '';
req.on('data', function(b) {
content += b;
});
req.on('end', function() {
//do something with content
});
I have written a http server using node js
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
http.createServer(function(request, res) {
var parsed_url = url.parse(request.url);
var uri = parsed_url.pathname;
if(uri === "/test"){
res.writeHead(200, {'Content-Type': 'text/javascript'});
request.addListener('data', function (chunk) {
var data = eval("(" + chunk + ")");
console.log(data[0].id);
})
request.addListener('end', function() {
console.log('end triggered');
res.write("Post data");
res.end();
});
}
}).listen(8080);
and i am trying to send back response of ajax request but i am unable to receive any response. Here is the code for ajax request ,
var myhttp = new XMLHttpRequest();
var url = "http://localhost:8080/test";
var data = [{"a":"1"},{"b":"2"},{"c":"3"}];
var dataJson = JSON.stringify(data);
myhttp.open('POST', url, true);
myhttp.send(dataJson);
myhttp.onreadystatechange = function() {
if ((myhttp.readyState == 4) && (myhttp.status == 200)){
alert(myhttp.responseText);
}
else if ((myhttp.readyState == 4) && (myhttp.status != 200))
{
console.log("Error in Connection");
}
Can anyone help me what i am doing wrong ...
Thanks
Vinay
Your code is almost right but on your code sample you have
console.log(data[0].id)
the data object has no property id so if you only have
console.log(data[0])
there you have a response like
{ a: '1' }
therefore you can access the property a by doing
console.log(data[0].a);
UPDATED Updated with a full example
One more thing is that you are using eval and node comes with JSON.parse bundle with it so the snippet below is how i made it work
File: app.js
var sys = require("sys"),
http = require("http"),
url = require("url"),
path = require("path"),
fs = require("fs");
http.createServer(function(request, res) {
var parsed_url = url.parse(request.url);
var uri = parsed_url.pathname;
if(uri === "/test"){
res.writeHead(200, {'Content-Type': 'text/javascript'});
request.addListener('data', function (chunk) {
// removed this - eval("(" + chunk + ")");
var data = JSON.parse(chunk);
console.log(data[0].a);
})
request.addListener('end', function() {
console.log('end triggered');
res.write("Post data");
res.end();
});
} else if(uri === "/") {
fs.readFile("./index.html",function(err, data){
if(err) throw err;
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data);
});
}
}).listen(8080);
On the same directory create a file index.html with the following:
<html>
<head>
<script type="text/javascript" charset="utf-8">
var myhttp = new XMLHttpRequest();
var url = "http://localhost:8080/test";
var data = [{"a":"1"},{"b":"2"},{"c":"3"}];
var dataJson = JSON.stringify(data);
myhttp.open('POST', url, true);
myhttp.send(dataJson);
myhttp.onreadystatechange = function() {
if ((myhttp.readyState == 4) && (myhttp.status == 200)){
alert(myhttp.responseText);
}
else if ((myhttp.readyState == 4) && (myhttp.status != 200))
{
console.log("Error in Connection");
}
}
</script>
</head>
<body>
</body>
</html>
That is a complete working example of what you want.
With regards to the same origin policy issues you were having is mainly due to the fact that you cant POST data between 2 different domains via ajax unless you use some tricks with iframes but that is another story.
Also i think is good for anyone to understand the backbone of a technology before moving into frameworks so fair play to you.
good luck
You have to read the data in a different way. Posted data arrives on a node server in chunks (the 'data' event), that have to be collected until the 'end' event fires. Inside this event, you are able to access your payload.
var body = '';
request.addListener('data', function (chunk) {
body += chunk;
});
request.addListener('end', function() {
console.log(body);
res.write('post data: ' + body);
});
Additionaly, there seem to be some issues with your client-side code (especially concerning the status-code checks), but i can't really help you with those as i always work with frameworks like jQuery to manage async requests.
If you want to build reliable node.js servers for web use, i highly recommend the high-performance HTTP-Framework Express. It takes away alot of the pain when developing a web-based server application in node and is maintained actively.