Simple Fetch API Post Request Fails No Matter What - node.js

I have been working on this issue for 2 days, looked at various pages and cannot find a single solution that would work.
Please only reply if you know how to write them with async await functions and please reply if you know the answer of fetch api. I am not looking for axios solutions for the time being.
I have a backend server which runs on port 8000 of localhost, frontend runs on port 3000. Front end is written in React, backend is written in Node/Express.
I am able to successfully make a GET request from backend server but the POST request fails for some reason with the error "VM942:1 POST http://localhost:8000/frontend-to-backend 500 (Internal Server Error)"
Backend server has this error: SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse ()
// React-To-Node-Connection
// React "App.js" file
// "package.json" file contains this
// "proxy": "http://localhost:8000"
useEffect(() => {
const getBackend = async () => {
const res = await fetch('backend-to-frontend');
const data = await res.json();
if (!res.ok) {
throw new Error(`Cannot get data from backend server. HTTP Status: ${res.status}`);
}
console.log(data.message);
// Prints "Hi from backend!"
}
getBackend();
const postBackend = async () => {
try {
const res = await fetch('http://localhost:8000/frontend-to-backend',
{
method: 'POST',
mode: 'no-cors',
body: JSON.stringify({ message: 'Hi from frontend!' }),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}
);
if (res.ok) {
const data = await res.json();
console.log(data);
}
} catch (error) {
console.error(error);
}
}
postBackend();
}, []);
Now the backend code:
app.get('/backend-to-frontend', (req, res) => {
res.json({ message: 'Hi from backend!' });
});
app.post('/frontend-to-backend', (req, res) => {
try {
const reactMessage = JSON.parse(req.body.data);
console.log(`message: ${reactMessage}`);
} catch (err) {
console.error(err);
}
});
How to fix this? Please help!
Full backend server code can be found here:
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.get('/backend-to-frontend', (req, res) => {
res.json({ message: 'Hi from backend!' });
});
app.post('/frontend-to-backend', (req, res) => {
try {
const reactMessage = JSON.parse(req.body.data);
console.log(`message: ${reactMessage}`);
} catch (err) {
console.error(err);
}
});
const port = process.env.PORT || 8000;
app.listen(port, function () {
console.log(`Backend server started on port ${port}.`);
});

