Exporting Objects in NodeJS for API - javascript

I'm trying to write a RESTful API in NodeJS that connects to a MySQL database. I have multiple files that handle routes:
I'm using the "mysql" package from www.npmjs.com. In app.js I create a connection object for the database but then want to use that object in both books.js and entries.js. I need to use the connection object to send queries to the database and I plan to do that in the routes files (books.js, etc.). What is the proper way to export and import that object? I'm new to NodeJS. Also, app.js is already exporting "app".
app.js:
const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const bookRoutes = require('./api/routes/books');
const entryRoutes = require('./api/routes/entries');
const connection = mysql.createConnection({
host: 'localhost',
user: 'rlreader',
password: process.env.MYSQL_DB_PW,
database: 'books'
});
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'GET');
return res.status(200).json({});
}
next();
});
// Routes which should handle requests
app.use('/books', bookRoutes);
app.use('/entries', entryRoutes);
app.use((req, res, next) => { //request, response, next
const error = new Error('Not found');
error.status = 404;
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
module.exports = app;
books.js:
const express = require('express');
const router = express.Router();
const axios = require('axios');
router.get('/', (req, res, next) => {
axios.get('/').then(docs => {
res.status(200).json({
"hello": "hi"
})
}).catch(err => {
res.status(500).json({
error: err
});
})
});
module.exports = router;

GrafiCode had the answer to this one. I made a separate file called db.js
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'rlreader',
password: process.env.MYSQL_DB_PW,
database: 'books'
});
module.exports = connection;
Then, in books.js I added:
const con = require('../../db');
Then I was able to use the .query() from the mysql component in multiple files.

Related

Cannot POST to Express router (404 error)

I cannot fetch POST requests to my Express router. I have many GET requests which work fine, but this is my first POST request and it is not working.
My frontend code looks like this:
export async function postHamster(name, age) {
try {
await fetch('/hamsters/api/new-hamster',
{
method: 'POST',
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: name,
age: age
})
})
console.log("postHamster has run") //LOGGED
}
catch (e) {
console.error(e)
}
}
The response will always be:
fetchData.js:38 POST http://localhost:3000/hamsters/api/new-hamster 404 (Not Found)
I have triple-checked the path and it cannot be in error. The backend path is "router.get('api/new-hamster', async (req, res)..." in the file 'hamsters.js'.
I have also put the backend function at the very top of its file, to ensure that it is not overrruled by any other function in the file.
This is my server.js:
// THIS FIRST FUNCTION I JUST COPIED FROM A SOLUTION BUT IT DOES NOT SEEM TO HELP
// routes/index.js
module.exports = (express) => {
// Create express Router
var router = express.Router();
// add routes
server.route('/hamsters/api/new-hamster')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
res.send('You sent: sdadad to Express');
});
return router;
}
const express = require('express');
const server = express();
const serverPort = process.env.PORT || 1234;
server.use(express.static(__dirname + '/../build'))
let data = require('./data.json')
const { Router } = require('express');
let router = new Router();
//USE BODY-PARSER BEFORE REGISTERING ROUTES!
const bodyParser = require('body-parser')
server.use(bodyParser.urlencoded({ extended: true }));
server.use(bodyParser.json())
server.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// ROUTES
const hamstersRoute = require('./routes/hamsters');
const chartsRoute = require('./routes/charts')
const gamesRoute = require('./routes/games')
const statsRoute = require('./routes/stats')
const imagesRoute = require('./routes/images')
const uploadRoute = require('./routes/upload')
server.use('/assets', express.static("assets"))
server.use(express.static('public'))
server.use('/hamsters', hamstersRoute)
server.use('/charts', chartsRoute)
server.use('/games', gamesRoute)
server.use('/stats', statsRoute)
server.use('/images', imagesRoute)
server.use('/upload', uploadRoute)
server.listen(serverPort, () => {
console.log(`Server is up n running on port ${serverPort}!`)
})
module.exports = data;
I have looked at these threads:
Cannot GET/POST with express Router()
Express.js routers post request returns 404
Express: router cannot read POST request
Have you checked the url you're trying to post to in the network tab in the console? I think you need to add a / before api in the backend route: router.get('/api/new-hamster', async (req, res)...".
You have this:
server.use(bodyParser.urlencoded({ extended: true }));
Instead of this:
server.use(bodyParser.urlencoded({ extended: false }));

Socket.io GET/POST 404

