var express = require("express");
var app = express();
var bodyParser = require('body-parser');
var port = 3000;
const fs = require('fs');
// we are connecting to the mangodb using mangoose
var mongoose = require("mongoose");
// Now we are using bodyParser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.connect("mongodb://localhost:27017/YourDB", { useNewUrlParser: true })
// now we are creating the schema to the database
var nameSchema = new mongoose.Schema({
firstName: String,
lastNameName: String
});
// Now we have to create a model
var User = mongoose.model("User", nameSchema);
app.use("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
// Now we are posting the data
app.post("/addname", (req, res) => {
console.log("nnnnnn")
console.log(req.body.firstName)
var myData = new User(req.body);
myData.save()
console.log(myData);
fs.writeFile(__dirname +"/data.json",myData, function(err){
if(err) {
return console.log(err);
}
console.log("The file is saved ");
})
console.log(myData)
})
// Now we are getting the data
app.listen(port, () => {
console.log("Server listening on port " + port);
});
1)I am using express app.post to post the data into database and store the data into the write file to check
2) app.post is not working it tried console.log to check but it is not going inside the function
3) I am not getting output as well as any error plese help me
there is no error handling and response handling in this code.
it will be readable if we write post method with async/await :
app.post("/addname", async (req, res) => {
console.log("nnnnnn")
console.log(req.body.firstName)
var myData = new User(req.body);
await myData.save()
console.log(myData);
fs.writeFileSync(__dirname +"/data.json", myData)
console.log(myData)
})
you will add next() to app.use
var User = mongoose.model("User", nameSchema);
app.use("/", (req, res,next) => {
res.sendFile(__dirname + "/index.html");
next()
});
// Now we are posting the data
app.post("/addname", (req, res) => {
console.log("nnnnnn")
console.log(req.body.firstName)
var myData = new User(req.body);
myData.save()
console.log(myData);
fs.writeFile(__dirname +"/data.json",myData, function(err){
if(err) {
return console.log(err);
}
console.log("The file is saved ");
})
console.log(myData)
})
// Now we are getting the data
app.listen(port, () => {
console.log("Server listening on port " + port);
});
That's because every request is going to this app.use code block. app.use("/", (req, res) => { ... });
Just Put it below the app.post("/addname", (req, res) => { ... });
app.use is used to mount middlewares into the request-response chain. So, every request that comes matches the /(which is essentially every request) goes inside that middleware. So, use your routes first then use the middleware at the end.
EDIT:
Let me give you a mcve which I tested locally:
const express = require('express');
const fakeData = function(){
return {
s: "fakeData"
}
}
const app = express();
const port = 8181
const path = require('path')
app.get("/a", (req, res) => {
return res.json({d:'yay'});
});
app.use('/',(req,res)=>{
return res.json(fakeData());
})
app.listen(port, () => {
console.log(`Server started on PORT ${port}`);
});
Because every request goes through a mounted middleware, so when you GET/POST/ANYTHING to localhost:8181/<abosulutely_any_path> it will go through the app.use because it treats that function as middleware and will return { s: "fakeData" }.
But when you make a GET call http://localhost:8181/a it will go to the app.get route BECAUSE WE DECLARED IT FIRST and return { d : "yay" }
Related
i am trying to return the value of my search after using the node-spotify-api package to search for an artist.when i console.log the spotify.search ..... without the function search function wrapped around it i get the values on my terminal..what i want is when a user sends a request to the userrouter routes i want is to display the result to the user..i using postman for testing ..
This is the controller
const Spotify = require('node-spotify-api');
const spotify = new Spotify({
id: process.env.ID,
secret: process.env.SECRET,
});
const search = async (req, res) => {
const { name } = req.body;
spotify.search({ type: 'artist', query: name }).then((response) => {
res.status(200).send(response.artists);
}).catch((err) => {
res.status(400).send(err);
});
};
module.exports = {
search,
};
**This is the route**
const express = require('express');
const searchrouter = express.Router();
const { search } = require('./spotify');
searchrouter.route('/').get(search);
module.exports = searchrouter;
**This is my server.js file**
const express = require('express');
require('express-async-errors');
const app = express();
require('dotenv').config();
// built-in path module
const path = require('path');
// port to be used
const PORT = process.env.PORT || 5000;
// setup public to serve staticfiles
app.use(express.static('public'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.set('port', PORT);
const searchrouter = require('./route');
app.use('/search', searchrouter);
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'index.html'));
});
app.listen(PORT, (req, res) => {
console.log(`Server is listening on port ${PORT}`);
});
[that is my project structure][1]
Well Your Code has a bug
Which is
searchrouter.route('/').get(search);
You are using a get request and still looking for a req.body
const { name } = req.body;
name is going to equal to = undefined
and when this runs
spotify.search({ type: 'artist', query: name })
it's going to return an empty object or an error
req.body is empty for a form GET request
So Your fix is
change your get request to a post
searchrouter.route('/').post(search);
I'm a new learner express.js I want to test simple post and get operations with tdd mechanism. I created the test, route, index and db files but when I try to test POST method it gives me this error.
This is my routes/task.js
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
This is my test/task.js
let chai = require("chai");
const chaiHttp = require("chai-http");
const { send } = require("process");
let server = require("../index");
//Assertion Style
chai.should();
chai.use(chaiHttp);
describe('Tasks API', () => {
/**
* Test the POST Route
*/
describe('POST /api/task', () => {
it("It should POST a new task", () => {
const task = {task: "Wake Up"};
chai.request(server)
.post("/api/task")
.send(task)
.end((err, response) => {
response.should.have.status(201);
response.body.should.be.a('string');
response.body.should.have.property('id');
response.body.should.have.property('task');
response.body.should.have.property('task').eq("Wake Up");
response.body.length.should.be.eq(1);
done();
});
});
});
});
This is my db.js
var sqlite3 = require('sqlite3').verbose()
const DBSOURCE = "db.sqlite"
let db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message)
throw err
}else{
console.log('Connected to the SQLite database.')
db.run(`CREATE TABLE IF NOT EXISTS todo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task text
)`,
(err) => {
if (err) {
// Table already created
console.log(err);
}
});
}
});
module.exports = db
And this is my index.js
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
The thing that I try to do is building a test case to test the post method. I think I couldn't built the correct relations the files.
Currently, just by doing a POST request to /api/task, the error will appear. That is because of these lines in index.js:
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
The req parameter is circular, hence cannot be JSON-stringified.
Solution
In routes/task.js export the router:
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
// By adding this line you can export the router
module.exports = router
In index.js, include the routes/task.js file and pass it to app.use(...), also remove the now-obsolete /api/task route:
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const taskRoutes = require("./routes/task")
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.use(taskRoutes)
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
This way we got rid of the circular structure stringifying and the tests should now pass.
I'm taking a course on NodeJS, there were a few assignments related to routing, everything works fine except this part which seems a little odd: For some reason, I cannot read the parameter ID being passed to the mounted router.
dish.js
const express = require('express');
const bodyParser = require('body-parser');
const dishRouter = express.Router();
dishRouter.use(bodyParser.json());
dishRouter.route('/')
.all((req,res,next) => {
res.statusCode = 200;
res.setHeader('Content-Type','text/plain');
next();
})
.get((req,res) => {
console.info('Info: ',req);
res.end(`Sending details of the dish back to you: ${req.params.dishId}`);
})
.post((req,res) => {
res.statusCode = 403;
res.end(`Operation not supported: ${req.params.dishId}`);
})
.put((req,res) => {
res.write(`Updating the dish...: ${req.params.dishId} \n` );
res.end(`Will update this dish: ${req.body.name} with details: ${req.body.description}`);
})
.delete((req,res) => {
res.end(`Deleting this dish: ${req.params.dishId}`);
});
exports.dish = dishRouter;
dishes.js
const express = require('express');
const bodyParser = require('body-parser');
const dishesRouter = express.Router();
dishesRouter.use(bodyParser.json());
dishesRouter.route('/')
.all((req,res,next) => {
res.statusCode = 200;
res.setHeader('Content-Type','text/plain');
next();
})
.get((req,res) => {
res.end('Sending all dishes back to you');
})
.post((req,res) => {
res.end(`Will add the dish: ${req.body.name} with details: ${req.body.description}`);
})
.put((req,res) => {
res.statusCode = 403;
res.end(`Operation not supported.`);
})
.delete((req,res) => {
res.end(`Deleting all dishes.....`);
});
exports.dishes = dishesRouter;
index.js
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const http = require('http');
const dishRouter = require('./routes/dish');
const dishesRouter = require('./routes/dishes');
const hostname = 'localhost';
const port = 3000;
const app = express();
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use('/dishes',dishesRouter.dishes);
app.use('/dishes/:dishId',dishRouter.dish);
app.use(express.static(__dirname+'/public'));
app.use((req,res,next) => {
res.statusCode = 200;
res.setHeader('Content-Type','text/html');
res.end('<html><body><h1>This is an Express Server</h1></body></html>');
});
const server = http.createServer(app);
server.listen(port,hostname,(req,res) => {
console.info(`Server running on port: ${port}, at: ${hostname}`);
})
This GET localhost:3000/dishes/123 is calling the right route, but the parameter dishId comes back as "undefined". Again, just learning nodeJS, seems like my receiver/mounted route should receive those parameters just fine, the body can be read properly, but not the params. ... thanks.
Yeah the params don't flow between routers. You're on a new router, hence new route params object.
You can check out the code for this:
https://github.com/expressjs/express/blob/master/lib/router/index.js#L43
Check out line 43 and line 53 where route.params is set to an empty object.
Some examples:
index.js
app.use('/dishes/:dishId',(req, res) => {
console.log('now I get my dishId', req.params.dishId)
});
dish.js (version 1)
dishRouter.route('/')
.get((req, res) => {
console.log('now i get nothing', req.params)
})
dish.js (version 2)
dishRouter.route('/:anotherId')
.get((req, res) => {
console.log('now we get another parameter', req.params.anotherId)
})
// the path would be /dish/123/456
I'm not sure if there is a offical-expressjs-way to pass the params object between routers.
One solution would be to create a custom handler
index.js
app.use('/dishes/:dishId', handler)
handler.js
function handler (req, res, next) {
if (req.method === 'GET') {
console.log('now we get it', req.params)
}
}
module.exports = handler
Anoter way would be to add the dishId to the request object before calling the router:
index.js
app.use('/dishes/:dishId', (req, res, next) => {
req.dishId = req.params.dishId
router(req, res, next)
})
dish.js
const express = require('express')
const router = express.Router()
router.route('/')
.get((req, res) => {
console.log('nothing here', req.params)
console.log('dishId', req.dishId)
})
module.exports = router
Third way would be to send the params as options to a router function
index.js
app.use('/dishes/:dishId', (req, res, next) => {
router(req.params)(req, res, next)
})
dish.js
function createRouter (options) {
const router = express.Router()
router.route('/')
.get((req, res) => {
console.log('nothing here', req.params)
console.log('but alot here', options)
})
return router
}
module.exports = createRouter
If you want you could also just put the :dishId on the router as an optional parameter
index.js
app.use('/dishes', dishesRouter)
dishes.js
const express = require('express')
const router = express.Router()
router.route('/:dishId?')
.get((req, res) => {
if (req.params.dishId) {
res.end(`Sending details of the dish back to you: ${req.params.dishId}`)
} else {
res.end('Sending all dishes back to you');
}
})
module.exports = router
I'm attempting to access a route directly from a request, even though another subfolder works the other does not. Repeatedly throwing 404 errors. /api/getPostList works but /post/ or /post/:title doesn't work.
I've restructured the code, attempted to change it from a get request to a post request, added /post/:title to access an individual post or without a / to access the main list.
Server.js contains
app.use('/', Routes);
routes/index.js contains
const router = require('express').Router();
const posts = require('./posts');
const api = require('./api');
router.use('/post', posts);
router.use('/api', api);
module.exports = router;
routes/api/index.js contains
Api.get('/getPostList', (req, res) => {
PostModel.find(function (err, post) {
if (err) return console.log('error: ' + err);
return res.json({ postList: post});
});
console.log("Attempted to get post list on /getPost/ route: " + ++postRouteCnt);
});
Api.get('/getPost/:title', getPost);
module.exports = Api;
routes/post/index.js contains
const Posts = require('express').Router();
const post = require('./post');
const PostModel = require('../../../server/models.js');
let postRouteCnt = 0;
Posts.get('/', (req, res) => {
PostModel.find(function (err, post) {
if (err) return console.log('error: ' + err);
return res.json({ postList: post});
});
console.log("Attempted to get post list on /post/ route: " + ++postRouteCnt);
});
Posts.get('/:title', post);
module.exports = Posts;
When calling /post/ I get a 404 Cannot GET /post/ when I should receive the json response.
EDIT:
Folder structure
Server/
routes/
api/
index.js
getPost.js (for individual post)
posts/
index.js
post.js (for individual post)
server.js
Base on your structure folder, I try to write code with simple code
App.js :
const express = require('express')
const app = express()
const port = 3000
const Routes = require('./routes/posts/index.js');
app.use('/', Routes);
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
.routes/ posts/ index.js :
const express = require('express');
const router = express.Router();
const postController = require('./post');
// GET /
router.get('/posts', postController.getPosts);
module.exports = router;
.routes/ posts/ post.js :
exports.getPosts = (req,res) => {
res.send('test');
}
Try input http://localhost:3000/posts and its work
You can write any logic in .routes/ posts/ post.js :
try changing it like this
Posts.get('/', (req, res) => {
PostModel.find(function (err, post) {
if (err) throw err;
res.send({ postList: post});
});
console.log("Attempted to get post list on /post/ route: " + ++postRouteCnt);
});
now try this url
/post/
I am using express backend with a react frontend everything is working fine but occasionally i get error
Cant set header after they are sent
and server gets down.i searched few ways this error might happen but in my code i could not find such cases.i tried to be simple as possible in the code.can anyone please point me what might be the issue?
Server.js file
// call the packages we need
const addItem = require('./controllers/addItem');
const addCategory = require('./controllers/addCategory');
const addSubCategory = require('./controllers/addSubCategory');
const getSubCategory = require('./controllers/getSubCategoryByCategory');
const getCategory = require('./controllers/getAllCategory');
const getAllItems = require('./controllers/getAllItems');
const cors = require('cors');
const express = require('express');
// call express
const app = express(); // define our app using express
const bodyParser = require('body-parser');
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
const port = process.env.PORT || 8080; // set our port
// ROUTES FOR OUR API
// =============================================================================
const addItemRoute = express.Router(); // get an instance of the express Router
const getCategoryRoute = express.Router();
const addCategoryRoute = express.Router();
const addSubCategoryRoute = express.Router();
const getSubCategoryRoute = express.Router();
const getAllItemsRoute = express.Router();
getCategoryRoute.get('/get_category', (req, res) => {
getCategory(res);
});
addCategoryRoute.post('/add_category', (req, res) => {
addCategory(req.body.name, res);
});
getSubCategoryRoute.get('/get_subcategory/:catId', (req, res) => {
getSubCategory(req.params.catId, res);
});
addSubCategoryRoute.post('/add_subcategory', (req, res) => {
addSubCategory(req.body.name, req.body.cat_id, res);
});
// code, name, quantity, length, description and subcategory id should be passed as parameters
addItemRoute.post('/add_item', (req, res) => {
addItem(req.body.item, res);
});
getAllItemsRoute.get('/get_items', (req, res) => {
getAllItems(res);
});
// more routes for our API will happen here
// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', addItemRoute);
app.use('/api', getCategoryRoute);
app.use('/api', addCategoryRoute);
app.use('/api', addSubCategoryRoute);
app.use('/api', getSubCategoryRoute);
app.use('/api', getAllItemsRoute);
// START THE SERVER
// =============================================================================
app.listen(port);
console.log(`Server started on port ${port}`);
getAllCategories() function
Object.defineProperty(exports, '__esModule', {
value: true,
});
const pool = require('./connection');
module.exports = function (res) {
pool.getConnection((err, connection) => {
if (err) {
connection.release();
return res.json({ code: 100, status: 'Error in connection database' });
}
console.log(`connected as id ${connection.threadId}`);
connection.query('select * from category;', (err, rows) => {
connection.release();
if (!err) {
return res.json(rows);
}
});
connection.on('error', err => res.json({ code: 100, status: 'Error in connection database' }));
});
};
If you get an error in connection.query() you send a response with res.json(). This error is caught in connection.on('error') where you send another response. You can't send two responses to the same request. It seems that in this case, you don't really need connection.on() at all or if you have it to catch other errors, don't send a response on connection.query()'s error.