with no-cors, you can only use simple headers, so you cannot POST JSON (see: Supplying request options)
Try urlencoded:
const postBackend = async() => {
try {
const res = await fetch('http://localhost:8000/frontend-to-backend', {
method: 'POST',
mode: 'no-cors',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'message': 'Hi from frontend!'
})
});
if (res.ok) {
const data = await res.json();
console.log(data);
}
} catch (error) {
console.error(error);
}
}
postBackend();
and on the server, don't parse req.body, as it's already done by middleware:
app.post('/frontend-to-backend', (req, res) => {
console.log('req.body: ', req.body);
try {
const reactMessage = req.body.message;

req.body.data may be an object (check with debugger). If so, you might try to stringify before parsing :
JSON.parse(JSON.stringify(req.body.data))

I finally found the answer, here is my sample code. I did not change the React code that much so it is pretty much same, I removed the no cors section and added cors to Express JS code.
Here is my React code.
// React-To-Node-Connection
// "package.json" file has the following line
// "proxy": "http://localhost:8000"
// React Code
useEffect(() => {
const getBackend = async () => {
const res = await fetch('/backend-to-frontend');
const data = await res.json();
if (!res.ok) {
throw new Error(`Cannot get data from backend server. HTTP Status: ${res.status}`);
}
console.log(data.message);
}
getBackend();
const postBackend = async () => {
try {
await fetch('http://localhost:8000/frontend-to-backend',
{
method: 'POST',
body: JSON.stringify({ message: 'Hi from frontend!' }),
headers: {
'Content-Type': 'application/json'
}
}
);
} catch (err) {
console.error(err);
}
}
postBackend();
}, []);
And here is my Express JS code.
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
// Express JS Code
const cors = require('cors');
app.use(express.json());
app.use(cors());
app.get('/backend-to-frontend', (req, res) => {
res.json({ message: 'Hi from backend!' });
});
app.post('/frontend-to-backend', (req, res) => {
try {
console.log(req.body.message);
} catch (err) {
console.error(err);
}
});
const port = process.env.PORT || 8000;
app.listen(port, function () {
console.log(`Backend server started on port ${port}.`);
});
Thanks.

Related

Node server gives me undefined when I send data

I'm trying to send data to the server but when I log it gives me undefined even tho I can log it on the client. I think I'm missing something.
Thanks in Advance!
Client
const handleSubmit = async (e) => {
e.preventDefault()
try{
const response = await axios.post('http://localhost:8000/send', {formData})
console.log(response)
} catch(error){
console.log(error)
}
}
Server
app.post('/send', async (req, res) => {
console.log(req.body)
res.send("ok")
})
//client
const handleSubmit = async (e) => {
e.preventDefault()
const config = {
"headers":{
"Content-Type":"application/json"
}
}
const body = JSON.stringify({
formData
})
try{
const response = await axios.post('http://localhost:8000/send', body, config)
console.log(response)
} catch(error){
console.log(error)
}
}
// server
const express = require("express");
const app = express();
app.use(express.json()); // this is necessary
app.post('/send', async (req, res) => {
console.log(req.body)
res.send("ok")
})
Hope it helps!
remove the object property shorthand, use just formData:
const response = await axios.post('http://localhost:8000/send', formData)
I think you might need to set a header on the request
try adding config object as a 3rd argument
const config = {
headers: {'Content-Type': 'application/json'}
}
const handleSubmit = async (e) => {
e.preventDefault()
try{
const response = await axios.post('http://localhost:8000/send',
{formData}, config)
console.log(response)
} catch(error){
console.log(error)
}
}

Connection is getting reset if I am doing a POST request

I am new to Node JS. Please help me to understand what am I doing wrong in the POST request. Sometimes my POST request is getting successfully resolved but sometimes it is giving me ECONNRESET.
I am sharing my app.js and file reader wrapper module.
GET is working perfectly fine.
Below is my App.js
const express = require('express');
const FileReader = require('./readFS');
const app = express();
const FS = new FileReader();
const port = 3000;
app.listen(3000, '127.0.0.1', () => {
console.log(`App running on port ${port}`);
});
app.use(express.json());
app.get('/api/v1/tours', (request, response) => {
const data = FS.read(`${__dirname}/dev-data/data/tours-simple.json`).then(
(data) => {
response.status(200).json({
status: 'success',
results: data.length,
data: {
tours: data,
},
});
}
);
});
app.post('/api/v1/tours', (request, response) => {
(async (req, res) => {
const tours = await FS.read(`${__dirname}/dev-data/data/tours-simple.json`);
const newID = tours[tours.length - 1].id + 1;
const newTour = Object.assign({ id: newID }, req.body);
tours.push(newTour);
console.log('File written Started');
await FS.write(
`${__dirname}/dev-data/data/tours-simple.json`,
JSON.stringify(tours)
);
console.log('File written Successfully');
res.status(200).send('Created Succesfully');
})(request, response);
});
File Reader Module:
module.exports = class {
constructor() {
this.tours = [];
}
read(path) {
return new Promise((resolve, reject) => {
if (this.tours.length > 0) {
resolve(this.tours);
}
fs.readFile(path, 'utf-8', (err, data) => {
if (err) reject(er);
this.tours = Object.assign(JSON.parse(data));
resolve(this.tours);
});
});
}
write(path, data) {
return new Promise((resolve, reject) => {
if (data.length <= 0) reject('Data is empty');
fs.writeFile(path, data, (err) => {
if (err) reject('Could not write');
resolve('Done');
});
});
}
};
Explanation of the error I was encountering
My issue with occasionally receiving ECONNRESET when POSTing to my listening endpoint was caused by the endpoint automatically restarting after each successful POST of a file to that same endpoint.

Not receiving the API call output from a fetch function in NodeJS

I want to retrieve data from a API call and send the results to the user in NodeJS. There are separate functions for the API call and for the route call. The data is print to the console within the API call function, but not been sent to the route call. Please be kind to help me up with this. The API needs Basic auth headers.
import express from 'express';
import bodyParser from'body-parser';
import fetch from 'node-fetch';
// This server is used to get the issues of the project and store them in an array
/* App config */
const app = express()
const port = process.env.PORT || 9000;
/* Middleware */
app.use(bodyParser.json())
var issues = []
var issueIds = []
async function getIssueIds()
{
try
{
const response = await fetch('API link',
{
method: 'GET',
headers:
{
'Authorization': `Basic ${Buffer.from(
'authorization data'
).toString('base64')}`,
'Accept': 'application/json',
}
})
.then(res => res.json())
.then(json => {
issues = json.issues;
for(let i = 0; i < issues.length; i++)
{
issueIds.push(issues[i].id)
}
return issueIds;
})
.then(function(data) {
return data;
})
.catch(err => console.error(err));
}
catch(err)
{
return err;
}
}
app.get('/api/issues', (req, res) =>
{
getIssueIds().then(issues => {
console.log("Issue array: "+ issues);
});
res.set('Access-Control-Allow-Origin', '*');
//If success, send the data
res.status(200).send(issueIds);
});
/* Listen */
app.listen(port, () => console.log(`Listening on port : ${port}`));

How to stop downloading when the client cancels the request in nodejs

In the nodeJs application, I'm downloading a file with Axios. when the client cancels the request I have to stop downloading. After starting downloading How can I stop downloading?
with the following code, I notice that the client cancel its request:
req.on('close', function (err){
// Here I want to stop downloading
});
complete code :
const express = require('express')
const app = express()
const Axios = require('axios')
app.get('/download', (req, res) => {
req.on('close', function (err){
// Here I want to stop downloading
});
downloadFile(res)
})
async function downloadFile(res) {
const url = 'https://static.videezy.com/system/resources/previews/000/000/161/original/Volume2.mp4'
console.log('Connecting …')
const { data, headers } = await Axios({
url,
method: 'GET',
responseType: 'stream'
})
const totalLength = headers['content-length']
let offset = 0
res.set({
"Content-Disposition": 'attachment; filename="filename.mp4"',
"Content-Type": "application/octet-stream",
"Content-Length": totalLength,
// "Range": `bytes=${offset}` // my problem is here ....
});
data.on('data', (chunk) => {
res.write(chunk)
})
data.on('close', function () {
res.end('success')
})
data.on('error', function () {
res.send('something went wrong ....')
})
}
Axios documentation has a section about cancelation.
The code would look like:
// before sending the request
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// then pass-in the token with request config object
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
});
// upon cancelation
source.cancel('Operation canceled by the user');
Moreover, looks like there's an open issue for supporting AbortController/AbortSignal in Node.js 15+. You can check it out here.

fastify-request-context is not working for POST API calls

This is my fastify server written in typescript while using the fastify-request-context plugin I am able to access the context of fastify request when I am requesting the resource using the GET method,
But I am not able to access the context of fastify request if I am requesting the resource using POST method
import fastify from 'fastify';
const { fastifyRequestContextPlugin } = require('fastify-request-context');
const server = fastify({
logger: true
});
const preValidationFn = (req, reply, done): any => {
req.requestContext.set('hello', 'hello world');
console.log(req.requestContext.get('hello'));
done();
};
const handlerFn = (req, reply): any => {
console.log(req.requestContext.get('hello'));
reply.send('hello world');
};
server.route({
url: '/test',
method: ['GET', 'POST'],
preValidation: preValidationFn,
handler: handlerFn
});
server.register(fastifyRequestContextPlugin);
console.log('Starting fastify Typescript server ');
server.listen(8085, '0.0.0.0', (err, address): void => {
if (err) {
console.warn(err);
process.exit(1);
}
console.info(`Server listening at ${address}`);
});
process.on('uncaughtException', error => {
console.error(error);
});
process.on('unhandledRejection', error => {
console.error(error);
});```

Resources