Sorry for this noob question, student here and still learning
I'm trying to pass the request body of a POST request from server to client. I have an Arduino sensor making post requests with sensor data to an express server. The sensor data is inside the POST request body, and I push the data to an array called 'dataArray'. This part seems to be working.
My problem is that I'm now stuck on how to pass this data from the express server to a Vue component on the client side. Should I make a new route? I'm not asking anyone to write any code for me, I'm just hoping someone could point me in the right direction or suggest something, because I'm at a loss on exactly how I should go about doing this. Thank you.
server.js
var express = require("express")
var cors = require("cors")
var bodyParser = require("body-parser")
var app = express()
var mongoose = require("mongoose")
var Users = require("./routes/Users")
var port = process.env.PORT || 5000
var dataArray = []
app.use(bodyParser.json())
app.use(cors())
app.use(bodyParser.urlencoded({ extended: true }))
const mongoURI = 'my_connection_string'
mongoose.connect(mongoURI, { useNewUrlParser: true })
.then(() => console.log("MongoDB Connected"))
.catch(err => console.log(err))
app.use("/users", Users)
app.route("/api/:apikey1")
app.post("/api/:apikey1", function(request, response) {
var myData = request.body;
console.log(myData)
dataArray.push(myData)
response.send("Array Filled")
});
app.listen(port, function () {
console.log("Server is running on port: " + port)
})
If you want to keep it simple use the socket.io library.
It is available for both client and server, you can use in your Vue client too.
Also, you won't need any extra route, just in your app.post("/api/:apikey1") route, use the emit method on socket.io library to broadcast the data as it is received from the sensors
Any data flow from the server to client must be first initiated on the client side, either by polling, using WebSockets or Server-sent events.
Related
First a quick preface I think may be helpful: I am new to splitting my client and server into separate web apps. My previous apps have all had my server.js at the root level in my directory and the client (typically a create-react-app) in a /client folder.
What I wanted to do: Host a single express.js server on the web which multiple other web applications could make requests to.
I did the first part using an express server and aws elastic beanstalk.
server.js
require('dotenv').config()
const express = require('express');
const app = express();
const cors = require('cors');
const PORT = process.env.PORT || 5000;
const Mongoose = require('mongoose');
const { Sequelize } = require("sequelize");
//ROUTES
const APIUser = require('./routes/api/mongo/api-user');
more routes...
//INITIATE DATA MAPPING CONNECTIONS START
Mongoose.connect(
process.env.MONGO_URI,
{ useNewUrlParser: true, useUnifiedTopology: true },
console.log("connected to MongoDB")
);
const Postgres = new Sequelize(process.env.PG_CONN_STRING);
try {
Postgres.authenticate()
.then(console.log("connected to Postgres"));
} catch {
console.log("Postgres connection failed")
}
//INITIATE DATA MAPPING CONNECTIONS END
//middleware
app.use(cors())
more middleware...
//home route
app.get('/api', (req, res) => {
console.log('RECEIVED REQ to [production]/api/')
res.status(200).send('models api home').end();
})
//all other routes
app.use('/api/user', APIUser);
more route definitions...
//launch
app.listen(PORT, () => console.log(`listening on port ${PORT}`));
The log file for successful boot up on aws: https://imgur.com/vLgdaxK
At first glance it seemed to work as my postman requests were working. Status 200 with appropriate response: https://imgur.com/VH4eHzH
Next I tested this from one of my actual clients in localhost. Here is one of my react client's api util files where axios calls are made to the backend:
import { PROXY_URL } from '../../config';
import { axiosInstance } from '../util';
const axiosProxy = axios.create({baseURL: PROXY_URL}); //this was the most reliable way I found to proxy requests to the server
export const setAuthToken = () => {
const route = "/api/authorization/new-token";
console.log("SENDING REQ TO: " + PROXY_URL + route)
return axiosProxy.post(route)
}
export const authorize = clientsecret => {
const route = "/api/authorization/authorize-survey-analytics-client";
console.log("SENDING REQ TO: " + PROXY_URL + route)
return axiosProxy.post(route, { clientsecret })
}
Once again it worked... or rather I eventually got it to work: https://imgur.com/c2rPuoc
So I figured all was well now but when I tried using the live version of the client the request failed somewhere.
in summary the live api works when requests are made from postman or localhost but doesn't respond when requests are made from a live client https://imgur.com/kOk2RWf
I have confirmed that the requests made from the live client do not make it to the live server (by making requests from a live client and then checking the aws live server logs).
I am not receiving any Cors or Cross-Origin-Access errors and the requests from the live client to the live server don't throw any loud errors, I just eventually get a net::ERR_CONNECTION_TIMED_OUT. Any ideas where I can look for issues or is there more code I could share?
Thank you!
Add a console.log(PROXY_URL) in your client application and check your browser console if that's logged correctly.
If it works on your local client build, and through POSTMAN, then your backend api is probably good. I highly suspect that your env variables are not being set. If PROXY_URL is an emplty string, your axios requests will be routed back to the origin of your client. But I assume they have different origins since you mention that they're separate apps.
Remember environment variables need to prefixed with REACT_APP_ and in a production build they have to be available at build time (wherever you perform npm run build)
I'm must say I'm very new to back end development,
I'm currently working on an exercise project of making a fake money poker website. I use Node.js socket.io/express-session/passport
At first, I mainly used express with a HTTP server listening on one port. Averagely Like this:
const express = require("express")
const app = express()
app.get('/home',connectEnsureLogin.ensureLoggedIn("/loginPage"),function(req, res) {
//console.log(req.user.username+": sessionId: "+req.sessionID);
return res.sendFile( __dirname+"/website/index.html");
}
);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log("Poker site Server started on ${PORT})")
The website wasn't working very fast. When a client joined a poker table they needed to ask the server every second for new updates on the state of the game so that was a lot of HTTP requests coming into my server. So I decided without much theoretical certitude that it seemed like a good idea: To have the server use socket.io sockets to hand info for clients that are in poker tables, but when they are not in poker tables and are just browsing the site I use a HTTP server to handle their request. Code wise I feel I haven't really managed to do this correctly. My code with Express, express-session, and passport combined makes sure only to hand information to users authenticated. But since The socket.io servers seem totally separate from all the express code, they don't share the same authentication functionality as the express code. So I need to somehow link my express and socket.io code so I can check if a client is authenticated before handing him any info via sockets. here is the system I'm currently using I didn't put all my code but I tried to summarize the essential parts:
const express = require('express');
const app = express();
//i creat the http server that is somehow linked with my express app when this server is listening
//it will call express handling methods.
const http = require('http').Server(app);
const io = require('socket.io')(http);
const path = require("path");
const passport = require("passport");
const connectEnsureLogin = require('connect-ensure-login');
const AccountInfo = require("./AccountInfo").AcccountInfo;
const expressSession = require('express-session')({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
});
//passport setup
passport.use(AccountInfo.createStrategy());
passport.serializeUser(AccountInfo.serializeUser());
passport.deserializeUser(AccountInfo.deserializeUser());
//body parser
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//Sessions
app.use(expressSession);
//!!!!here is where I connect socket.io with the sessions i found this in another forum.
// thanks to this code I can access the session that a client is using when their socket connects.
io.use(function(socket, next) {
expressSession(socket.request, socket.request.res, next);
});
//so when a clients socket connects i save his socket.id to his session.
io.on('connection',function(socket) {
console.log(`socket.io connected: ${socket.id}`);
// save socket.io socket in the session
socket.request.session.socketio = socket.id;
socket.request.session.save();
});
//once the clients socket is connected directly after the clients sends a HTTP "PUT" request
//and this code answers it.
app.post('/Table/ConnectSocketToTable',Utilities.ensureLoggedIn(),function(req, res)
{
//I retrieve the socket using the socket.id I had saved in the session.
let socket = io.sockets.sockets.get(req.session.socketio);
let player = GetPlayerFromAnyTable(req.user.username);
if(player==null)//the player can't be in two tables at once
{
//since now we are in an express callback, express made sure that the client is indeed
//authenticated with the middle-ware: "Utilities.ensureLoggedIn()" also just before I made sure
//the client is not in another table. So we are good to go we can now link the socket to the table
//and have the client receive all the info about the state of his table
socket.join("table-"+req.session.passport.table);
req.user.socket = socket;
let table = GetTable(req.session.passport.table);
table.sitPlayer(req.user);
}
else
{
//the player is already connected so we just update his socket to a new one
player.requestUnseat=false;
player.account.socket =io.sockets.sockets.get(req.session.socketio);
}
socket.on('chatMessage', function(data,time) {
socket.to("table-"+req.session.passport.table).emit("chatMessage",req.user.username,data,time);
console.log(`send chat message : ${data}`);
});
socket.on('disconnect', function() {
GetTable(req.session.passport.table).requestUnsitUsername(req.user.username);
console.log(req.user.username +" was disconnected so now requesting unsit");
});
console.log("the socket of "+req.user.username+" has being connected to table-"+req.session.passport.table);
return res.sendStatus(200);
});
So for me, the way I'm doing this seems pretty bad since "app.post('/Table/ConnectSocketToTable'...)" and "io.on('connection',...)" are two different request listening functions I feel I should probably just do everything in one.
So should I do all the checks in the "io.on('connection',...)" function and somehow manage to make sure the client is authenticated within the callback of io.on('connection',callback) ?
or should I find a way to make the socket connection happen in the initial HTTP call the client uses to join a table, which is what I initially wanted?
But really I'm kinda lost because I'm telling myself maybe I don't even need Express anymore and I should just use socket.io for everything. I seem to clearly lack the general understanding that would allow me to know what approach I should be going for so any help is welcome. I started doing this self-made exercise to get into server-side development but also if there is any other recommended exercise to start up with back-end development I'm definitely interested in hearing about it.
From random testing I found out how to authenticate to my express session from the socket code you don't actually have to do it in the callback of io.on('connection',callback) you just need to add a few more middleware functions like this:
//connecting express sessions
io.use(function(socket, next) {
expressSession(socket.request, socket.request.res, next);
});
//connecting passport
io.use(function(socket, next) {
passport.initialize()(socket.request, socket.request.res, next);
});
//connecting passport sessions
io.use(function(socket, next) {
passport.session()(socket.request, socket.request.res, next);
});
//check if client is authenticated returns error if authentication failed
io.use((socket, next) => {
console.log("started socket Connection");
if(!socket.request.isAuthenticated&&socket.request.isAuthenticated())
{
socket.request.session.socketio = socket.id;
socket.request.session.save();
console.log("table "+socket.request.session.passport.table);
console.log("user.username "+socket.request.user.username);
console.log(`is authentificated`);
next();
}
else
{
console.log(`failed socket connection`);
next(new Error("unauthorized"));
}
});```
addwordform.addEventListener('submit', (event)=>{
event.preventDefault();
const formdata=new FormData(addwordform);
const word=formdata.get('addword');
const description =formdata.get('addiscription');
const worddata={
word,description,totalcount
};
console.log(worddata);
fetch(API_URL,{
method:'POST',
headers:{
'content-Type':'application/json'
},
body:JSON.stringify(worddata),
}).then(response=>response.json()).then( data =>{
console.log(data);
});
});
this is the client side javascript
here API_URL="http://localhost:3005/word"
and server side code is
const express= require('express');
const serveStatic = require('serve-static');
const datastore= require('nedb');
const app= express();
app.listen(3005,()=>{console.log("listening on :http://localhost:3005")});
app.use(serveStatic('public',{'index':['client.html']}));
const database=new datastore('database.db');
database.loadDatabase();
app.post('/word',(req,res)=>{
const data=req.body;
database.insert(data);
res.json();
});
i am using express a node framework and vanilla javascript for client side all i want is to post the data from a form that has an id=addwordform and i am using nedb a light weight database management in node
.problem with it is the worddata that i am sending from client side is not getting in the server side "req" so i cant save it in database and ultimatly i cant "res" it back ?
If you're using express version >= 4.16. Body parser comes bundled with express.
It parses incoming requests with JSON payloads and is based on body-parser.
It is not needed to use body-parser. Here is the documentation
You just have to add this code before require your routes.
app.use(express.json());
Here is the stackoverflow original post.
Here is the express release
Here is the express commit
I’m building an API for a SPA built with Angular 2, for this app I have a stand alone API and than an Angular 2 app. So they are on built on two separate node.js servers. I’m using node.js and express along with 'express-connection' and 'mysql' modules to build a secure API to handle login and registration with JWT’s (json web tokens), along with other tasks of course. So I’ve successfully built this API so I can access data with my Angular 2 app via a URL. I can use the URL ’localhost:3000/data’ to access a json data object from my Angular 2 app running on 'localhost:3001/'. However, I also need the API to have access to this data object (an array of users) once the data becomes available. What is the best way to approach/accomplish this task? The only way I can think of now is to have a setTimeout function that waits for the app to load than uses an http get to grab the data from the url. There must be a cleaner way of accomplishing this task. Heres some code I have working, basically a simple node server running express. I'm somewhat new with building API's and Angular 2 concepts so any help is greatly appreciated.
app.js
/** Dependencies **/
var logger = require('morgan'),
cors = require('cors'),
http = require('http'),
express = require('express'),
errorhandler = require('errorhandler'),
dotenv = require('dotenv'),
bodyParser = require('body-parser');
/** Setup **/
var app = express();
dotenv.load();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use(function(err, req, res, next) {
if (err.name === 'StatusError') {
res.send(err.status, err.message);
} else {
next(err);
}
});
if (process.env.NODE_ENV === 'development') {
app.use(logger('dev'));
app.use(errorhandler())
}
/** Requires **/
require('./config/sql.js')(app);
require('./config/routes.js')(app);
/** Port **/
var port = process.env.PORT || 3001;
http.createServer(app).listen(port, function (err) {
console.log('listening in http://localhost:' + port);
});
routes.js
// routes.js
module.exports = function(app) {
var query = require('./query.js')(app);
app.get('/data', function(req, res) {
query.getData(req,res);
});
};
sql.js
var connection = require('express-myconnection');
var mysql = require('mysql');
module.exports = function(app){
app.use(
connection(mysql,{
host : 'localhost',
user : 'root',
password: ‘password’,
port : 3306,
database: ‘my_project’
}, 'request')
);
};
query.js
// DB Queries
module.exports = function(app){
return {
getData: function(req, res) {
req.getConnection(function(err,connection){
connection.query('SELECT * FROM users',function(err,rows){
// console.log("success: ", rows);
res.json(rows);
});
});
}
}
};
user.js
setTimeout(function(){
// http.get function to call to API and grab data and create variable
},500);
// this is where I need an array of users that I get from a mysql database for login and registration logic
var users = [];
I'm not sure I got why you need the Angular code to talk to a different UrL but I would write the server code to take the requests from Angular and then internally reach out to the other API to get the data required. Basically use the node server to act like a proxy to reach the other API.
jfriend00 is right in his comment, this is a question of asynchronous calls.
You are looking for the initial requests to kick off the following: Frontend Request > NodeJS API > Database Query
And the response to fulfill and return promises to create a response chain in the reverse order: Database Response > NodeJS API > Frontend Response
You are probably looking for the angular function $http.get with .then() to perform your frontend calls. But you also need an asynchronous function to request the data from within the API or a database instance, then provide it on an endpoint that the frontend can consume. For that you need a promise or callback in your server-side code as listed in jfriend00's comment.
Consider working on just your NodeJS API until you can achieve the response and requests you need, and build out your frontend with Angular later. The users.js file is a fine endpoint to start on.
I have the following code:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/rasp', function(req, res) {
res.send("received");
res.send(req.body.data);
});
app.listen(process.env.PORT || 5000);
I used POSTMAN to see if it worked and apparently the "received" text is sent back, but the data parameter is blank. What could be the problem?
Basically, the client sends a request and waits for a single response from your server. Once the client receives that response, it stops waiting for another. Furthermore, Express only allows you to send one response per request (going along with the client stuff explained above). You may be able to change this setting, but I've never dealt with it, so my answer will be limited to that knowledge.
Your server is executing res.send('received'); and the response is handled. You cannot call res.send again. You should be getting an error on your server when you attempt the second call.
You should send all data that the client needs in the first (and only) res.send().
Server responses should not be handled like logging (ex: sending 'received', 'analyzing', etc). Keep the logging separate. The client doesn't want to know all that extra info, it just wants the expected data response.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.listen(process.env.PORT || 5000);
app.post('/rasp', function(req, res) {
res.send({received:true,data:req.body});
});
can you try this one and writing the response here
I believe your post body is "data=Some Value".
If you want to send multiple chunks of data, you should use res.write, and res.end. In your code change the following lines
res.send("received");
res.send(req.body.data);
to
res.write("received");
res.end(req.body.data);