I have a Node.js webserver and I am fetching data from a mysql Server. The fetched Data needs to be displayed now in the frontend as HTML. I am not allowed to use any 3rd Party node.js/JavaScript framework's.
I'm new to Webserver development and i'm having a hard time figuring out how to "transport" the Backend Data to the Frontend.
I have 2 Ideas in my mind but dont know what's the right way to approach this problem...
Send Data via JSON to Client and process it with JavaScript. (Possible? and if yes how?)
Before sending the HTTP response, parse the HTML and insert the data. (Complicated without using Frameworks and too costly ?)
What would be the right way to solve this problem ?
Any Help would be appreciated. Thank's.
Solved it like this:
app.js
var http = require('http');
var url = require('url');
var server = http.createServer(function(req, res) {
var q = url.parse(req.url, true);
if(q.filename == "command"){
res.writeHead(200, {'Content-Type':'application/json'});
return res.end(some_json);
}
}
index.html
<script>
xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST","http://localhost:8000/command", true);
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//Process Data
var jsonObj = JSON.parse(xmlhttp.responseText);
document.getElementById("test").innerHTML = jsonObj;
}
}
xmlhttp.send();
</script>
<div id="test"></div>
Something like this?
const http = require('http');
const util = require('util');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
mysql.query("select * from table").then(rows => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end(`<html><head></head><body>${util.inspect(rows)}</body></html>`);
})
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Related
I am trying to communicate with the frontend to the backend. currently, I have the backend sending an expression to the frontend, and the frontend computes it. from there I want the frontend to send the computed answer back to the backend.
Forexample:
the backend sends "2+2="
the frontend computes that 2+2 = 4
the frontend then sends the answer 4 to the backend
the backend logs the answer 4
Front-end
var XMLHttpRequest = require('xhr2');
const URL = "http://localhost:5000/"
let firstNumber = Math.floor(Math.random() * 10);
let secondNumber = Math.floor(Math.random() * 10);
const express = require('express');
const app = express();
// excecuting random addition
const finalExpression = firstNumber + "+" + secondNumber + "="
console.log(finalExpression);
var xhr = new XMLHttpRequest();
xhr.open("POST", URL, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
expression: finalExpression
}))
Back-end:
const express = require('express')
const app = express()
app.use(express.json())
app.post('/', (req, res) => {
console.log(req.body.expression);
arr = req.body.expression.split("")
console.log(parseInt(arr[0]) + parseInt(arr[2]))
// res.send(parseInt(arr[0]) + parseInt(arr[2]))
})
app.listen(5000, () => console.log())
as you can see, I tried res.send in the frontend to the backend.
You appear to have mixed things up a little.
You can't use express on the front-end - it's a node application. You shouldn't need to use XMLHttpRequest on the server at all. express will handle all the routing for you.
You should use fetch on the front-end to get/post requests to the server (I've used async/await here).
It might look a little more like this.
Server:
// Send an expression to the front-end
app.get('/getExpression', (req, res) => {
res.send(expression);
});
app.post('/postResult', (req, res) {
const result = res.body;
// Calculate whether the result is correct,
// and then send the answer back
res.send(isResultCorrect);
});
Client:
// To get the expression from the server
const response = await fetch('/getExpression');
const expression = await response.text();
// To post the result back to the server
const options = { type: 'POST', body: result };
const response = await fetch('/postResult', options);
const isResultCorrect = await response.text();
You invert frontend and backend :) It is the frontend that sends the XMLHTTPREQUEST and it is the server that processes the request and returns the response.
This being said, using res.send is the right solution to return a response. You did the right thing in BACKEND. Therefore, you can uncomment the // res.send(parseInt(arr[0]) + parseInt(arr[2])) and leave the backend code as it is.
What is missing in the FRONTEND is a code to listen to and handle this response :
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
console.log(xhr.response);
}
}
Add it after var xhr = new XMLHttpRequest();
Your code should then look like this :
var xhr = new XMLHttpRequest();
// New code added here
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
// Handle the response (ex: console.log it)
console.log(xhr.response);
}
}
xhr.open("POST", URL, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
expression: finalExpression
}))
I am trying to send a csv file which is uploaded by the user, from browser to nodejs server for processing (file is over 50 mb, so the page becomes unresponsive). I'm using XMLHttpRequest for this purpose. I cannot find a solution to this. Any help is appreciated.
Javascript code
var csv = document.getElementById('inputFile').files[0];
var request = new XMLHttpRequest();
request.open("POST", "/handleFile", true);
request.setRequestHeader("Content-type", "text/csv");
request.onreadystatechange = function() {
if (request.readyState === XMLHttpRequest.DONE && request.status === 200) {
console.log("yey");
}
}
request.send(csv);
NodeJS server
var express = require('express')
var app = express()
var bodyparser = require('body-parser')
app.post('/handleFile', function(req, res) {
console.log(req.body); // getting {} empty object here....
console.log(req);
var csv = req.body;
var lines = csv.split("\n");
var result = [];
var headers = lines[0].split("\t");
for (var i = 1; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split("\t");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
fileData = result;
});
What did I do wrong? Is the XMLHttpRequest used incorrectly? or there is some other thing that i did not understand ? why is there no data in req.body even though its a post request.
Or is there any other way to send a csv/text file to nodejs server from front end.
This question is not a duplicate because, the body-parser i.e. the middleware responsible for parsing the req.body does not handle text/csv and multipart/form-data . The above link is not the correct solution.
So, after looking around, I found that the problem was not my XMLHttpRequest. The request was received by the server just fine, but the body-parser could not parse the text/csv and multipart/form-data content-type. Here is the step by step answer to this problem.
In the client/browser-end whenever you are sending a large file to the server, convert it into multipart/form-data . It is the correct way of sending a text/csv/anyfile to the server.
var csv=document.getElementById('inputFile').files[0];
var formData=new FormData();
formData.append("uploadCsv",csv);
var request = new XMLHttpRequest();
//here you can set the request header to set the content type, this can be avoided.
//The browser sets the setRequestHeader and other headers by default based on the formData that is being passed in the request.
request.setRequestHeader("Content-type", "multipart/form-data"); //----(*)
request.open("POST","/handleFile", true);
request.onreadystatechange = function (){
if(request.readyState === XMLHttpRequest.DONE && request.status === 200) {
console.log("yey");
}
}
request.send(formData);
So, this is how you'll send your http request to the nodejs server.
On Node js server: Normally for application/json or any other request type the body-parser would have worked fine. But for large data and files i.e. multipart/form-data body-parser cannot parse the req.body. Thus it will give req.body as {} (empty object).
Read about body-parser here.
So for these content-type you can use other middleware for handleling the request. Some are multer,multiparty,busboy etc. I used multer.
Here is the code snipet.
//EXPRESS
var express = require('express')
var app = express()
var config=require('./config.js');
//multer
var multer = require('multer');
var upload = multer();
app.post('/handleFile',upload.single('uploadCsv'), function(req, res, next) {
// req.file is the `uploadCsv` file
// req.body will hold the text fields, if there were any
console.log(req.file);
// the buffer here containes your file data in a byte array
var csv=req.file.buffer.toString('utf8');
});
NOTE:
This will still give you an error in nodejs server.
hint: It has something to do with the line (*). Try removing it and see what happens.
Google the rest ;)
Im sorry if this may be a dumb question but i hit a wall and been trying to figure this out for hours.
How to call json api and and add it to html page via node.js
my api address is localhost:8080/api I'm routing my html page to index.html.
I'm guessing it to make son an array and then call array in html? I have n idea how to do that.
please help me out. thanks.
server.js`
var util = require('./util.js');
//call random gen - return string with 9 length.
var output = util.stringGen(9);
console.log(output);
var express = require('express');
var app = express();
var path = require('path');
// viewed at http://localhost:8080
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.get('/api', function(req, res){
res.json({healthy: output})
});
app.listen(8080);
Your question is how to call your server from your client.
You might choose different approaches depending on what client you are using.
For native javascript, you can try reading here or if you are using AngularJS, see how to use $http
The URL you would want to call is `http://localhost:8080/api'
To hit api on client side, you need to use XMLHttpRequest . I've added a simple example of how to do that using github api and displaying the response in the label field. Although you can display response in any way you want :
<body>
<script>
function httpGet(theURL) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", theURL);
xmlHttp.setRequestHeader("Content-Type", "application/json");
xmlHttp.send(null);
xmlHttp.onreadystatechange = function() {
var response = null;
if(xmlHttp.readyState == XMLHttpRequest.DONE) {
response = xmlHttp.responseText;
document.getElementById("response").value = response;
}
};
}
</script>
<input id="clickMe" type="button" value="get Data"
onclick="httpGet('https://api.github.com/search/users?q=rohankanojia')" />
<br>
Response : <input id="response" type="label"/>
</body>
I'm able to handshake from a JavaScript client (NOT browser or Node.js based) to a Node.js server that uses socket.io using http but not https. For https, the server code includes
var app = express();
var https = require("https");
var fs = require("fs");
var options = {
key: fs.readFileSync("server.key"),
cert: fs.readFileSync("server.cert")
};
var server = https.createServer(options, app);
var socketio = require("socket.io");
var io = socketio.listen(server);
server.listen(443);
and the client code includes
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://localhost:443/socket.io/1/");
xhr.onreadystatechange = function(){
if(xhr.readyState !== 4){
return;
}
callback({status: xhr.status,
header: xhr.getAllResponseHeaders(),
body: xhr.responseText
});
};
xhr.send();
The client is run after the server has started but the handshake fails with the values
readyState: 4
status: 0
header:
body:
Does the client need to include some security info or do something else for the handshake to work with https and get a session ID?
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.