I was searching for a similiar issue, but I still can't fix this problem. I'm working on a chat app in ReactJs, Node/Express, Mongoose and Socket.io. Everything works, db is working, server is running, so now I want to add socket. I'm trying to connect client side with server, but I get error (about every 2/3sec) POST/GET http://localhost:3000/socket.io/?EIO=3&transport=polling&t=N5PeKkf 404 (Not Found).
React:
const host = 'http:localhost:5000/api/rooms'
const [endpoint, setEndpoint] = useState('')
const {width,mobileWidth} = props;
useEffect(()=>{
setEndpoint(`${host}${props.location.pathname}`);
socket = io(endpoint);
const roomId = props.location.pathname.slice(1,props.location.pathname.length);
socket.emit('join', {roomId})
},[endpoint])
Node:
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const socketIo = require("socket.io");
const http = require("http");
const HttpError = require('./models/http-error');
const roomsRouter = require('./routes/rooms-routes');
const usersRouter = require('./routes/users-routes');
const app = express();
mongoose
.connect(
`mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}#cluster0-lnoai.mongodb.net/${process.env.DB_NAME}?retryWrites=true&w=majority`
)
.then(() => {
app.listen(process.env.PORT || 5000);
})
.catch(err => {
console.log(err);
});
const server = http.createServer(app);
const io = socketIo(server);
app.use(bodyParser.json());
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE');
next();
});
io.on('connection',(socket)=>{
console.log('connected');
})
app.use('/api/rooms', roomsRouter);
app.use('/api/users', usersRouter);
app.use((req, res, next) => {
throw new HttpError('Route not found.', 404);
});
app.use((error, req, res, next) => {
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500).json({
message: error.message || 'An uknown error occurres!',
errorCode: error.code || 500
});
});

Trying to send data from Reactjs Component to express app using axios

I'm working on a project that uses ReactJS typescript for the front-end, express for the back-end, and MongoDB for the database.
The main issue I am having is that I want to somehow send data from my React component to the express app so that it can query and add things to the database.
Currently, I have the express server running on http://localhost:9000, and the React app on http://localhost:3000, and I can connect them using routes.
My express app looks like the following:
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var cors = require('cors');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var testAPIRouter = require('./routes/testAPI');
var testAddUser = require('./routes/addUser');
const MongoClient = require('mongodb').MongoClient;
const mongoose = require('mongoose');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use("/testAPI", testAPIRouter);
app.use("/addUser", testAddUser);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
const dbRoute = 'mongodb+srv://Adminname:fjfeinjd#pawornaw-b4vzg.gcp.mongodb.net/test?retryWrites=true&w=majority';
mongoose.connect(dbRoute,
{useNewUrlParser: true})
.then(() => console.log("Connected to MongoDB"))
.catch(err => console.error("Could not connected to Mongo"));
module.exports = app;
and my React Component is this, minus import statements. The render function only contains a button that has an onlclick that executes doThing()
constructor(props: any) {
super(props);
this.state = {
showHomePage: true,
showAnimalUploadSearch: false,
showProfile: false,
showAnimal: true,
apiResponse: "",
fName: "bob"
};
this.changeView = this.changeView.bind(this);
// this.callAPI = this.callAPI.bind(this);
// this.componentWillMount = this.componentWillMount.bind(this);
this.doThing = this.doThing.bind(this);
}
callAPI() {
fetch("http://localhost:9000/testAPI")
.then(res => res.text())
.then(res => this.setState({apiResponse: res}))
.catch(err => err);
}
componentWillMount(): void {
this.callAPI();
}
changeView() {
this.setState({showHomePage: !this.state.showHomePage});
this.setState({showAnimalUploadSearch: !this.state.showAnimalUploadSearch});
this.setState({showAnimal: true});
this.setState({showProfile: false});
}
doThing() {
Axios.post('http://localhost:9000/testAPI', ({firstName: this.state.fName}))
.then(res => console.log(res));
}
and finally, testAPI.js looks like this
const router = express.Router();
const axios = require('axios');
router.get('/', function(req, res, next) {
//res.send('API is working properly');
axios.get('http://localhost:3000')
.then(res => console.log("got it"))
.catch(err => err);
});
module.exports = router;
I want to be able to access and use the data that is sent from my react component so that I can query my database with user input in the future. The API does connect with my React code, and when the testAPI function only contains these lines:
const router = express.Router();
const axios = require('axios');
router.get('/', function(req, res, next) {
res.send('API is working properly');
});
module.exports = router;
the message can be displayed on my react app in the browser via the state.
If anyone could help me see what I am doing wrong, or maybe give me a clue as to what other options I can try, please let me know.
Thank you.
When you send post request from client side, it will be in body property of req object
const router = express.Router();
// you shoud listen post request
router.post('/', function(req, res) {
const { body } = req;
// do somethin with data which you recieved in body, save to database for example
// and send response to the client
res.json({ message: 'your data was saved'});
});
module.exports = router;
to send data to client use:
router.get('/', function(req, res) {
res.json({ data: 'Some data'}); // or res.send('some text') to send plain text
});

