Res not working after receiving JSON from client - javascript

I am trying to make a simple code works, but i have a little problem that i can't understand.
So, i am trying to send to server (Express 4.16), a form in JSON, with POST method. My server receive it (i can see it with console log req.body), but none of res methods are working (it just pass through it, res.send, res.json, res.redirect... and witout any errors..).
There is my code :
app.js
const express = require('express')
const path = require('path')
const app = express()
app.use(express.urlencoded({extended: false}))
app.use(express.json())
app.use('/public', express.static(path.join(__dirname, 'static')))
app.get('/', (req,res) => {
res.sendFile(path.join(__dirname, 'static', 'index.html'))
})
app.post('/', (req,res) => {
console.log(req.body)
res.send(`You did it ${req.body.name} !! `)
})
app.listen('8080')
main.js
window.addEventListener("load", function () {
let form = document.getElementById("id-form")
function sendData() {
let XHR = new XMLHttpRequest()
let data = {}
for (const input of form.getElementsByTagName('input')) {
data[input.name] = input.value
}
XHR.open('POST', '/')
XHR.setRequestHeader('Content-Type', 'application/json')
let dataToSend = JSON.stringify(data)
XHR.send(dataToSend)
}
form.addEventListener("submit", function (event) {
event.preventDefault()
sendData()
})
})
Thanks for your help !

You are not processing the response from the server in XHR.send(dataToSend), but you should be able to see the response in the network tab on the Chrome Devtools (or its equivalent in a different browser).

Related

fetch() POST requests with Express: unexpected end of JSON input

I've been trying to practice with some HTTP requests, and specifically I want to send a POST request, with data taken from an field, and sent via fetch() to a url on my localhost thats set up with express. From there i want to somehow get the response back and have that be displayed on my HTML doc.
However, I've ran into a real head scratcher when it comes to getting response.json() to be anything other than undefined.
here's my frontend script:
const url = "/result";
const inputField = document.querySelector("#write");
const submitButton = document.querySelector("#submit");
const responseField = document.querySelector("#text-goes-here");
const postText = async () => {
const text = inputField.value;
const data = JSON.stringify({ destination: text });
try {
const response = await fetch(url, {
method: "POST",
body: data,
headers: {
"Content-type": "application/json",
},
});
if (response.ok === true) {
const jsonResponse = await response.json();
responseField.innerHTML = jsonResponse;
}
} catch (error) {
console.log(error);
}
};
const displayText = (event) => {
event.preventDefault();
while (responseField.firstChild) {
responseField.removeChild(responseField.firstChild);
}
postText();
};
submitButton.addEventListener("click", displayText);
and my server script:
const express = require("express");
const bodyParser = require("body-parser");
const read = require('fs');
const router = express.Router();
const app = express();
const port = 3000;
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.get("/", (req, res) => {
res.sendFile("public/index.html");
})
router.post("/result", (req, res) => {
console.log(req.body);
res.send();
});
app.use("/", router);
app.listen(port, () => {
console.log(`Server running at port: ${port}`)
});
I did some digging in the dev console and found that (response.ok) is in fact "true", yet it errors out into the catch statement saying "SyntaxError: Unexpected end of JSON input
at postText (script.js:23)"
which is this line exactly:
const jsonResponse = await response.json();
can anyone shed any light on what i'm doing wrong here? I'm at a loss at this point
This error means that you're trying to parse something that is not a valid JSON object.
"SyntaxError: Unexpected end of JSON input at postText (script.js:23)"
Which is true, because the response you're sending back to the frontend is not a JSON.
router.post("/result", (req, res) => {
console.log(req.body);
// The response is not a valid JSON object
res.send();
});
You can change res.send() to res.json() and give it a valid object.
res.json({ name:"John", age:30, car:null })

priority of calbacks, how to handle a xmlhttprequest post request with node express js

