node express return request body empty by using API fetch POST - javascript

Learning nodejs and trying to post a form from HTML (with image upload) to nodejs (express) but the request.body returning empty object.
Tried few solutions on this site but no one is working.
Here is my code for creating a dynamic form. (HTML)
function show(data) {
const d = data.temp_form;
let content = ''
// console.log(d)
d.forEach((item) => {
if (item === 'image_backup' || item === 'image_banner') {
content += `<label for='${item}'>${item}</label><input name='${item}' type='file' id='${item}' value=''><br/>`
}else{
content += `<label for='${item}'>${item}</label><input name='${item}' type='text' id='${item}' value=''><br/>`
}
})
content += ` <input type="submit" id="handle_submit">`
getFormContianer.innerHTML = content
}
Code handling form submit
async function handleForm(e) {
e.preventDefault();
let dataForm = new FormData(e.target)
let obj = {}
dataForm.forEach((value, key) => {
obj[key] = value
if( typeof value === 'object'){
console.log(value.name)
obj[key] = value.name
}
});
let data = JSON.stringify(obj);
await fetch(file_api, {
method: 'POST',
body: data
}).then((res)=>{
return res.json();
}).then((data)=>{
console.log('api err: '+data);
}).catch((err) =>{
console.log('api err: '+ err)
})
}
Then, in my nodejs
const express = require('express');
const cors = require('cors');
const config = require('./config')
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
const app = express()
const templates = require('./routes/templates-routes');
const files = require('./routes/files-routes');
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());
app.use(express.static('public'))
app.use('/api', templates.routes);
app.use('/create', files.routes);
app.listen(config.port, () => {
console.log(`Example app listening at http://localhost:${config.port}`)
})
and in the route.js
const express = require('express');
const router = express.Router();
const {replaceValue } = require('../controllers/filesController');
router.post('/file', replaceValue);
module.exports={
routes: router
}
for the fileController.js
const replaceValue = (request, response) =>{
console.log(request.body)
response.send(request.body)}
Hope that can get some comment for you, thank you so much!

