I encountered a problem in getting client POST data as follow:
my client sent:
content-type:application/x-www-form-urlencoded
the content:
{"value":"123456"}
In node.js, it is no problem to parse the content to a json object, my code as follow:
http.createServer(function onRequest(request, response) {
request.setEncoding("utf8");
var content = [];
request.addListener("data", function(data) {
content.push(data); //Collect the incoming data});
//At the end of request call
request.addListener("end", function() {
response.writeHead( 200, {"Content-Type": "text/plain"} );
ms = content[0];
if(ms.toString() != "")
{
var msg = ms.toString(); //Parse the ms into string
console.log(msg); // Prints the message in the console
var reqObj = JSON.parse(msg); // If the incoming message is in JSON format, it can be parsed as JSON.
console.log(reqObj);
response.end(); //Close the response
}
});
Output of the above code:
{"account": "48264"} //before parse to JSON
{ account: '48264' } //after parse to JSON
but when I changed into express.js and use bodyParser, it mixed up.
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.post('/', function(req, res, next) {
req.setEncoding('utf8');
console.log(req.body);
console.log(req.body.value);
});
module.exports = router;
The above outputs in the console as follow:
{ "{\"account\": \"123456\"}": "" }
undefined
I searched the web, but can't find the solution. please help.
Thanks in advance
You need to use express body-parser middleware before defining any routes.
var bodyParser = require('body-parser');
var app = express();
port = parseInt(process.env.PORT, 10) || 8080;
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// parse application/json
app.use(bodyParser.json());
app.listen(port);
app.post("/someRoute", function(req, res) {
console.log(req.body);
res.status(200).json({ status: 'SUCCESS' });
});
Related
I'm using VueJs3, Multer middleware for file uploading, expressJs. Its pretty new for me, so probably it is just a small mistake and i couldn't find it... After submit in console axios throw this error : "Request failed with status code 404".
And console.log(formData.append("file", this.file)) gives 'undefined'.
Some code from component:
import axios from "axios"
export default {
name: "FileUpload",
data() {
return {
file: "",
message: "",
}
},
methods: {
onSelect() {
const file = this.$refs.file.files[0]
this.file = file
},
async onSubmit() {
const formData = new FormData()
formData.append("file", this.file)
try {
await axios.post("/upload", formData)
this.message = "Upload successfully"
} catch (err) {
console.log(err)
this.message = "Something went wrong :("
}
},
},
}
And back-end:
const express = require("express")
const dotenv = require("dotenv")
const cors = require("cors")
const bodyParser = require("body-parser")
// const db = require("./app/config/db.config")
const multer = require("multer")
dotenv.config()
const app = express()
const port = process.env.PORT || 8080
const upload = multer({
dest: "./uploads",
})
var corsOptions = {
origin: "http://localhost:8081",
}
app.use(cors())
app.use(express.json())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.post("/upload", upload.single("file"), (req, res) => {
res.json({ file: req.file })
})
app.listen(port, () => console.log(`Server started on port ${port}`))
I been trying to look for solutions in some tutorials, but probably mistake is to small for my rookie eyes at the moment...
Not sure which axios version you are using but you could try switching the versions because some versions handle multipart/form-data differently.
from docs
Starting from v0.27.0, Axios supports automatic object serialization to a FormData object if the request Content-Type header is set to multipart/form-data.
I take this to mean that the header needs to be defined explicitly
const formData = new FormData()
formData.append("file", this.file)
await axios.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
you can also try using the postForm method
docs
await axios.postForm("/upload", {file: this.file})
// or with multipart
await axios.postForm("/upload", {'files[]': [this.file]})
I would also recommend that you look at the network panel to see if that header is included, and try sending the request directly with something like postman or insomnia to determine definitively whether the issue is on the front-end or back-end.
I recently added express-static-gzip to my server and have since noticed that my req.body is undefined in my router.post when submitting a form.
Previously it was working without issue but now I am getting a POST 500 internal server error, a Cannot read property "name" of undefined & a Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0 error.
here is my form submission:
const handleSubmit = async (e) => {
e.preventDefault();
setStatus("Sending...");
const { name, email, message } = e.target.elements;
let details = {
name: name.value,
email: email.value,
message: message.value,
};
console.log(typeof JSON.stringify(details))
let response = await fetch("/api/v1/mail", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8"
},
body: JSON.stringify(details),
});
setStatus("Send Message");
let result = await response.json();
alert(result.status);
};
here is my server setup, the route in question is '/api/v1/mail':
const express = require('express')
const path = require('path')
const router = express.Router();
const cors = require("cors");
var expressStaticGzip = require("express-static-gzip")
const mailRoutes = require('./routes/mail');
const server = express()
server.use('/api/v1/mail', mailRoutes)
server.use(cors())
server.use(express.json())
server.use("/", router)
server.use(expressStaticGzip(path.join(__dirname, 'public'), {
enableBrotli: true
}))
server.use(express.static(path.join(__dirname, 'public')))
and here is my POST request:
router.post("/", (req, res) => {
const name = req.body.name;
const email = req.body.email;
const orderId = req.body.orderId
const message = req.body.message;
const mail = {
from: name,
to: "info#example.com ",
subject: "Contact Form Submission",
html: `<p>Name: ${name}</p>
<p>Email: ${email}</p>
<p>Order ID: ${orderId}
<p>Message: ${message}</p>`,
};
contactEmail.sendMail(mail, (error) => {
if (error) {
res.json({ status: "ERROR" , req});
} else {
res.json({ status: "Message Sent" });
}
});
});
})
If the route you're trying to use req.body.name in is this one:
server.use('/api/v1/mail', mailRoutes)
Then, you have to move this:
server.use(express.json())
to be BEFORE that route definition.
As it is, you're trying to handle the route request before your middleware has read and parsed the JSON. Route handlers and middleware are matched and executed in the order they are registered. So, any middleware that needs to execute for a route handler to function must be registered before the route handler itself is registered.
I need to consume third party webservice using node js and write it to oracle table . Basically I got the code for getting the data. What is the command to insert bulk data into oracle from node json? I will be getting a huge file and I am parsing it. The code is as below.
Can someone help me with insert command here?
const express = require("express");
const oracledb = require("oracledb");
const cors = require("cors");
const bodyparser = require("body-parser");
const request = require("request");
let app = express();
app.use(cors());
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({extended:false}));
app.get("/demo",(req,res)=>{
oracledb.getConnection({
user:"INFO",
password:"12345",
connectString:"194.234.222.22:1521/TEST"
},(err,connection)=>{
if(err) throw err;
else{
//make request call
try{
request.post({
url: 'https://qmilet.com/api/v1/partners/login',
body: {"user":"_api","password":"_api"},
json: true
}, function(error, response, body){
//console.log(body);
token = body.access_token
console.log(token);
//make api request
//31ae0b786d4958c0a93a459f46a59d67b8a9cff8
try{
//replace thw dynamic token
//Syntax : ${token}
request.post({
url : `https://qmilet.com/api/v1/orders/pull?access_token=${token}&date_from=2020-05-01&date_to=2021-05-30&include_synced=1`
},function(err,response,body){
let obj = JSON.parse(body);
res.send(obj.data);
//how to read parsed data, and insert into oracle db
})
}catch(err){
console.log(err);
}
});
}catch(err){
console.log(err);
}
}
});
});
app.listen(8080,()=>{
console.log("server started");
});
I am using 12.1.0.2 version of Oracle.
I am trying to build a small website. In that i using React for frontend, Nodejs for backend, and some third party api. Here my idea is, first to post the form data to nodejs. And from then i accepting that data in node and need to call an external api. For this purpose i am using axios. After receiving values from my api i have to send that value back to react application. And when i run my code in postman, the output is {}. I think that i am not getting values from my api but dont know how to resolve this. And i am new to these technologies. Someone pls help me to sort out this problem. Thanking you in advance. Here is my what i have tried so far.
const express = require('express');
const axios = require('axios');
const router = express.Router();
const request = require('request');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended : false}));
router.get('/', (req, res) => {
res.send(" Express Homepage is running...");
});
async function callApi(emailid, pswd) {
return axios({
method:'post',
url:'http://51.X.X/api/login',
data: {
"email": `${emailid}`,
"password": `${pswd}`
},
headers: {'Content-Type': 'application/json' }
})};
callApi().then(function(response){
return response.data;
})
.catch(function(error){
console.log(error);
})
app.post('/api/login', (req, res) => {
let emailid = String(req.body.email);
let pswd = String(req.body.password);
const data = callApi(emailid, pswd);
if(data) {
res.send(data);
}else {
res.json({msg : " Response data not recieved.."})
}
});
use async/await syntax to handle asynchronous calls
app.post('/api/login', async (req, res) => {
let emailid = String(req.body.email);
let pswd = String(req.body.password);
const data = await callApi(emailid, pswd);
if(data) {
res.send(data);
}else {
res.json({msg : " Response data not recieved.."})
}
});
The problem is you are not waiting for async call to finish.
use async-await as mentioned in official doc https://www.npmjs.com/package/axios
function callAPI(){
const response = await axios({
method:'post',
url:'http://51.X.X/api/login',
data: {
"email": `${emailid}`,
"password": `${pswd}`
},
headers: {'Content-Type': 'application/json' }
})};
return response
}
app.post('/api/login', async (req, res) => {
let emailid = String(req.body.email);
let pswd = String(req.body.password);
//add try catch to catch exception
const data = await callApi(emailid, pswd);
if(data) {
//check for response from axios in official doc and send what data you
want to send
res.send(data);
}else {
res.json({msg : " Response data not recieved.."})
}
});
I'm getting the error specified above when trying to build a express-stormpath app. I'll list the applicable code:
Error: If you do not specify a 'requestAuthenticator' field, you must specify an ApiKey.
at Object.getAuthenticator (d:\dev\git-repos\bps\VolumeGridDataEntry\node_modules\express- stormpath\node_modules\stormpath\lib\authc\index.js:24:11)
at new RequestExecutor (d:\dev\git-repos\bps\VolumeGridDataEntry\node_modules\express-stormpath\node_modules\stormpath\lib\ds\RequestExecutor.js:37:37)
at new DataStore (d:\dev\git-repos\bps\VolumeGridDataEntry\node_modules\express-stormpath\node_modules\stormpath\lib\ds\DataStore.js:46:52)
at new Client (d:\dev\git-repos\bps\VolumeGridDataEntry\node_modules\express-stormpath\node_modules\stormpath\lib\Client.js:8:21)
at d:\dev\git-repos\bps\VolumeGridDataEntry\node_modules\express-stormpath\lib\stormpath.js:60:36
at d:\dev\git-repos\bps\VolumeGridDataEntry\node_modules\express-stormpath\node_modules\stormpath\lib\authc\ApiKeyLoader.js:14:14
at d:\dev\git-repos\bps\VolumeGridDataEntry\node_modules\express-stormpath\node_modules\stormpath\node_modules\properties-parser\index.js:348:20
at fs.js:208:20
at Object.oncomplete (fs.js:108:15)
[Updated] server.js
var express = require('express'),
session = require('express-session'),
crypto = require('crypto'),
formidable = require('formidable'),
path = require('path'),
favicon = require('serve-favicon'),
logger = require('morgan'),
cookieParser = require('cookie-parser'),
bodyParser = require('body-parser'),
index = require('./routes/index'),
users = require('./routes/users'),
stormpath = require('express-stormpath'),
config = require('./config/credentials.js'),
app = express();
function hashPwd(pwd) {
return crypto.createHash('sha256').update(pwd).digest('base64').toString();
}
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(stormpath.init(app, {
apiKeyFile: config.stormpathapi.apiKeyFile,
application: config.stormpathapi.application,
secretKey: config.stormpathapi.secretKey,
sessionDuration: 1000 * 60 * 30
}));
// domains for better error handling
app.use(function(req, res, next){
// create a domain for this request
var domain = require('domain').create();
// handle errors on this domain
domain.on('error', function(err){
console.error('DOMAIN ERROR CAUGHT\n', err.stack);
try {
// failsafe shutdown in 5 seconds
setTimeout(function(){
console.error('Failsafe shutdown.');
process.exit(1);
}, 5000);
// stop taking new requests
server.close();
try {
// attempt to use Express error route
next(err);
} catch(error){
// if Express error route failed, try
// plain Node response
console.error('Express error mechanism failed.\n', error.stack);
res.statusCode = 500;
res.setHeader('content-type', 'text/plain');
res.end('Server error.');
}
} catch(error){
console.error('Unable to send 500 response.\n', error.stack);
}
});
// add the request and response objects to the domain
domain.add(req);
domain.add(res);
// execute the rest of the request chain in the domain
domain.run(next);
});
// cross-site request forgery protection
app.use(require('csurf')());
app.use(function(req, res, next){
res.locals._csrfToken = req.csrfToken();
next();
});
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'client')));
//name: cookie_name,
//store: sessionStore, // connect-mongo session store
app.use(session({
secret: config.cookieSecret,
resave: false,
saveUninitialized: true
}));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
route index.js
var express = require('express'),
stormpath = require('express-stormpath'),
router = express.Router();
router.get('/', stormpath.groupsRequired(['dataentry']), function(req, res) {
res.render('index', { title: 'Volume Grid Data Entry' });
});
module.exports = router;
Initially the route signature was this but that didn't work either. I will need the ability in the future to base page security on groups...so, I'm not sure if I should use loginRequired or groupsRequired or both :-/
router.get('/', stormpath.loginRequired, function(req, res) {
Thanks!
That code looks correct -- but where is your app.use(require('./index')); code? That will be necessary after the app.use(stormpath.init(...)) stuff above =)
NOTE: I'm the author of the express-stormpath library.
EDIT: Here's a full example:
var express = require('express'),
stormpath = require('express-stormpath'),
router = express.Router();
var app = express();
router.get('/', stormpath.groupsRequired(['dataentry']), function(req, res) {
res.render('index', { title: 'Volume Grid Data Entry' });
});
app.use('/', router);
app.listen(3000);