I have a problem with managing xmlhttprequest post request. This is the code of the node express server:
const fs = require("fs")
const path = require("path")
const express = require("express")
const app = express()
const port = 3001
app.use(express.static(__dirname))
app.use("/", (request, response) => {
console.log("inside app.use")
response.sendFile(path.join(__dirname, "index.html"))
})
app.post("/database", (request, response) => {
console.log("inside app.use02")
console.log("request-body: "+request)
console.log("response-body: "+response)
response.send("it works")
})
app.listen(port)
The problem is thatwhen i do a ajax request to the /database url, it gets served by the app.use statement instead of the app.post statement. Why is that? is something that I'm no understanding ofhow expressjs works, what is it?
const btnForm = document.getElementById("form-btn")
const input01 = document.getElementById("firstName")
const input02 = document.getElementById("lastName")
const input03 = document.getElementById("profession")
const form = document.getElementById("form01")
form.addEventListener("submit", sendForm)
const httprequest = new XMLHttpRequest()
const FD = new FormData()
function sendForm(event){
event.preventDefault()
console.log("sendForm")
FD.append(input01.name, input01.value)
FD.append(input02.name, input02.value)
FD.append(input03.name, input03.value)
httprequest.open("POST", "http://localhost:3001/database")
httprequest.send(FD)
}
What I want to know is why the ajax request is served by the app.use statement first instead of the app.post statement, I thought that since I'm doing a ajax post request it should have to get responded with the app.post statement, despise he app.use statement being called before.
Your code should instead be
app.get("/", (request, response) => {
console.log("inside app.use")
response.sendFile(path.join(__dirname, "index.html"))
})
app.get / app.post is to define routes. While, app.use is to attach middleware.

close server from within router

