Send response multiple times? - javascript

I have a little problem.
I have a node application on a server, that serves a website as control panel for a client based application.
Example:
You click a link on the site
A http request triggers the server to send a command via socket to the client
The client executes this command
The client sends the output of the command back to the server (socket)
That works fine, on time. The second time the server crashes because the header is already sent.
//Comand comes in
app.get('/create/:id/:package', function (req, res) {
if (io.sockets.connected[req.params.id]) {
//Command is sent to client
io.sockets.connected[req.params.id].emit('control', {type: 'create', packageName: req.params.package});
//Output is coming back
socket.on('createOutput', function (data) {
//Response sent back to http request (works once)
res.send(data);
});
}
});
Is there any way to work around this behavior?

You can send the data only once with socket.once:
socket.once('createOutput', function (data) {
//Response sent back to http request (works once)
res.send(data);
})

Related

I don't fully understand what app.get('/consult')

I am new to express and I still struggle with the meaning of app.get().
In my HTML page, I have a button with the id=consult-button.
I gave it the following script:
document.getElementById("consult-button").addEventListener("click", function() {
window.location.href = '/consulting';
});
On my app.js file, on the other hand, I have:
app.get('/consulting', (req, res) => {
const client = new pg.Client(config);
client.connect();
client.query('SELECT * FROM questionaire', (err, result) => {
if (err) {
console.log(err);
}
res.send(result.rows);
client.end();
});
});
Can someone help me understand this? Tell me if what I am writing is right:
when the button is clicked, a url with the name "consulting" is created. then app.get call on that url and sends the results of the query in that url?
When the user clicks on the button on the web page, the browser is going to send an HTTP GET request to the endpoint on the server (/consulting),
for example, if your website domain is www.example.com, the browser is going to send the request to www.example.com/consulting,
or if your domain is 192.168.1.50:3000 for example in case you're working on localhost for example, the website is going to send a request to 192.168.1.50:3000/consulting.
But this piece of code doesn't only send a request to the server, it also changes the URL to /consulting, (ex: www.example.com becomes www.example.com/consulting).
Now when the request travels from the website (the computer of the website visitor) to the back-end server (which is express in your case), express is going to catch this request in the following controller (it's called a controller)
app.get('/consulting', (req, res) => {
const client = new pg.Client(config);
client.connect();
client.query('SELECT * FROM questionaire', (err, result) => {
if (err) {
console.log(err);
}
res.send(result.rows);
client.end();
});
});
app.get is the controller which catches this request and handles it because it's
app.get('/consulting') which matches the destination of the request.
Now this controller has a bunch of codes, it basically sends a request to the Postgres database saying "SELECT * FROM questionaire" which basically means give me all the entries inside the questionaire table.
the database responds with that, so the server (the controller) takes care of the response from the database and forwards it back to the website.
Hope this helps.

Is it possible to send second request over persistent connection, before response is returned. Node.js

I know it sound strange but the situation is strange. I have been trying to send second request to the server(over the same connection) before the first response. What I get is response to the first request and the second one is ignored by the server. The server keeps the connection alive:
server.on("connection", socket => {
socket.setTimeout(50 * 1000);
socket.on("timeout", () => {
console.log("socket timeout");
socket.end();
});
socket.on("close", hadError => {
console.log(
hadError
? "Socket closed due to ERROR during transmission"
: "Socket closed"
);
});
});
This is the route that handles the request:
app.post("/enddev", (req, res) => {
console.log("REQUEST TO ", req.route.path);
console.log("Req Header ", req.headers);
res.write("request\r\n");
setInterval(() => {
res.write("ack\r\n");
}, 2000);
});
I think that the HTTP protocol does not allow this, but may be there is some workaround.
Websockets are not solutions because the client is (not a browser) an embedded device.
And here is an image of the test (I use a TCP client terminal program ti simulate the request message from the client):
The right terminal (black one) is the node server. The white one is the terminal. On the terminal in pink is is what the client sent. In black is the response from the server. You can see that the server sends "request" message right after the header. But upon second request no response appears.
I don't think you're ever calling res.end(). Without that, node.js thinks your response is not over yet.

Handling ajax requests, not receiving data

i'm having a hard time setting up my client-side ajax calls to send data to node express server.
i want to fire my ajax request "onclick" of an href link.
I'm trying to send the ID of the link as a variable to the server, but the server doesn't receive my data (without setInterval)
if i put the ajax request inside a setInterval() (which i don't want to do, because i only want to send the data once a link is clicked to the server),
the server receives the data in res.req.body, why?
client side:
$('.link_group').click(function () {
data = $(this).attr('id');
$.ajax({
type: "POST",
url: "/ajax_handler",
data: {id: data}
});
});
server side
app.post("/ajax_handler", function(req, res) {
res.send({ //works as it should....
user : req.session.user,
data_objekt: req.session.data
});
if(res.req.body) {
console.log(res.req.body);
}
});
Is this even a common way to "catch" the data from client?
if(res.req.body) {...
doesn't seems right, but i don't know how to do it in a smarter way / can't find any good examples.
I'm about to fire 3-4 Ajax other requests to /ajax_handler which leads to my next question: how to handle multiple ajax requests to the same url?
Thanks in advance!
Are you parsing the request? req.body is initially empty/undefined. You will need to pass it to a middleware that parses the data into req.body. Body-parser is a nodejs module that can achieve this. Here's how to a POST request with JSON data being sent.
const bodyParser = require('body-parser')
app.use(bodyParser.json());
app.post("/ajax_handler", function(req, res) {
res.send({ //works as it should....
user : req.session.user,
data_objekt: req.session.data
});
if(req.body) {
console.log(req.body);
}
});

How to send info from client back to the same connection

I need help with socket.io. I want the client to send info that the server and then the server sends it back to the same client, not all of them. Here is how the code is set up:
Client
var socket = io.connect();
socket.on("receive", function(data){
console.log(data);
});
socket.emit("send", "hello");
Server
socket.on("send", function(data){
io.sockets.emit("receive", data);
});
This way makes "hello" get logged to all the connections. Is there a way so that only the one that sent it receives?
Change to:
socket.on("send", function(data){
socket.emit("receive", data);
});
io.sockets.emit() is an explict directive to send to all connected sockets whereas socket.emit() only sends to the one socket.

How can I fetch data from socket.io client for node POST request

I'm working on a node.js app that tries to fetch data from a socket.io client to populate a response to a POST request from another client. Something like...
POST http request from client A
server requests data over socket.io from client B
client B returns data over socket to server
server responds to client A
Client A, making the initial POST request, is a web service (Plivo/plivo-node) so I can't change how it hits the server.
The node code which is called on the POST request looks like this...
app.handlePlivoRequest = function (req, res) {
// create Plivo response object
var r = plivo.Response();
// set listener for client response
client.socket.on('callResponse', function(msg){
// add msg data from client to the Plivo response
r.addSpeak(msg);
});
// forward request to socket client
client.socket.emit('call', req.body );
// render response as XML for Plivo
return r.toXML();
}
The problem I have is that handlePlivoRequest returns without waiting for the response from the client.
Can anyone help with how I'd re-factor this to wait for the socket to respond?
Thanks!
You need to end the http request inside the socket response callback:
app.handlePlivoRequest = function (req, res) {
// create Plivo response object
var r = plivo.Response();
// set listener for client response
client.socket.on('callResponse', function(msg){
// add msg data from client to the Plivo response
r.addSpeak(msg);
// render response as XML for Plivo
res.set({ 'Content-Type' : 'text/xml'});
res.end(r.toXML());
});
// forward request to socket client and wait for a response..
client.socket.emit('call', req.body );
}

Categories

Resources