I'm attempting to get a response from a Node application I created using the XMLHttpRequest object in JavaScript. The code I am using to do such is below:
var get = function()
{
var http = new XMLHttpRequest({mozSystem: true});
http.onreadystatechange = function() {
if (http.status === 200) {
console.log(http.responseText);
}
}
http.open("GET", "http://127.0.0.1:3000", true);
http.setRequestHeader("Content-Type", "text/plain");
http.send();
}
And the Node application is:
const http = require('http');
const fs = require('fs');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) =>
{
let body = [];
req.on('data', (chunk) =>
{
body.push(chunk);
}).on('end', () =>
{
body = Buffer.concat(body).toString();
if(req.method === "GET")
{
console.log("GET");
}
res.setHeader('Content-Type', 'text/plain');
res.end("Hello World");
})
});
However, nothing is being printed. I opened the developer tools in Chrome and Mozilla and can see that the status is 200, and the response is listed under the response for the Ajax call - it says clearly "Hello World".
I'm doing this all locally, as a Node demo for school. I have the application able to handle post requests perfectly fine - but getting the response from the GET request does not seem to work. I'm open to any and all advice!
Thank you in advanced.
To answer my question, I was not aware that not having CORs enabled would cause such behavior - the browser would show that the request was going through, the response could be seen in developer tools, but could not be printed to console. Thank you to Jaromanda for helping me come to realize this.
Related
This question already has answers here:
How can I make an AJAX call without jQuery?
(24 answers)
Closed 3 years ago.
I'm setting up my first server with node.js, but I don't know how to connect a client and that server. I don't want to use jquery, and all the questions I could find about this involved jquery or were about different languages. Does anyone know how to do this?
Edit: I have a connection between the server and client, but the response has nothing in it. The code for my server is here, and the code for my client is here (in the folder "Multiplayer").
Do something like this to setup a Node.js HTTP server listenning on port 8080.
The client will send GET requests using AJAX.
index.html
<html>
<head>
<script>
var xhttp = new XMLHttpRequest();
// Create a function callback, called every time readyState changes
xhttp.onreadystatechange = function()
{
// When the response has been received with status 200
// Update the element div#response-holder
if (this.readyState == 4 && this.status == 200)
{
var txtDisplay = elem document.getElementById("response-holder")
txtDisplay.innerHTML = this.responseText;
}
};
// Send a GET request to /api, asynchronously
xhttp.open("GET", "/api", true);
xhttp.send();
<script>
</head>
<body>
<div id="response-holder"></div>
</body>
</html>"
server.js
// Load the http and fs (filesystem) modules
var app = require("http");
var fs = require("fs");
// Serve the "/index.html" home page on port 8080
app.createServer(function (req, resp)
{
fs.readFile("index.html", function(err, data)
{
resp.writeHead(200, {'Content-Type': 'text/html'});
resp.write(data);
resp.end();
}
);
}
).listen(8080);
// Also answer to GET requests on "/api"
app.get('/api', function(req, resp)
{
var responseStr = "Hello World!";
resp.status(200);
resp.setHeader('Content-type', 'text/plain');
return resp.send(responseStr);
}
);
Here is a W3Schools tutorial on AJAX:
https://www.w3schools.com/js/js_ajax_intro.asp
You may do that with vanilla JavaScript, using Fetch API.
Assuming that Node will provide you some URLs, you can get, post, etc., through fetching them.
More on how that works here:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
TCP connection between client and Node server will be the option. Here's a sample code snippet:
var ser = require('ser');
var clientSer = new net.Socket();
clientSer.connect(1220, '127.0.0.1', function() {
console.log('Connected');
client.write('Hello, Connection Established!');
});
clientSer.on('data', function(data) {
console.log('Received: ' + data);
client.destroy(); // kill client after server's response
});
clientSer.on('close', function() {
console.log('Connection closed');
});
Node tutorial: https://www.w3schools.com/nodejs/nodejs_intro.asp
I'm new to using nodejs and javascript so I'm sorry if I'm just doing something obviously wrong. I have a nodejs app I'm running and serves a html page. That html page can send Post requests using XMLHttpRequest. The request goes though and my node app calls the function that my request is meant to invoke. The problem is I want to get some data back from that request so I am trying to get that from the response to the request. The issue is I am getting an empty response and I do not know why.
Here is my request.
function SendCachedTriangulation(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById('responseLog').textContent = "sent triangulation: " + this.response;
}
};
xhttp.open("Post", "/sendCachedTriangulation");
xhttp.setRequestHeader("Content-type", "application/json");
var text = '{ "data" : ' + '{ "someData":"' + '1' + '" } }';
xhttp.send(text);
return false;
}
The result I get from this is response is empty. It does update the element I am trying to update but it just says "sent triangulation: ".
On the nodejs side this is my code.
router.post('/sendCachedTriangulation', (req, res, next) => {
client.SendCachedTriangulation(() => {
res.status(200)
;}, req.body
);
res.status(200).message = "sent triangulation";
res.send();
});
Which this seems to be calling my function to send cached triangulation properly i just don't get that "sent triangulation" message.
What do I need to change to display that message in my HTML page?
Actually I understood your snippet. I also understand that is complicated at first time with Node, because is everything Javascript. Let me explain: in your HTML, think the request is OK, but actually have, let's say, two files: HTML file, that performs the request, and the node HTTP server, that responds the request. So I mean something like:
// /server/app.js
router.post('/sendCachedTriagulation', (req, res, next) => {
res.status(200).send("sent triangulation")
})
// /client/index.html
client.SendCachedTriangulation(/* do stuff */)
Overarching goal is to save some JSON data I create on a webpage to my files locally. I am definitely sending something to the server, but not in format I seem to able to access.
JsonData looks like:
{MetaData: {Stock: "UTX", Analysis: "LinearTrend2"}
Projections: [2018-10-12: 127.62, 2018-10-11: 126.36000000000001, 2018-10-10: 132.17, 2018-10-09: 140.12, 2018-10-08: 137.73000000000002, …]}
XMLHttpRequest on my webpage:
function UpdateBackTestJSON(JsonUpdate){ //JsonUpdate being the JSON object from above
var request = new XMLHttpRequest();
request.open('POST', 'UpdateBackTestJSON');
request.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
// request.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
request.onload = function() {
console.log("Updated JSON File");
};
console.log("about to send request");
console.log(JsonUpdate);
request.send(JSON.stringify(JsonUpdate));
}
and I handle posts on my server (rather carelessly I realize, just going for functionality as a start here)
var http = require('http')
, fs = require('fs')
, url = require('url')
, port = 8008;
var server = http.createServer (function (req, res) {
var uri = url.parse(req.url)
var qs = require('querystring');
if (req.method == 'POST'){
var body = '';
req.on('data', function (data){
body += data;
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6){
// FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
req.connection.destroy();
}
});
req.on('end', function () {
var POST = qs.parse(body);
console.log(POST); // PARSED POST IS NOT THE RIGHT FORMAT... or something, idk whats going on
UpdateBackTestData(POST);
});
}
function UpdateBackTestData(TheJsonData){
console.log("UpdateBackTestData");
console.log(TheJsonData);
JsonUpdate = JSON.parse(TheJsonData);
console.log(JsonUpdate["MetaData"]);
//var Stock = JsonUpdate["MetaData"]["Stock"];
// var Analysis = JsonUpdate["MetaData"]["Analysis"];
fs.writeFile("/public/BackTestData/"+Analysis+"/"+Stock+".json", TheJsonData, function(err){
if(err){
console.log(err);
}
console.log("updated BackTest JSON!!!");
});
}
Most confusing to me is that when I run this, the Json object Im am trying to pass, does go through to the server, but the entirety of the data is a string used as a key for a blank value in an object. when I parse the body of the POST, I get: {'{MetaData:{'Stock':'UTX','Analysis:'LinearTrend2'},'Projections':[...]}': ''}. So my data is there... but not in a practical format.
I would prefer not to use express or other server tools, as I have a fair amount of other services set up in my server that I don't want to go back and change if I can avoid it.
Thanks for any help
I am very new with node js and decided to learn how to secure api keys, i've looked everywhere but can't find a example. But i found some that suggest the only way is to do a server side api request.
I am using openweathermap api for this code, i get the expected data back as a response in chrome network tab but i have questions regarding it.
How do i use the response data (e.g getting the current weather, temp) ?
Is this the proper way on doing a server side api request in node.js?
http.createServer(function(req, res) {
if (req.url === '/') {
res.writeHead(200, {"Content-Type": "text/html"});
fs.createReadStream(__dirname + '/index.html').pipe(res);
} else if (req.url === '/getweather') {
var weatherApiURL = 'https://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=<API KEY>';
request(weatherApiURL, function (error, response, body) {
if (error) {
res.writeHead(500, 'Weather API request failed', {'content-type': 'text/plain'});
res.end();
} else {
res.writeHead(200, {'content-type': 'application/json'});
res.end(body);
}
});
} else {
res.end('not found')
}
}).listen(8080);
Front:
function requestWeatherData() {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getweather', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
console.log(this.responseText);
};
xhr.send();
};
Thank you in advanced!!
Part 1: How to use the data.
The first thing you'll want to do is to check whether the request succeeded
if (this.status !== 200) {
// The request did not work.
throw new Error('Cannot use data.');
}
Once the requset status has been verified you need to 'parse' the response.
const weatherData = JSON.parse(this.responseText);
// Lets see the js object:
console.log(weatherData);
Now you can do whatever you need with the data.
The full example:
function requestWeatherData() {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getweather', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
if (this.status !== 200) {
// The request did not work.
throw new Error('Cannot use data.');
}
const weatherData = JSON.parse(this.responseText);
// Lets see the js object:
console.log(weatherData);
};
xhr.send();
};
Part 2: Is there a proper way of doing this?
Now, I don't not know enough about this to say definitely, however, here are some concerns that you may want to think about.
Most APIs have rate limits, meaning you probably want to try to 'cache' the requests somewhere to reduce the need to 'poll' the APIs
Other people could use your exposed url in their application.
Writing all of the routes as you are currently will become a real headache for larger applications, I can recommend express from experience for small to medium applications.
Technically this is my first try in nodejs and frankly I am not sure if I am doing it right. I am creating a local server that will stream the output from a distant server. However, when I run my code and I enter a URL in the browser, the program fails with the following message:
events.js:45
throw arguments[1]; // Unhandled 'error' event
^
Error: ENOTFOUND, Domain name not found
at IOWatcher.callback (dns.js:74:15)
The URL I used was: 127.0.0.1:9000/http://www.yahoo.fr. And in the browser I had the following message:
No data received
Unable to load the webpage because the server sent no data.
Here are some suggestions:
Reload this web page later.
Error 324 (net::ERR_EMPTY_RESPONSE): The server closed the connection without sending any data.
Any help is greatly appreciated.
Here is the code:
var base, dest, node_client,
count = 0,
url = require('url'),
util = require('util'),
http = require('http'),
http_client = require('http'),
request = require('request'),
events = require('events'),
httpProxy = require('./lib/node-http-proxy'),
data_emitter = new events.EventEmitter();
httpProxy.createServer(9000, 'localhost').listen(8000);
http.createServer(function (req, res) {
if(!count)
{
base = url.parse(req.url).pathname;
node_client = http_client.createClient(80, base);
count++;
} else {
dest = req.url.substr(1, req.url.length -1);
}
request = node_client.request("GET", dest, {"host": base});
request.addListener("response", function (response) {
var body = "";
response.addListener("data", function (data) {
body +=data;
});
response.addListener("end", function () {
var out = JSON.parse(body);
if(out.length > 0) {
data_emitter.emit("out", out);
}
});
});
// request.close();
var listener = data_emitter.addListener("data", function(out) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(JSON.stringify(out));
res.close();
});
}).listen(9000);
Wild guess : your browser automatically requests 127.0.0.1:9000/favicon.ico and your program then tries to resolve favicon.ico which obviously fails and makes your program crash before it can send any data for the real request.
Why such tangled code?
This is a scenario where it makes sense to avoid nested callbacks, and use named functions. If you refactor the code, then people are more likely to be help you.
Can you do console.log(out) in your listener callback? Let us know if Node.js has any response data to return.
Well, for any newbie like me in this area, here is how I solved it. It's not clean and can be implemented in better way. Feel free to change, give suggestions.
Code:
var url = require('url'),
http = require('http'),
request = require('request'),
httpProxy = require('./lib/node-http-proxy'),
des = '',
util = require('util'),
colors = require('colors'),
is_host = true;
httpProxy.createServer(9000, 'localhost').listen(8000);
var server = http.createServer(function (req, res) {
var pathname = '';
if(is_host) {
dest = req.url.substr(0, req.url.length -1);
pathname = dest;
is_host = false;
} else {
pathname = req.url.substr(0, req.url.length);
if(pathname.charAt(0) == "/") {
console.log('new request');
console.log(pathname);
pathname = dest + pathname;
}
}
console.log(pathname);
request.get({uri: pathname}, function (err, response, html) {
res.end(html);
});
console.log('fetched from ' + pathname);
});
server.listen(9000);