Reputation: 33
I am creating a simple form using HTML and nodejs. The form takes in two data namely email and password and works according to the functionality written in the code.
I have two files app.js
and index.html
in my program.
app.js
const _ = require('lodash');
const express = require('express');
const path = require('path');
const Joi = require('joi');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.get('/',(req,res)=>{
res.sendFile(path.join(__dirname,'index.html'));
});
app.get('/example',(req,res)=>{
res.send('Hitting Example Route');
});
app.get('/example/:name/:age',(req,res)=>{
console.log(req.params);
console.log(req.query);
//res.send('example with route params');
res.send(req.params.name+":"+req.params.age);
});
app.post('/',(req,res)=> {
console.log(req.body);
const schema = Joi.object().keys({
email : Joi.string().trim().email().required(),
password : Joi.string().min(5).max(10).required()
});
Joi.validate(req.body,schema,(err,result)=>{
if(err)
{
console.log(err);
res.send('An error has occured');
}
console.log(result);
res.send('Successfully posted data');
});
//database work here
//res.json({success:true});
});
app.listen(3000);
index.html
<!DOCTYPE html>
<html>
<head>
<title>Text Input Control</title>
</head>
<body>
<!--<form !action="/"></form> method="POST" id="form">-->
<form method="POST" id="form">
First name: <input type = "text" name = "first_name" />
<br>
Last name: <input type = "text" name = "last_name" />
<input type="submit" value="Submit">
</form>
<script
src="http://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous"></script>
<script>
$(document).ready(()=>{
$('#form').submit((e)=>{
e.preventDefault({});
$.ajax({
url : '/',
type : 'post',
contentType : 'application/json',
data : JSON.stringify($('#form').serializeArray()),
success : (response)=>{
console.log('Successfuly got response');
console.log(response);
}
});
});
});
</script>
</body>
</html>
I get an error stating Cannot set headers after they are sent to the client
. How may I fix the code?
Error:
PS F:\DatabaseProject8> node app.js
[ { name: 'first_name', value: '[email protected]' },
{ name: 'last_name', value: 'gredyjht' } ]
{ ValidationError: "value" must be an object
at Object.exports.process (F:\DatabaseProject8\node_modules\joi\lib\errors.js:203:19)
at internals.Object._validateWithOptions (F:\DatabaseProject8\node_modules\joi\lib\types\any\index.js:764:31)
at module.exports.internals.Any.root.validate (F:\DatabaseProject8\node_modules\joi\lib\index.js:147:23)
at app.post (F:\DatabaseProject8\app.js:40:9)
at Layer.handle [as handle_request] (F:\DatabaseProject8\node_modules\express\lib\router\layer.js:95:5)
at next (F:\DatabaseProject8\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (F:\DatabaseProject8\node_modules\express\lib\router\route.js:112:3)
at Layer.handle [as handle_request] (F:\DatabaseProject8\node_modules\express\lib\router\layer.js:95:5)
at F:\DatabaseProject8\node_modules\express\lib\router\index.js:281:22
at Function.process_params (F:\DatabaseProject8\node_modules\express\lib\router\index.js:335:12)
isJoi: true,
name: 'ValidationError',
details:
[ { message: '"value" must be an object',
path: [],
type: 'object.base',
context: [Object] } ],
_object:
[ { name: 'first_name', value: '[email protected]' },
{ name: 'last_name', value: 'gredyjht' } ],
annotate: [Function] }
[ { name: 'first_name', value: '[email protected]' },
{ name: 'last_name', value: 'gredyjht' } ]
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (F:\DatabaseProject8\node_modules\express\lib\response.js:767:10)
at ServerResponse.send (F:\DatabaseProject8\node_modules\express\lib\response.js:170:12)
at Joi.validate (F:\DatabaseProject8\app.js:47:13)
at internals.Object._validateWithOptions (F:\DatabaseProject8\node_modules\joi\lib\types\any\index.js:767:20)
at module.exports.internals.Any.root.validate (F:\DatabaseProject8\node_modules\joi\lib\index.js:147:23)
at app.post (F:\DatabaseProject8\app.js:40:9)
at Layer.handle [as handle_request] (F:\DatabaseProject8\node_modules\express\lib\router\layer.js:95:5)
at next (F:\DatabaseProject8\node_modules\express\lib\router\route.js:137:13)
at Route.dispatch (F:\DatabaseProject8\node_modules\express\lib\router\route.js:112:3)
Upvotes: 0
Views: 389
Reputation: 823
The error you got is because of the asynchronous nature of Nodejs. Use Promise/Async-Await to prevent this type of error. Using Async-Await
app.post('/',async(req,res)=> {
console.log(req.body);
const schema = Joi.object().keys({
email : Joi.string().trim().email().required(),
password : Joi.string().min(5).max(10).required()
});
let result = await Joi.validate(req.body,schema);
if(result.err){
console.log(err);
res.send('An error has occured');
}else{
console.log(result);
res.send('Successfully posted data');
}
//database work here
//res.json({success:true});
});
This may do the job
Upvotes: 0
Reputation: 960
I had this problem sometimes, I solved changin res.send
for res.redirect('/example')
.
Another thing you can try is change the if statement, is it possible in case of an error res.send
is executed 2 times:
if(err){
console.log(err);
res.send('An error has occured');
}
else {
console.log(result);
res.send('Successfully posted data');
}
Upvotes: 0
Reputation: 1289
the schema you defined might be incorrect
define it like this
const schema = {
email: Joi.string().trim().email().required(),
password: Joi.string().min(5).max(10).required()
};
Upvotes: 0
Reputation: 1990
The reason you are getting an error about setting headers twice, is that an error is happening in Joi.validate
callback. You are sending "An error has occured" but then after the error handler you are still sending as well "Successfully posted data". You shouldn't call send
twice otherwise you will get that error. You should exit the Joi.validate
callback when an error occurs.
Upvotes: 2