I am practicing ExpressJS with NuxtJS. I am expecting to get data from axios POST request but always came up empty on the req.body and req.params. Below are my configuration and snippets
nuxt.config.js
...
serverMiddleware: [
{ path: '/api', handler: '~/api/index.js' }
],
...
api/index.js
const express = require('express')
// Create express instance
const app = express()
// Require API routes
const staticDeploy = require('./routes/static-deploy')
// Import API Routes
app.use(staticDeploy)
// Export express app
module.exports = app
// Start standalone server if directly running
if (require.main === module) {
const port = process.env.PORT || 3001
app.listen(port, () => {
console.log(`API server listening on port ${port}`)
})
}
api/routes/static-deploy.js
const { Router } = require('express')
var CryptoJS = require('crypto-js')
const router = Router()
router.post('/static-deploy', (req, res) => {
console.log('req: ' + req.url) // Returns "req: /static-deploy/"
console.log('req: ' + req.body) // Returns "req: undefined"
console.log('req: ' + JSON.stringify(req.params)) // Returns "req: {}"
console.log('req headers: ' + JSON.stringify(req.headers)) // Returns "req headers: {"accept":"application/json, text/plain, */*","content-type":"application/json;charset=utf-8","user-agent":"axios/0.19.2","content-length":"12","host":"localhost:3000","connection":"close"}"
const STATIC_DEPLOY_AUTH = {
username: 'virus',
password: 'pass1234',
secret: 'utf81234'
}
var bytes = CryptoJS.AES.decrypt(req.body, STATIC_DEPLOY_AUTH.secret)
var decryptedBody = bytes.toString(CryptoJS.enc.Utf8)
if (
decryptedBody.username === STATIC_DEPLOY_AUTH.username &&
decryptedBody.password === STATIC_DEPLOY_AUTH.password
) {
console.log('Authentication successful')
res.send('Ok')
}
})
module.exports = router
Node CLI commands
const CryptoJS = require('crypto-js')
const axios = require('axios')
const ciphertext = CryptoJS.AES.encrypt(
'{"username": "virus", "password": "pass1234"}',
'utc81234'
).toString()
axios.post('http://localhost:3000/api/static-deploy/', ciphertext).catch(error => {
console.log('Error: ' + error)
})
The fix is to add the snippet below in api/index.js:
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
As mentioned in https://aslamdoctor.com/blog/simple-crud-app-using-express-nuxtjs-using-servermiddleware-part-1-2/239
Related
I created a GET API call intended to fetch every user in my Logins database. For some reason, I keep on getting 500 calls on it. Here is my code:
const http = axios.create({
baseURL: "http://localhost:8080/api",
headers: {
"Content-type": "application/json"
}
});
function fetchUsers(){
http.get("/getusers").catch(err => {
console.log("OOF: " + err.message);
});
}
fetchUsers();
This is the routes file:
const users = require("../controller/users.controller.js");
var express = require('express');
var router = express.Router();
const pathStart = "/api";
// Retrieve all Users
router.get(pathStart + "/getusers", users.findAll);
My routes file is being used in my app.js file:
var indexRouter = require('./routes');
var userRouter = require('./routes/users.routes.js');
var app = express();
app.use('/', indexRouter);
app.use('/', userRouter);
users.controller.js:
// Retrieve all users from the database.
exports.findAll = (req, res) => {
console.log("extracting users");
const user = req.query.user;
var condition = user ? { user: { [Op.like]: `%${user}%` } } : null;
Users.findAll({ where: condition })
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message: err.message || "Error occurred when retrieving users"
})
});
};
This is my output: OOF: Request failed with status code 500
It is because of these two lines:
app.use('/', indexRouter);
app.use('/', userRouter);
Basically you will never enter inside userRouter, as indexRouter catches every request. You need to have something like this below.
In app.js:
app.use('/api/', userRouter);
app.use('/', indexRouter);
In userRouter.js:
const users = require("../controller/users.controller.js");
var express = require('express');
var router = express.Router();
// const pathStart = "/api"; not needed anymore
// Retrieve all Users
router.get("/getusers", users.findAll);
Your fetch logic:
const http = axios.create({
baseURL: "http://localhost:8080/api",
headers: {
"Content-type": "application/json"
}
});
function fetchUsers(){
http.get("/getusers").catch(err => {
console.log("OOF: " + err.message);
});
}
fetchUsers();
I'm trying to post data from Angular to Express.js
This is my function connected to the button (TypeScript):
upload(): void {
const nameFromId = document.getElementById('taskName') as HTMLInputElement;
this.taskName = nameFromId.value;
const testData = [
{
task: this.taskName,
selectedType: this.selectedType,
selectedSubject: this.selectedSubject
}
];
const body = JSON.stringify(testData);
this.http.post('/api/upload', body)
.subscribe();
"body" is not null
This is express:
const express = require('express');
const path = require('path');
const app = express();
const port = 8080;
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: true
}));
app.post('/api/upload', (req, res) => {
let task = req.body.task;
let selectedType = req.body.selectedType;
let selectedSubject = req.body.selectedSubject;
console.log("task: " + task);
console.log("type: " + selectedType);
console.log("subject: " + selectedSubject);
console.log("server: " + req.body);
res.end("yes");
})
app.use(express.static(__dirname + '/dist/al'));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname + '/dist/al/index.html'));
});
app.listen(process.env.PORT || port);
And this is what I get as a mistake:
mistake from console
If I put extra options to my "post method" from Angular and write something like:
this.http.post('/api/upload', body, {responseType: 'text'})
.subscribe();
After adding responseType: 'text' this mistake is no longer exists, but when it comes to console.log all data, that I posted to express, undefined:
Express console.log
What am I doing wrong?
You are sending a string as http request body.
Don't use JSON.stringify, try sending object as is.
const testData = [
{
task: this.taskName,
selectedType: this.selectedType,
selectedSubject: this.selectedSubject
}
];
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
}
this.http.post('/api/upload', testData, httpOptions)
.subscribe();
Also add this line to server:
app.use(bodyParser.json());
Finally:
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
I am trying to send the form data to the node server, the data is showing at the time of request in the network payload but not reaching to the node server.
Request initiator file.
let formData = new FormData();
// formData.append('test', 'hello');
formData.append('productImage', productImage);
// console.log(productName);
formData.append('productName', productName);
formData.append('productDesc', productDesc);
formData.append('productPrice', productPrice);
formData.append('productCategory', productCategory);
formData.append('productQty', productQty);
// var options = { content: formData };
console.log(formData.entries());
createProduct(formData)
.then((response) => {
console.log('server response = ', response);
})
.catch((err) => {
console.log('Error Occurred ', err);
});
}
product.js file
import axios from 'axios';
export const createProduct = async (formData) => {
console.log(formData);
const response = await axios.post('/api/products/', formData);
return response;
};
server.js file
const express = require('express');
const app = express();
const cors = require('cors');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const connectDB = require('./database/db');
const authRoutes = require('./routes/auth');
const categoryRoutes = require('./routes/category');
const productRoutes = require('./routes/products');
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.use(cookieParser());
// app.use(express.json());
app.use('/api/auth', authRoutes);
app.use('/api/category', categoryRoutes);
app.use('/api/products', productRoutes);
connectDB();
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`listening to port ${port}`));
routes/products.js
const express = require('express');
const router = express.Router();
const productsController = require('../controllers/products');
const { authenticateJWT } = require('../middleware/authenticator');
router.post('/', authenticateJWT, productsController.create);
// router.get('/', authenticateJWT, categoryController.readAll);
module.exports = router;
controllers/products.js
const Products = require('../models/Products');
exports.create = async (req, res) => {
// const { product } = req.file;
console.log(req.body);
try {
// const categoryExists = await Category.findOne({ category });
// let newProduct = new Products();
// newProduct.product_name = ;
// newProduct = await newProduct.save();
res.status(200).json({
successMessage: ' was created',
});
} catch (err) {
console.log('Category create error', err);
return res.status(500).json({
errorMessage: 'Please try again later',
});
}
};
It shows the empty object in the console while printing the req.body.
GET /api/category/ 304 2935.667 ms - -
[0] {}
[0] POST /api/products/ 200 4.827 ms - 34
see the network payload shows the data.
can anyone help me??
Try changing
headers: { 'Content-Type': 'multipart/form-data' }
To
headers: { 'Content-Type': 'application/json' }
and add the following line
app.use(bodyParser.urlencoded({ extended: true })); //this line is already mentioned above
app.use(bodyParser.json());//add this line
Try to add content type to headers on axios.post.
export const createProduct = (formData) => {
return axios({
method: 'post',
url: '/api/products/',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' }
});
};
Also use bodyParser.urlencoded() middleware on server side.
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
You will get data from req.body.
I use Nextjs and Express.js. I separate the nextjs root folder in the app folder like this :
app->pages->
-_app.js
-login.js
-index.js
When i add this :
app.get('*', (req, res) => {
const parsedUrl = parse(req.url,true);
const {pathname, query = {} } = parsedUrl;
const route = routes[pathname];
/**
* Pull in front end routes and check request against those routes
*
*/
if(route){
return app.render(req,res,route.page,query);
}
handle(req, res) // for all the react stuff
});
I got error like this :
Note that pages will be compiled when you first load them. ready at
http://localhost:3000 TypeError [ERR_INVALID_ARG_TYPE]: The "path"
argument must be of type string. Received type object
at assertPath (path.js:39:11)
at extname (path.js:835:5)
at new View (D:\WEBSITE\MENPRO\TRACER-STUDY-NEXTJS\node_modules\express\lib\view.js:57:14)
at Function.render (D:\WEBSITE\MENPRO\TRACER-STUDY-NEXTJS\node_modules\express\lib\application.js:570:12)
at app.get (D:\WEBSITE\MENPRO\TRACER-STUDY-NEXTJS\server\index.js:77:24)
But when i remove this : return app.render(req,res,route.page,query); its work again.
What happens with that ?
full code my server :
const express = require('express');
const bodyParser = require('body-parser');
const next = require('next');
const passport = require('passport');
const session = require('express-session');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const keys = require('./config/keys');
const uuidv4 = require('uuid').v4;
// const path = require('path');
// const RouteAPI = require('./modules');
const dev = process.env.NODE_ENV !== 'production';
const PORT = process.env.PORT || 3000;
const nextApp = next({ dev, dir: "./app" });
const { parse } = require('url');
const handle = nextApp.getRequestHandler()
const getRoutes = require('./routes');
const routes = getRoutes();
nextApp.prepare().then(() => {
// express code here
const app = express();
app.use(session({
genid: function (req) {
return uuidv4() // use UUIDs for session IDs
},
name: keys.session.name,
secret: keys.session.secret,
resave: false,
saveUninitialized: true,
rolling: true,
cookie: {
secure: false,
httpOnly: true,
maxAge: keys.session.maxAge, // satu hari,
sameSite: true,
}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(cookieParser());
app.disable('x-powered-by');
app.use(cors({ origin: keys.origin.url, credentials: true }))
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// app.use((req, res, next) => {
// res.header('X-XSS-Protection', '1; mode=block');
// res.header('X-Frame-Options', 'deny');
// res.header('X-Content-Type-Options', 'nosniff');
// res.header("Access-Control-Allow-Origin", keys.origin.url);
// next();
// })
// app.use('/api/', [
// RouteAPI.MahasiswaRoutes
// ]);
app.get('*', (req, res) => {
const parsedUrl = parse(req.url,true);
const {pathname, query = {} } = parsedUrl;
const route = routes[pathname];
/**
* Pull in front end routes and check request against those routes
*
*/
if(route){
return app.render(req,res,route.page,query);
}
handle(req, res) // for all the react stuff
});
app.listen(PORT, err => {
if (err) throw err;
console.log(`ready at http://localhost:${PORT}`)
});
})
// Server static assets if in production
Routes
module.exports = () =>{
return{
"/":{page:"/"},
"/login":{page:"/login"},
"/404":{page:"/404"}
};
};
Ah yes, I've had the same issue and just found the solution: use nextApp.render() instead of app.render()
if(route){
return nextApp.render(req,res,route.page,query);
}
I am getting the following error when trying to test a basic GET Route in node
TypeError: app.address is not a function
I am retrieving my app code that I want to test but I don't see any reference to "address" error in my code so I don't know what to fix.
Any suggestions from anyone?
Below is my unit test
let chai = require('chai');
let chaiHttp = require('chai-http');
let app = require('../src/app');
let should = chai.should();
chai.use(chaiHttp);
describe('/POST getRating', () => {
it('it should not POST a book without pages field', (done) => {
chai.request(app)
.get('/')
// .send(testData1)
.end((err, res) => {
console.log('ERROR', err);
res.should.have.status(200);
res.body.should.be.a('string');
done();
});
});
});
Below is my app.js code
import express from 'express';
import mongoose from 'mongoose';
import bodyParser from 'body-parser';
import config from './config';
import http from 'http'
mongoose.Promise = Promise;
import rating from './components';
const cors = config.cors
const mongouri = config.mongoURI;
mongoose.connect(mongouri);
const app = express();
app.use(cors.cors(cors.origins));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get("/", (req, res) => res.json({message: "Welcome to our Bookstore!"}));
app.use('/api/rating', rating);
const port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
const server = http.createServer(app);
server.listen(port);
server.on('listening', onListening);
function normalizePort(val) {
let port = parseInt(val, 10);
if (isNaN(port)) {
return val;
}
if (port >= 0) {
return port;
}
return false;
}
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
console.log('Listening on ' + bind);
}
export default app;
It may be a problem because of the transpilation. Try:
let app = require('../src/app').default;