let data = JSON.stringify(obj);
await fetch(file_api, {
method: 'POST',
body: data
You are passing a string to body and haven't specified a Content-Type header so fetch will generate a Content-Type: text/plain header.
Since plain text isn't JSON, the JSON parsing middleware you have set up in Express won't process it.
await fetch(file_api, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: data
Note that this will make it a preflighted request, so make sure you follow the instructions for the CORS module to support that.

Related

When using a fetch request in a Node JS server it receives the body as blank

I was working on a user login system in Node JS and was making a POST request to the server like this.
let data = {
username: "John Doe",
password: "123abc",
}
let options = {
method: 'POST',
headers: {
"Content-type": "application/json"
},
body: JSON.stringify(data),
}
fetch('/verify-login', options).then(function(r) {
return r.text();
}).then(function(dat) {
if (dat == 'n') {
document.getElementById('login-fail').innerHTML = 'User name or password is incorrect!';
} else {
console.log('Login Success');
}
});
Server Side code:
const express = require('express');
const port = 80;
const bodyParser = require("body-parser");
const fs = require('fs');
var app = express();
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
const cors = require("cors");
app.use(cors());
app.post('/verify-login', async function(q, r) {
let dat = await q.body; //<-- Body is just {} not what the fetch request sent
//do account check stuff with dat
if (success) {
r.send('y');
} else {
r.send('n');
}
});
app.listen(port, function() {
console.log("Started application on port %d", port);
});
This issue is that on the server side when I receive the request, the body is returned with '{}'. Does anybody know why this is happening and how I can fix it?
There are various data types you can pass to fetch through the body option.
If you pass something it doesn't recognise, it converts it to a string and sends that.
Converting a plain object to a string doesn't give you anything useful.
let data = {
username: "John Doe",
password: "123abc",
}
console.log(`${data}`);
You said you were sending JSON (with the Content-Type header. So you need to actually send JSON.
const json = JSON.stringify(data);

POST data passed from frontend JS to Nodejs/Expressjs is always undefined

I have a frontend JS script that takes text input from an HTML text box and sends it to an expressjs server. The body of the POST request, though, is always undefined, or depending on how I tweak things, returning as "{ }" if I view it via console.log( ). As I'm new to this, I can't seem to see what's going wrong.
Front end js:
async function submitCity(){
let x = document.getElementById("wg_input").value;
console.log("Successfully captured city name:", x);
let toWeather = JSON.stringify(x);
console.log("Input data successfully converted to JSON string:", toWeather);
const options = {
method: 'POST',
mode: 'cors',
headers: {'Content-Type': 'text/plain'},
body: toWeather
}
fetch('http://localhost:3000', options)
.then(res => console.log(res))
.catch(error => console.log(error))
}
Backend:
// Dependencies
const express = require('express');
const bp = require("body-parser");
const request = require("request");
const jimp = require('jimp');
const cors = require('cors');
const wgServer = express();
const port = 3000;
// Dotenv package
require("dotenv").config();
// OpenWeatherMap API_KEY
const apiKey = `${process.env.API_KEY}`;
// Basic server initialization
wgServer.use(cors())
wgServer.use(bp.json())
wgServer.use(bp.urlencoded({ extended: true }))
wgServer.listen(port, function() {
console.log(`Example app listening on port ${port}!`)
});
wgServer.post('/', async function (req, res) {
res.set('Content-Type', 'text/plain');
console.log(req.body)
res.send('Hello World');
//const data = await req.body;
// let jsonData = JSON.stringify(req.body);
// res.status(201);
//res.json();
});
The returned data is supposed to be a string of about 15 characters, give or take a few (a city and state). I thank you in advance.

What does it mean by this async Javascript server app error?

I was setting a weather app website that is connected to another site using a server, and asynchronous javascript was used, but after trying to run the code, an error reading "uncaught syntax error: unexpected end of input" in the last line in the app file...I don't understand what it means and therefore I don't know how to solve it
here's my app file code
/* Global Variables */
const apiKey = "726f360f99f8ed5ce834f19b2f632fd3"
// Create a new date instance dynamically with JS
let d = new Date();
let newDate = +d.getMonth()+1+'.'+ d.getDate()+'.'+ d.getFullYear();
const gen = document.querySelector("#generate");
gen.addEventListener("click", async() =>{
const Zcode = document.querySelector("#zip").value;
const feel = document.querySelector("#feelings").value;
try {
getTemp()
.then(temp =>{
const object = {
date: newDate,
temp: temp,
}
return DealingWithServer()
})
.then(data =>{
UpdateSite(data)
})
}catch(error){
console.log(error);
}
});
async function getTemp (){
const res = await fetch (`https://api.openweathermap.org/data/2.5/weather=?zip=${zipCode}&appid=${apiKey}&units=metric`);
const data= await res.json;
const temp = data.main.temp
return temp
}
async function DealingWithServer (){
await fetch('/recieve', {
method: "POST",
credentials: "same-origin",
headers: {"Content-Type": "application/json"},
body:JSON.stringfy({
date: newDate,
temp: temp,
feel: feel
})
});
const Sres = await fetch('/get', {credentials: "same-origin"});
const Sdata = await Sres.json()
return (Sdata);
}
function UpdateSite (data)
and my server file code
// Setup empty JS object to act as endpoint for all routes
projectData = {};
const port = 3000;
// Require Express to run server and routes
const express= require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
// Start up an instance of app
const app=express()
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
app.use(cors())
// Initialize the main project folder
app.use(express.static('website'));
app.get("/get",(req, res) => {
res.send(projectData)
})
app.post("/recieve", (req, res) => {
projectData =req.body
res.status(200)
})
// Setup Server
app.listen(3000,() =>{
console.log("Server running");
})
It looks to me like you've not finished your UpdateSite function at the bottom. It should read something like this:
function UpdateSite (data) {
// Do things to update the site
}
Since there is no function definition, the input (JavaScript code in this case) has ended unexpectedly - i.e. the parser was not expecting the input to end with function UpdateSite (data)

NodeJS CORS error when making a post request

I have a node js application where I forward form data from the client to the server to store this data there in a mongoDB.
To send the data to the server I use a POST request with API_URL: http://localhost/mews.
Whenever the POST request is executed, I keep seeing a CORS error in the console of the client.
client side JS
const API_URL = "http://localhost/mews";
form.addEventListener('submit', async (event) => {
event.preventDefault();
const formData = new FormData(form);
//Grab the form values
const name = formData.get('name');
const content = formData.get('content');
const mew = {
name,
content
}
//send the mew information to the server
const response = await fetch(API_URL, {
method: "POST",
body: JSON.stringify(mew),
headers: {
'Content-Type': 'application/json'
}
});
const json = await response.json();
console.log(json);
});
server side JS
const express = require('express');
const cors = require('cors');
const db = require('monk')('localhost/meower');
const mewe = db.get('mews');
var corsOptions = {
origin: 'http://localhost/mews',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
const app = express();
app.use(cors(corsOptions));
app.use(express.json());
function isValidMew(mew) {
return mew.name && mew.name.toString().trim() !== '' &&
mew.content && mew.content.toString().trim() !== '';
}
//chen user sends a message (POST)
app.post('/mews', async (req, res) => {
if (isValidMew(req.body)) {
const mew = {
name: req.body.name.toString(),
content: req.body.content.toString(),
created: new Date()
};
console.log(mew);
const createdMew = await mewe.insert(mew);
res.json(createdMew);
} else {
res.status(422);
res.json({
message: 'Hey! Name and Content are required!'
});
}
});
app.listen(4000, () => {
console.log("Listening on http://localhost:4000/");
});
ERROR in client console when making the post request
Cross-Origin Request Blocked: The Same Origin Policy does not allow reading of the remote resource at http: // localhost / mews. (Reason: CORS request was unsuccessful).
Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource.
this worked for me using "cors": "2.8.5"
const express = require('express');
const cors = require('cors');
const db = require('monk')('localhost/meower');
const mewe = db.get('mews');
const app = express();
app.use(express.json());
app.use(cors());
Hope it helps you too, the reference is in here https://www.npmjs.com/package/cors

Get value from client side script and override server side script

Below are my server side and client side JavaScript files. I have hard coded queryObject in server side script I can display the body in client-side.
The problem is how to get value from client side for queryObject variable in server side and override the existing values.
In short, current program converts USD to GBP as I hard-coded it. I want a way to access queryObject from client side and give my own values.
//=====================Server Side Script========================//
var request = require('request');
const path = require("path");
const express = require("express");
const app = express();
// const hbs = require("hbs");
const port = process.env.PORT || 3000;
const pathPublic = path.join(__dirname, "../public");
const pathView = path.join(__dirname, "../templates/views");
app.set("view engine", "hbs");
app.set("views", pathView);
app.use(express.static(pathPublic));
app.get("", (req, res) => {
res.render("home", {
title: "Currency Converter"
});
});
app.get("/currency", (req, res) => {
const uri = "https://currency-exchange.p.rapidapi.com/exchange?",
headers={
'x-rapidapi-host': 'currency-exchange.p.rapidapi.com',
'x-rapidapi-key': 'b13c4f3d67msh8143a7f1298de7bp1e8586jsn4453f885a4e7'
}
const queryObject = {
q: 1,
from: 'USD',
to: 'GBP'
};
request({
url:uri,
qs:queryObject,
headers: headers
},
function (error, response, body) {
if (error) {
console.log('error:', error); // Print the error if one occurred
} else if(response && body) {
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
res.json({'body': body}); // Print JSON response.
}
})
});
app.listen(port, () => {
console.log("Server is running on port " + port);
});
//=====================Client Side Script========================//
const currency = document.querySelector("#currency");
const text1= document.querySelector(".text1");
const text2= document.querySelector(".text2");
const text3= document.querySelector(".text3");
const Form = document.querySelector("form");
function refreshPage() {
window.location.reload();
}
Form.addEventListener("submit", e => {
e.preventDefault();
fetch("http://localhost:3000/currency").then(response => {
response.json().then(data => {
if (data.error) {
console.log(data.error);
} else {
currency.textContent = data.body;
}
});
});
SOLUTION:
In order to modify any values in server, you have to send appropriate HTTP method (eg: POST) with appropriate data in it. And let the server handle the request to change the content of object to make an API call from there.
I made some changes in your code for demonstration and install 'cors', 'body-parser' module and other missing modules to make it run.
HTML:
<!DOCTYPE html>
<html>
<body>
<div id="currencyType">
<select id="fromCurrency">
<option value="USD">USD</option>
<option value="GBP">GBP</option>
</select>
<select id="toCurrency">
<option value="USD">USD</option>
<option value="GBP">GBP</option>
</select>
</div>
<button type="button" id="getCurrency">Get Currency</button>
<div id="currency" name="currency" type="text"></div>
<script>
const currency = document.querySelector("#currency");
const btn = document.getElementById("getCurrency");
function refreshPage() {
window.location.reload();
}
btn.addEventListener("click", e => {
var fromCurrency = document.getElementById("fromCurrency");
fromCurrency = fromCurrency.options[fromCurrency.selectedIndex].value;
var toCurrency = document.getElementById("toCurrency");
toCurrency = toCurrency.options[toCurrency.selectedIndex].value;
var data = {
fromCurrency: fromCurrency,
toCurrency: toCurrency
};
// calls the API with POST method with data in it
fetch("http://localhost:3000/currency", {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
}).then(response => {
response.json().then(data => {
if (data.error) {
console.log(data.error);
} else {
currency.textContent = "1 " + fromCurrency + " = " + data.body + " " + toCurrency;
}
});
});
});
</script>
</body>
</html>
NodeJS:
var request = require('request');
const path = require("path");
const express = require("express");
const app = express();
var cors = require('cors')
// const hbs = require("hbs");
var bodyParser = require('body-parser');
const port = process.env.PORT || 3000;
const pathPublic = path.join(__dirname, "public");
const pathView = path.join(__dirname, "templates/views");
app.set("view engine", "hbs");
app.set("views", pathView);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(pathPublic));
app.use(cors())
app.get("", (req, res) => {
res.render("home", {
title: "Currency Converter"
});
});
app.post("/currency", (req, res) => {
console.log(req.body);
const uri = "https://currency-exchange.p.rapidapi.com/exchange?",
headers={
'x-rapidapi-host': 'currency-exchange.p.rapidapi.com',
'x-rapidapi-key': 'b13c4f3d67msh8143a7f1298de7bp1e8586jsn4453f885a4e7'
}
const queryObject = {
q: 1,
from: req.body.fromCurrency,
to: req.body.toCurrency
};
console.log(queryObject);
request({
url:uri,
qs:queryObject,
headers: headers
}, function (error, response, body) {
if (error) {
console.log('error:', error); // Print the error if one occurred
} else if(response && body) {
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
res.json({'body': body}); // Print JSON response.
}
})
});
app.listen(port, () => {
console.log("Server is running on port " + port);
});
Sample output:
You'll code in client-side to send a request to server-side containing the query object.
And on the server-side, you pick up your query object.
There are so many ways of doing this.
Using a GET request with parameters - On the server-side your query object will be available at res.query.params
Using a POST request - On the server side you will want to use the body-parser plugin for parsing your response body and hence, your data will be available at res.body
Read on body parser

Categories