I create an express app like this
const express = require('express')
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.post('/close', async (_, res) => {
res.status(200);
res.end();
app.close();
});
module.exports = app;
I instantiate it in another module
const myApp = require('./app.js');
myApp.listen(port, () => {
console.log(`Started server on ${port}`);
});
I want the server to shut itself down when it receives a post request to /close. At the moment, I just get a app.close is not a function error.
I know I can close a server externally like this
const server = myApp.listen(port, () => {
console.log(`Started server on ${port}`);
});
server.close();
but I want to close the server on a post request to /close, how can I do that?
To get access to your server object, try using
req.connection.server
from within your route handler.
.close() makes the server stop listening for new connections. Already-established connections are not affected. The server object emits a 'close' event when all open connections have disconnected.
process.exit() stops your whole nodejs app.
So, this code might do what you want.
app.post('/close', (req, res, next) => {
res.status(200)
res.end()
const server = req.connection.server
if (server.listening) {
server.addEventListener('close', ev => {
console.log('server closed. See ya later alligator.')
process.exit(0)
})
console.log('closing server')
server.close()
}
});
If you need to get the server object from your app object (if getting it from your req object isn't good enough), you could put in a little middleware function like this.
app.use( function adornApp( req, res, next ) {
req.app.locals.server = req.connection.server
next()
} )
Then you'll be able to get your server from app.locals.server once your middleware is first invoked.
You could use the http-terminator package to close your server. The following should do the trick. The reason we use the http-terminator is because the server won't close if it is visited via a route.
const { createHttpTerminator } = require("http-terminator");
const { initApp, app } = require("./app.js");
const PORT = 3000;
const server = app.listen(PORT, () => {
console.log(`Started server on ${PORT}`);
});
const httpTerminator = createHttpTerminator({ server });
initApp(httpTerminator);
Inside the module:
const express = require("express");
const app = express();
const initApp = (httpTerminator) => {
app.get("/close", async (_, res) => {
res.json({ message: "we closed" });
await httpTerminator.terminate();
});
};
module.exports = { initApp, app };

Express.js: Undefined request body (base64)

I'm trying to convert the .xls table to .csv row.
I found the library that helps with such operation, its name XLSX
As the first step, I encode .xls table to base64 format.
Now I'm trying to send the post request with Postman (with base64 code as the body of the request)
But when I'm trying to console.log my req.body, I'm receiving undefined. Can you tell me where I could make a mistake in my app?
my app.js:
const express = require('express');
const dataConverter = require('./inputDataConverter');
const { errorHandler } = require('./../error/error-handler');
const app = express();
const port = process.env.PORT || 5000;
const domain = process.env.DOMAIN || '0.0.0.0';
app.post('/convert', dataConverter);
app.all('*', (req, res, next) => next('Invalid request'));
app.use(errorHandler);
app.listen(port, () => {
console.log(`Microservice runs on http://${domain}:${port}`);
});
inputDataConverter.js:
const XLSX = require('xlsx');
module.exports = (req, res, next) => {
console.log('First console.log ' + req.body);
const getWorkbook = (data) => {
let wb = null;
if (!data.type || data.type === 'base64') {
wb = XLSX.read(data.body, { type: 'base64' });
}
console.log('everything is working');
return wb;
};
const requestData = req.body;
console.log(requestData);
getWorkbook(requestData);
};
As Molda said
You may need body parser
https://www.npmjs.com/package/body-parser
On new version actually body-parser is embedded to express so you can use that like:
app.use(express.json())
I really suggest you use express-generator package to generate base Express application
https://www.npmjs.com/package/express-generator
You may find something you may not need
just strip that out

Error: Request failed with status code 404 (Node.js + Vue.js)?

I am little bit confused and need some help.
I write an HTTP server using Node.js, and make an HTTP request from Vue.js to the HTTP server. Somehow it always return error like this:
Error: Request failed with status code 404
at FtD3.t.exports (createError.js:16)
at t.exports (settle.js:18)
at XMLHttpRequest.f.(:3010/anonymous function) (http://localhost:3010/static/js/vendor.1dc24385e2ad03071ff8.js:1312:88758)
It seems like url address don't correct cause error is 404 in browser. I check url address several times but did't notice something wrong. What I miss?
P.S. The main task to load file from remote sftp server from website. I use to that task ssh2-sftp-client library as backend side.
When user click the button, application run getFile function where we send post request to HTTP server.
Code inside Vue.js component:
getFile (fileName) {
axios.post('http://localhost:3010/csv', {file_name: fileName}, {headers: {'Authorization': this.token}}).then(response => {
console.log(response)
this.showAlert('You download file successfully.', 'is-success', 'is-top')
}).catch((error) => {
console.log(error)
this.showAlert(error, 'is-danger', 'is-bottom')
})
}
app.js:
const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');
const path = require('path');
const bodyParser = require('body-parser');
const csvRouter = require('./server/routes/csv')
const app = express();
app.use(cors());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'dist')));
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use('/csv', csvRouter);
module.exports = app;
routers/csv.js:
const express = require('express')
const router = express.Router()
const csvControllers = require('../controllers/csv')
router.get('/', csvControllers.getFile)
module.exports = router
controllers/csv.js:
const request = require('request')
const queryString = require('query-string')
let Client = require('ssh2-sftp-client')
let sftp = new Client()
const config = require('../config')
exports.getFile = (req, res) => {
console.log(req) // In console I don't notice nothing.
let data = {
file_name: req.query.file_name
}
let options = {
method: 'port',
json: true,
header: {'Authorization': req.header.token},
url: `http://localhost:3010/csv?` + queryString.stringify(data)
}
request(options, (error, response) => {
console.log('Message') // In console I don't notice nothing.
if (response) {
sftp.connect(config.sftpServer).then(() => {
return sftp.get('/reports/' + data.file_name)
}).then((chunk) => {
console.log(chunk)
}).catch((err) => {
console.log(err)
})
} else {
response.status(500).send(error)
}
})
}
It seems that app.listen(port) is missing in your app.js file:
app.listen(3000)
https://expressjs.com/en/starter/hello-world.html
In controllers/csv.js you never send a response. You should have a res.send or res.render or res.json somewhere.

Categories

Resources