I have a site in javascript where I get information from a Rest API (JSON)
I would like to make this information available to my server (A node.js that I have created that connects to the database)
It is my first time working with web development; I would like to know how I make the connection between the two?
front end
<!DOCTYPE html>
<head>
<style>
.bodyFrame {
margin: 40px;
}
.headerLabel {
font-weight: bold;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class="bodyFrame">
<h2 style="text-align:center;">WIDS JSON Retrieval Example</h2>
<button type="button" onclick="makeServiceCall()">Retrieve JSON Data</button>
<br /><br />
<label class="headerLabel">Programs</label>
<ul id="programUL"></ul>
<div>
<script>
function makeServiceCall() {
var url = "http://widsservicedev.yaharasoftware.com/WidsService/JSON/GetPortagePrograms/?apikey=104043F0-9C24-4957-879D-046868973CC4&callback";
$.getJSON(url, function (data) {
//var myArray = [];
//myArray[0] = data;
parseProgramData(data, url);
});
}
function parseProgramData(jsonData, url) {
$("#dataHeader").empty();
$("#dataHeader").append('<b>' + url + '</b>');
var programUL = document.getElementById("programUL");
for (var pgmIndex = 0; pgmIndex < jsonData.Programs.length; pgmIndex++) {
var pgmLi = document.createElement("li");
var program = jsonData.Programs[pgmIndex];
var programInfoRevision = program.ProgramInfoRevisions[0];
var numberTitle = programInfoRevision.ProgramNumber + " " + programInfoRevision.ProgramTitle;
pgmLi.appendChild(document.createTextNode(numberTitle));
programUL.appendChild(pgmLi);
var linebreak = document.createElement("br");
pgmLi.appendChild(linebreak);
var poLabel = document.createElement("label");
poLabel.appendChild(document.createTextNode("Program Outcomes"));
poLabel.classList.add("headerLabel");
pgmLi.appendChild(poLabel);
var pgmOutcomeUL = document.createElement("UL");
pgmLi.appendChild(pgmOutcomeUL);
for (var poIndex = 0; poIndex < program.ProgramOutcomes.length; poIndex++) {
var poLi = document.createElement("li");
poLi.appendChild(document.createTextNode(program.ProgramOutcomes[poIndex].Description));
pgmOutcomeUL.appendChild(poLi);
}
}
}
</script>
</body>
<footer>
</footer>
node.js
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
/* var config = { user: 'papercut', password: 'Portage.2018', server: 'devsqlcl2:1433', database: 'AgrM6', port: "1433", dialect:",ssql", dialectOptiond:"SQLEXPRESS" };*/
// connect to your database
sql.connect('mssql://xxx:xxxx#xxxx:1433/xxx', function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from dbo.balance_papercut', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
});
var server = app.listen(5000, function () { console.log('Server is running..'); });
Thank you.
Well to make those data available to the server you basically have to sent a request to the server containing those data. Since you want to sent data to the server you most likely need to use a POST request. There are more informations here about how to send such a request.
On the server side you need to an endpoint listening for a post request. You can find a lot of information about how to do this on the server on google.
A simple way to accomplish connection between frontend and backend is to create api-endpoints. You have already done so with your app.get('/', function (req, res).
You can do a similar one for sending data to the server. The http method used to send data to the server is generally POST. You can read more about the http methods here:
https://restfulapi.net/http-methods/
A good guide I stumbled upon a few weeks ago are this one:
https://codeforgeek.com/2014/09/handle-get-post-request-express-4/
In this example it does exactly what you're trying to accomplish, by sending data from a script in a static html-file to an Express server.
Related
Program runs as it should until I try to use the function once again and it returns the error: Can't set headers after they are sent.
I'm creating this app to familiarize myself with nodejs and javascript and I've been reading about the error and it seems to be an issue when sending more than one response to a request. I started using res.setHeader before knowing this, but I read that res.header could avoid this problem, it didn't solve it but I kept it.
HTML:
<!doctype html>
<head>
<link rel="stylesheet" type="text/css" href="youtube2music.css">
<title>
Youtube2Music
</title>
</head>
<body>
<div id="cabeza">
<h1>
Youtube 2 Music
</h1>
<p>
just paste your link below and download your song.
</p>
</div>
<div id="down-part">
<input id="myUrl" class='myUrl-input'>
</input>
<button type="button" class="download_button">
Download
</button>
</div>
</body>
<script src='youtube2music.js'></script>
</html>
Javascript:
var urlinput = document.querySelector('.myUrl-input'); // gets url inputbox
var button = document.querySelector('.download_button'); // gets download button
button.addEventListener('click', () => {
console.log(urlinput.value); // prints in console the url
sendUrl(urlinput.value); // sends url to function to start the request
});
// function to make requst
function sendUrl(URL){
window.location.href = `http://localhost:4000/?URL=${URL}`; // makes the video request to nodejs server
}
index.js < node file:
var eventEmitter = new events.EventEmitter();
var sfn;
appi.use(cors());
const {app, BrowserWindow} = require('electron')
function createWindow(){
let win = new BrowserWindow({width:800, height:600});
win.loadFile('index.html');
}
app.on('ready', createWindow)
appi.listen(4000, () => {
console.log('server at port 4000');
});
appi.get('/',(req,res)=>{
var URL = req.query.URL;
ytdl.getInfo(URL, function(err,info){
if(err) throw err;
var songTitle = info.title;
sfn = filenamify(songTitle);
eventEmitter.emit('name_ready');
});
var startDownload = function(){
let stream = ytdl(URL, {
quality: 'highestaudio',
});
res.header('Content-Disposition', 'attachment; filename=' + sfn + '.mp3');
res.header('Content-type', 'audio/mpeg');
proc = new ffmpeg({source: stream})
proc.withAudioCodec('libmp3lame').toFormat('mp3').output(res).run();
}
eventEmitter.on('name_ready', startDownload);
})
as it is works for the first input but asking for another output results in error, why is it really returning this error and how can it be avoided?
There are several problems with your current setup:
Try not to use event emitter for signaling events within an HTTP request, it wasn't made for this.
With HTTP requests, try not to use global variables for data received during the request, when two requests come in at the same time, they may get confused and get sent the wrong data.
appi.listen(4000, () => {
console.log('server at port 4000');
});
appi.get('/', (req,res)=> {
const { URL } = req.query;
ytdl.getInfo(URL, (err,info) => {
if(err) throw err;
const songTitle = info.title;
const sfn = filenamify(songTitle);
let stream = ytdl(URL, {
quality: 'highestaudio',
});
res.set('Content-Disposition', 'attachment; filename=' + sfn + '.mp3');
res.set('Content-type', 'audio/mpeg');
const proc = new ffmpeg({source: stream})
proc.withAudioCodec('libmp3lame').toFormat('mp3').output(res).run();
});
})
I am trying to build a gnuchess web api and bind it to a graphical web interface. Trought a websocket the users will connect and when connecting the server-websocket will launch a "gnuchess" as subprocess. Then I would like to communicate with the gnuchess's stdin/stdout and send the stream to the user. But as the code is today it only starts new gnuchess's but I could only write to one of them (with all connected clients I could do that)
I have this code node-code:
var http = require("http");
var ws = require("./");
var fs = require("fs");
var process = require('child_process');
theglobal = "";
var ls = "";
// Web server
http.createServer(function (req, res) {
fs.createReadStream("index.html").pipe(res)
}).listen(8080);
// Socket stuff
var server = ws.createServer(function (connection) {
connection.on("text", function (str) {
var tmp_cmd = str.split(" ")[0];
var tmp_string = str.substr(str.indexOf(" ") + 1);
console.log(tmp_cmd)
console.log(tmp_string)
if (tmp_cmd == "move") {
ls.stdin.write(tmp_string + "\n");
connection.sendText(str);
}
if (str == "start") {
connection.sendText(str);
ls = process.spawn('/usr/games/gnuchess');
ls.stdout.on('data', function (chunk) {
broadcast(chunk)
});
}
})
});
server.listen(8081);
// Functions
// This broadcasts to all clients connected
function broadcast(str) {
server.connections.forEach(function (connection) {
connection.sendText(str)
})
}
HTML:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Chat example</title>
<script>
var connection
window.addEventListener("load", function () {
var nickname = prompt("Choose a nickname")
if (nickname) {
connection = new WebSocket("ws://"+window.location.hostname+":8081")
connection.onopen = function () {
console.log("Connection opened")
connection.send(nickname)
document.getElementById("form").onsubmit = function (event) {
var msg = document.getElementById("msg")
if (msg.value)
connection.send(msg.value)
msg.value = ""
event.preventDefault()
}
}
connection.onclose = function () {
console.log("Connection closed")
}
connection.onerror = function () {
console.error("Connection error")
}
connection.onmessage = function (event) {
var div = document.createElement("div")
div.textContent = event.data
document.body.appendChild(div)
}
}
})
</script>
</head>
<body>
<form id="form">
Message: <input size="50" id="msg"> <input type="submit" value="Submit">
</form>
</body>
</html>
But what happens is that it starts a new gnuchess for every user who connects (it should be like that) but the data routes to the first openeded gnuchess.
Could solve the problem by using a IRC bot and IRC server and use different channel for each game (#gnuchess_user1, #gnuchess_user2, etc..) But I think it's easier actually to solve it by making a method or own object for each user and route it in the websocket.
You should look at socket.io, it has built in support for rooms:
io.on('connection', function(socket){
socket.join('some room');
});
Which means you can broadcast to all sockets connected to that room. You don't have to spawn separate processes for these (it will be devastating for your performance..)
io.to('some room').emit('some event');
http://socket.io
I am trying to do something seemingly very simple but I'm having trouble working it out. Users can submit some text using a HTML form with POST method. This is then sent off to an API for processing, and returns with a JSON object. I then just want the app.js file to send this JSON object back so I can play around with it using JQuery.
Here is the .post method in my app.js
app.post('/', function(req, res){
console.log("starting app.post");
// See User Modeling API docs. Path to profile analysis is /api/v2/profile
// remove the last / from service_url if exist
var parts = url.parse(service_url.replace(/\/$/,''));
var profile_options = { host: parts.hostname,
port: parts.port,
path: parts.pathname + "/api/v2/profile",
method: 'POST',
headers: {
'Content-Type' :'application/json',
'Authorization' : auth }
};
// create a profile request with the text and the https options and call it
create_profile_request(profile_options,req.body.content)(function(error,profile_string) {
if (error) {res.render('home.html',{'error': error.message});
console.log("errormessage: "+error.message);
}
else {
// parse the profile and format it
var profile_json = JSON.parse(profile_string);
var flat_traits = flatten.flat(profile_json.tree);
// Extend the profile options and change the request path to get the visualization
var fileName="file 1"; //this will eventually be imported automatically
//console.log(flat_traits);
var scoreObject={"title":fileName, "percentage":functions.matchPercentage(flat_traits)}
res.send(scoreObject); //this is what I assume should send this back client-side
});
}
});
});
// creates a request function using the https options and the text in content
// the function that return receives a callback
var create_profile_request = function(options,content) {
return function (/*function*/ callback) {
// create the post data to send to the User Modeling service
var post_data = {
'contentItems' : [{
'userid' : 'dummy',
'id' : 'dummyUuid',
'sourceid' : 'freetext',
'contenttype' : 'text/plain',
'language' : 'en',
'content': content
}]
};
// Create a request to POST to the User Modeling service
var profile_req = https.request(options, function(result) {
result.setEncoding('utf-8');
var response_string = '';
result.on('data', function(chunk) {
response_string += chunk;
});
result.on('end', function() {
if (result.statusCode != 200) {
var error = JSON.parse(response_string);
console.log("status: "+result.statusCode);
callback({'message': error.user_message}, null);
console.log(error.user_message);
} else
callback(null,response_string);
});
});
profile_req.on('error', function(e) {
callback(e,null);
});
profile_req.write(JSON.stringify(post_data));
profile_req.end();
}
};
So I presume res.send is what passes the data across to the client-side, but then how do I receive the data on the client-side? This is my attempt at the JScript:
$.getJSON('/').done(function(data){
$('#resultsList').append('<li data-icon="arrow-r" data-iconpos="right" id="'+
data.title+'"> <a href="#breakdownDialog"> <div id="cvResults"><h3>'+
data.title+'</h3> <span>'+data.percentage+
'%</span></div></a><div id="output"></div></li>');
console.log(data.title+data.percentage);
}
});
I want to take some of the values from the JSON object and put them in a list on the existing HTML page. At the moment this just takes me to a different blank page that says Undefined.
How should I grab the JSON data from the server?
EDIT: Here's the HTML form I am submitting the data with:
<form method="POST" id="submitForm">
<fieldset>
<textarea id="textArea" required="true" rows="5" name="content"></textarea>
<button class="btn btn-block" type="submit">
Analyse
</button>
</fieldset>
</form>
Are you sure that you are sending json with res.send()? Try to set header
res.set('Content-Type', 'application/json') or use this res.json() instead of res.send()
I've created client and server of node with socket.io. server is executing 4 get requests of news feed and fetched the data. These data is sent to the client with socket.io.
client is displaying news feed on the occurrence of specific socket.io event.
This works well for once. Here is the code and working fiddle
server.js
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
, redis = require("redis");
var http = require("http");
// initialize the container for our data
var data = "";
var nfs = [
"http://economictimes.feedsportal.com/c/33041/f/534037/index.rss",
"http://www.timesonline.co.uk/tol/feeds/rss/uknews.xml",
"http://www.independent.co.uk/news/business/rss",
"http://www.dailymail.co.uk/money/index.rss"
];
//setInterval(function() {
for(var i=0; i<nfs.length; i++){
//console.log(nfs[i]);
http.get(nfs[i], function (http_res) {
// this event fires many times, each time collecting another piece of the response
http_res.on("data", function (chunk) {
// append this chunk to our growing `data` var
data += chunk;
});
// this event fires *one* time, after all the `data` events/chunks have been gathered
http_res.on("end", function () {
// you can use res.send instead of console.log to output via express
console.log("data received");
});
});
}
//}, 30000);
app.listen(8080);
function handler (req, res) {
fs.readFile(__dirname + '/client.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.on('connection', function (socket) {
//setInterval(function() {
socket.emit('news', data);
/*socket.on('my other event', function (data) {
console.log(data);
});*/
//}, 5000);
});
client.html
<html>
<head>
<script src="https://cdn.socket.io/socket.io-1.2.1.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
//socket io client
var socket = io.connect('http://localhost:8080');
//on connetion, updates connection state and sends subscribe request
socket.on('connect', function(data){
setStatus('connected');
socket.emit('subscribe', {channel:'notif'});
});
//when reconnection is attempted, updates status
socket.on('reconnecting', function(data){
setStatus('reconnecting');
});
//on new message adds a new message to display
socket.on('news', function (data) {
console.log(data);
//socket.emit('my other event', { my: 'data' });
addMessage(data);
});
/*socket.on('news', function (data) {
debugger;
socket.emit('my other event', { my: 'data' }
var msg = "";
if (data) {
msg = data;
}
addMessage(msg);
});*/
//updates status to the status div
function setStatus(msg) {
$('#status').html('Connection Status : ' + msg);
}
//adds message to messages div
function addMessage(msg) {
//debugger;
var $xml = $(msg);
var html = '';
$xml.find("item").each(function() {
var $item = $(this);
html += '<li>' +
'<h3><a href ="' + $item.find("link").text() + '" target="_new">' +
$item.find("title").text() + '</a></h3> ' +
'<p>' + $item.find("description").text() + '</p>' +
// '<p>' + $item.attr("c:date") + '</p>' +
'</li>';
});
$('#result').prepend(html);
}
</script>
</head>
<body>
<div id="status"></div><br><br>
<ul id="result"></ul>
</body>
</html>
What I understand about socket.io is that we don't need long server polling and so how do server come to know that news is added to the respected news feed.
How do I update the client with newly added news when news is added to the news feed rss ???
Update
Ok so from all the responses I get the point that it is not possible for socket.io to know that new entry has been added. So, how do I know (which tools/libraries do require to know that new entry has beed added and update the client as well) ???
Retrieving the messages from the news feeds are completely independent of socket.io unless the news feeds implement sockets on their end and your server becomes their client. So you will have to continue to poll them with http requests to know whether they have updated data.
In order to notify your clients of the update you would just emit the news event. Presumably you would have logic on the server to make sure you are only sending events which have not previously be sent.
There is no way for "node" to know when a new entry is added to the news feed. You will have to poll the news service like you are doing now. This really has nothing to do with Node or Socket.io unless I completely misunderstand what you are asking.
I have a webpage which creates a JSON object based on user input. I would like to then somehow allow the user to submit this JSON object to a NodeJS script for processing/insertion into a MySQL database. However, I'm really not sure how to do something like this -- the best I can come up with is some form of a POST, but I'm not sure where to start with this.
Because I don't know what such a method would be described as, I haven't had much success in locating any tutorials or other resources online.
Could anyone suggest some articles or documentation to look at that would be relevant to something like this? Or, at least, tell me what to search for? Thanks.
EDIT: This is the code I am trying to get working at the moment. I'm just trying to convert the POST data type from string to JSON on both sides.
Serverside:
var express = require('express');
var fs = require('fs');
var app = express();
app.use(express.bodyParser());
app.get('/', function(req, res){
console.log('GET /')
//var html = '<html><body><form method="post" action="http://localhost:3000">Name: <input type="text" name="name" /><input type="submit" value="Submit" /></form></body>';
var html = fs.readFileSync('index.html');
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(html);
});
app.post('/', function(req, res){
console.log('POST /');
console.dir(req.body);
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('thanks');
});
port = 8080;
app.listen(port);
console.log('Listening at http://localhost:' + port)
Clientside:
<html>
<body>
<form method="post" action="http://localhost:8080">
Name: <input type="text" name="name" />
<input type="submit" value="Submit" />
</form>
<script type="text/JavaScript">
console.log('begin');
var http = new XMLHttpRequest();
var params = "text=stuff";
http.open("POST", "http://localhost:8080", true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//http.setRequestHeader("Content-length", params.length);
//http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {
console.log('onreadystatechange');
if (http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
else {
console.log('readyState=' + http.readyState + ', status: ' + http.status);
}
}
console.log('sending...')
http.send(params);
console.log('end');
</script>
</body>
</html>
Here is a very basic example using jQuery to do the post request and an express app. I think it should be a decent starting point.
// client side, passing data to the server
$.post("/foo/", { data : { foo : "bar" } }, function(temp) {
// temp === "I am done";
});
// serverside app.js
var express = require("express");
var app = express();
// will parse incoming JSON data and convert it into an object literal for you
app.use(express.json());
app.use(express.urlencoded());
app.post("/foo/", function(req, res) {
// each key in req.body will match the keys in the data object that you passed in
var myObject = req.body.data;
// myObject.foo === "bar"
res.send("I am done");
});
EDIT: JSON.stringify() and JSON.parse() will serialize/deserialize JSON. (jQuery makes this much easier, but if you wanna go pure javascript)
Change to var params = "text=" + JSON.stringify({ foo : "bar" });
and
console.dir(JSON.parse(req.body.text));
It worked for me on my local.