How to catch POST request on back-end?

<!doctype html>
<head>
</head>
<body>
<script>
const Http = new XMLHttpRequest();
const url='http://localhost:4550/users';
Http.open("POST", url);
Http.send("hey");
Http.onreadystatechange = (e) => {
console.log(Http.responseText)
}
</script>
</body>
</html>
//user.js
var express = require('express');
var router = express.Router();
var array = [];
/* GET users listing. */
router.get('/', (req, res, next) => {
res.send('respond with a resource1');
});
router.post('/', (req, res, next) => {
res.send('respond with a resource2');
});
module.exports = router;
//app.js
const express = require('express')
const app = express();
app.get('/',(req,res)=> {
console.log('lior');
res.send('api running 2')});
app.use('/users',require('./routes/users'))
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
const PORT = process.env.PORT || 4550;
app.listen(PORT,()=> console.log('server started on port ${PORT}'));
I am new with connecting client and server side, and it might be why I couldn't find an answer for my question. Is a simple question.
As you can see I want to send "hey" from the client to the server(user.js). However I don't know how does I catch the response on the server side.
I know that a "hey" or neither the code make much sense, but is just an example to make things simple, I just wondering how does the server side could catch and handle the data.
Thanks in advance!
When you post data, specify how you are encoding it. It's generally best to use a standard encoding method rather than POSTing plain text. (Also don't start variable names with capital letters unless they are constructor functions)
const http = new XMLHttpRequest();
const url = 'http://localhost:4550/users';
const data = JSON.stringify({ value: "hey" });
http.open("POST", url);
http.setRequestHeader("Content-Type", "application/json");
http.send(data);
http.onreadystatechange = (e) => {
console.log(http.responseText)
}
Then in your server side code, use a body parser to decode the data.
Since you are using an absolute URL in the request, it seems likely that you are making a cross-origin request so you also need to grant permission using CORS.
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const app = express()
const port = 4550
const jsonParser = bodyParser.json()
const corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200
};
const corsMiddleware = cors(corsOptions)
app.get('/', (req, res) => res.send('Hello World!'))
app.get('/users', (req, res, next) => {
res.send('respond with a resource1');
});
app.options("/users", corsMiddleware)
app.post('/users', corsMiddleware, jsonParser, (req, res, next) => {
// data is in `req.body` (which will have a `value` property because the object on the client does)
res.send('respond with a resource2');
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
(The above is untested and may have minor errors in it)
Please send serialized data as below:
const http = new XMLHttpRequest();
const url = 'http://localhost:4550/users';
const data = JSON.stringify("hey");
http.open("POST", url);
http.setRequestHeader("Content-Type", "application/json");
http.send(data);
You need to use bodyParser package
npm install body-parser
const bodyParser = require("body-parser");
and before setting up routes use it as below :
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
Don't forget to allow the headers declaration as below :
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST"
);
next();
});
and now you can read your data as below
router.post('/users', (req, res, next) => {
console.log(req.body);
});

how to trigger Express get route using websocket?

I would update my client side view every insert in the database.
In y angular application I have a function that adds text to database :
ajoutText(newtext: String) {
this.dataService.sendtext(newtext)
.subscribe(res => this.socket.emit('save-message', { data: "hello" }));
}
after posting message to database I emit a socket. the idea is to trigger a get route to update my observable in Angular side with the new data, and create a data stream.
Here's my server configuration :
server.js:
var http = require("http");
var admin = require('firebase-admin');
var firebase = require("firebase");
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var port = process.env.app_port || 8080; // set our port
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var server = app.listen(port);
var io = require("socket.io")(server);
var routerProj = require("./routes/routes");
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,*");
next();
});
var config = {
... configuration...
};
firebase.initializeApp(config);
var serviceAccount = require("./ServiceAcountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://datatable-18f93.firebaseio.com"
});
app.use(function (req, res, next) {
req.io = io; // pass socket to route
next();
});
app.use("/v1", routerProj);
and routes.js file :
var express = require("express"); // call express
var router = express.Router(); // get an instance of the express Router
var admin = require("firebase-admin");
//module.exports = function (req) {
//router.route("/")
router.use(function (req, res, next) {
// Test
console.log(req.io.sockets)
next();
});
router
.route("/")
.get(function (req, res, err) {
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.once("value", function (snapshot) {
var list = [];
snapshot.forEach(function (elem) {
list.push(elem.val());
})
list = JSON.stringify(list);
res.send(list);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
res.status(500).send(errorObject.code);
});
});
router
.route("/")
.post(function (req, res, err) {
console.log(req.body);
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.push(
{
"text": req.body.text
}
);
});
//return router;
//}
module.exports = router;
How can I run post route on save-message emit from client side ?

Categories