I am trying to send an email using nodejs on a vercel host.
I am getting a bad request using the sendgrid/mail api. It looks as though it is not creating the header info in the request to Sendgrid.
When I dump the message, is it just the json info i am sending.
Here is the code i am using.
const sgMail = require('#sendgrid/mail')
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;
export default function (req, res) {
const mailData = {
from: 'dhook#fullonconsulting.com',
to: req.body.email,
subject: 'Message to Full On Consulting',
text: req.body.message,
html: '<div>'+req.body.message+'</div>'
}
const {
classes: {
Mail,
},
} = require('#sendgrid/helpers');
const mail = Mail.create(mailData);
const body = mail.toJSON();
console.log("======================================== ");
console.log("RAW BODY: " + JSON.stringify(body));
console.log("======================================== ");
sendMail(mailData)
.then((result) => {
console.log('Email sent...', result);
res.status(200).json({ status: 'SUCCESS' })
})
.catch((error) => console.log('Error ... ' + error.message));
}
async function sendMail(mailData) {
try {
var promise = new Promise( (resolve, reject) => {
sgMail.setApiKey(SENDGRID_API_KEY)
const msg = {
to: mailData.to, // Change to your recipient
from: mailData.from, // Change to your verified sender
subject: mailData.subject,
text: mailData.text,
html: mailData.html,
}
console.log("API KEY: " + SENDGRID_API_KEY);
console.log(JSON.stringify(msg));
sgMail
.send(msg)
.then(() => {
console.log('Email sent');
})
.catch((error) => {
console.error(error);
console.log('RECEIVED ERROR')
})
});
//promise.then( result => {
// console.log("PRomise Success ...");
//}, function(error) {
// console.log("Promise Failure...");
//});
} catch (error) {
console.log("CATCH ERROR: " + error)
return error;
}
}
Here is the Error
ResponseError: Bad Request
at node_modules/#sendgrid/client/src/classes/client.js:146:29
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 400,
response: {
headers: {
server: 'nginx',
date: 'Sat, 30 Oct 2021 13:51:20 GMT',
'content-type': 'application/json',
'content-length': '219',
connection: 'close',
'access-control-allow-origin': 'https://sendgrid.api-docs.io',
'access-control-allow-methods': 'POST',
'access-control-allow-headers': 'Authorization, Content-Type, On-behalf-of, x-sg-elas-acl',
'access-control-max-age': '600',
'x-no-cors-reason': 'https://sendgrid.com/docs/Classroom/Basics/API/cors.html',
'strict-transport-security': 'max-age=600; includeSubDomains'
},
body: { errors: [Array] }
}
}
I was not passing the info correctly from my front-end form which was causing the issue.
You can try expanding the response.body object and look for the error messages along with the help messages that you are getting.
Related
Getting response %PDF-1.4\n%����\n6 0 obj\n<</Type/XObject/Subtype/Image/Width 29/Height 29/Length 125/ColorSpace/DeviceGray/BitsPerComponent 1/Filter/CCITTFaxDecode/DecodeParms<</K -1/BlackIs1 true/Columns 29/Rows 29>>>>stream\n&����)�9_��~G?�A�G����?�q��(r�\b(�q�GA9�<?T\r���TD<D\�c��A�,Db������ ���\b����t\bdw�$�I/�\b.�"��G�
How to fix this response as readable pdf form please guide
const PDFDocument = require("pdfkit");
router.post("/get/PDF", (req, res) => {
axios({
method: "POST",
url: "http://143.155.55.11:8080/getPDF",
data: {
id: 1,
size: "A4",
},
headers: {
"Content-Type": "application/json",
},
})
.then(function (result) {
const doc = new PDFDocument();
let filename = "download";
// Stripping special characters
filename = encodeURIComponent(filename) + ".pdf";
// Setting response to 'attachment' (download).
// If you use 'inline' here it will automatically open the PDF
res.setHeader(
"Content-disposition",
'attachment; filename="' + filename + '"'
);
res.setHeader("Content-type", "application/pdf");
const content = encodeURIComponent(result.data);
doc.y = 300;
doc.text(content, 50, 50);
doc.pipe(res);
doc.end();
})
.catch(function (error) {
return res.status(500).json({
data: error,
status: "error",
message: "Something went wrong.",
});
});
});
router.post("/get/PDF", (req, res) => {
axios({
method: "POST",
url: "http://143.155.55.11:8080/getPDF",
data: {
id: 1,
size: "A4",
},
headers: {
"Content-Type": "application/json",
},
})
.then(function (result) {
const base64Str = Buffer.from(result.data).toString("base64");
let decodedBase64 = await base64topdf.base64Decode(
base64Str,
"download.pdf"
);
const fileContent = fs.readFileSync("download.pdf");
return res.status(200).json({
status: "success",
message: "Data send successfully.",
});
})
.catch(function (error) {
return res.status(500).json({
data: error,
status: "error",
message: "Something went wrong.",
});
});
});
I am using third party API. The way it works is:
I send post request then Token is returned in response.
Then i use that Token to check status. Afterwards, report is returned in response
In postman, i make both calls separately and it is working, but in Axios I have 1 async function and 2 await Promises.
Postman(NodeJs - Axios) looks like this:
For getting Token:
var data = JSON.stringify({
"security": {
"pLogin": "a",
"pPassword": "io"
},
"data": {
"pHead": "005",
"pCode": "00433",
"pLegal": 1,
"pClaimId": "z4LpXRWZKecSnL-FQtgD",
"pReportId": 8,
"pReportFormat": 1
}
});
var config = {
method: 'post',
url: 'http://10.22.50.10/report/',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
For getting Report with the token:
var data = JSON.stringify({
"data": {
"pHead": "005",
"pCode": "00433",
"pToken": "kgqjismxdrpjnjaqnlnbmovcsvnkarfd",
"pClaimId": "z4LpXRWZKecSnL-FQtgD",
"pReportFormat": 1
}
});
var config = {
method: 'post',
url: 'http://10.22.50.10/report/status',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
My async function with Axios:
/* 1. Searching for client in database (Full name is used, but can be changed)*/
const client = await client.findOne({
name: body.name,
family_name: body.family_name,
patronymic: body.patronymic
});
if (!client) {
return res.status(401).json({ message: "Client is not registered" });
}
/* 2. If client was found in database, make an API call */
let credit_report;
try{
credit_report = await axios.post(
'http://10.22.50.10/report',
{
security: {
pLogin: 'a',
pPassword: 'io',
},
data: {
pHead: "005",
pCode: "00433",
pLegal: 1,
pClaimId: client.claim_id,
pReportId: 8,
pReportFormat: 1
}
},
{
headers: {
'content-type': 'application/json'
}
}
);
}catch(err){
return res.status(400).json({errorMessage: err.message})
}
// await new Promise(resolve => setTimeout(resolve, 3000));
if(!credit_report.data.data.token) return res.status(400).json({message: credit_report.data});
const credit_report_status = await axios.post(
'http://10.22.50.10/report/status',
{
data: {
pHead: "005",
pCode: "00433",
pToken: credit_report.data.data.token,
pClaimId: client.claim_id,
pReportFormat: 1
}
},
{
headers: {
'content-type': 'application/json'
}
}
);
console.log(credit_report_status)
if(credit_report_status.data.data.result == '05000') return res.status(200).json({ message: 'Client fetched.', clientData64: credit_report_status.data.data.reportBase64});
else return res.status(400).json({message: credit_report_status.data})
When I am using Postman to check my module, it is saying Error 400 Bad Request
I'm suffering to create a server requesting to external server.
What I'm planning to do here is, sending a request to external server and return a code(like success or fail) to the client. But the callback function doesn't return. How should I make this happen?
app.post('/request', (req, res) =>{
const value = 'blah blah cyka'
const uploadValue = uploadTo(value)
res.json(uploadValue)
return
}
// This is request function
function uploadTo(VALUE){
await request.post({
url: 'https://stackunderpants.com/api',
method: 'POST',
rejectUnauthorized: false,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(VALUE)
}, (err, response, body) =>{
if(err){
console.log(response)
console.log(body)
console.log('Error has been occurred while sending to server. \n', err)
return {
'code': '400',
'detail': 'Error has been occurred while sending to server'
}
}
return {
'code': '200'
}
})
}
I've tried await async but not working...
const uploadValue = await uploadTo(value)
I'm literally dying right now.. it has been a week since I got this
Just edit your 3 lines code:
add "async" in app.post('/request', async (req, res) =>{...
add "await" in const uploadValue = await uploadTo(value) ...
add "await" in async function uploadTo(VALUE){ ....
`app.post('/request', async (req, res) =>{
const value = 'blah blah cyka'
const uploadValue = await uploadTo(value)
res.json(uploadValue)
return
}`
// This is request function
`async function uploadTo(VALUE){
await request.post({
url: 'https://stackunderpants.com/api',
method: 'POST',
rejectUnauthorized: false,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(VALUE)
}, (err, response, body) =>{
if(err){
console.log(response)
console.log(body)
console.log('Error has been occurred while sending to server. \n', err)
return {
'code': '400',
'detail': 'Error has been occurred while sending to server'
}
}
return {
'code': '200'
}
})
}`
While Uploading image , It is showing Error: Multipart: Boundary not found on node js server console
here is my react native code
const createFormData = async (photo, body) => {
const data = new FormData();
console.log("photoooooooooooo",photo.fileName);
data.append("photo", {
name: photo.fileName,
type: photo.type,
uri:
Platform.OS === "android" ? photo.uri : photo.uri.replace("file://", "")
});
Object.keys(body).forEach(key => {
data.append(key, body[key]);
});
console.log("datatyeeeeeeeeeeeeee",data);
return data;
};
const chooseFile = async() => {
var options = {
title: 'Select Image',
customButtons: [
{ name: 'customOptionKey', title: 'Choose Photo from Custom Option' },
],
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.showImagePicker(options, response => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
alert(response.customButton);
} else {
let source = response;
// You can also display the image using data:
// let source = { uri: 'data:image/jpeg;base64,' + response.data };
setfilePath(source);
// postImage(source);
handleUploadPhoto(source);
}
});
};
const handleUploadPhoto = async (filePath) => {
fetch("http://192.168.43.118:3000/updateImageprofile2", {
method: "POST",
body: createFormData(filePath, { userId: "123"}),
headers: {
Accept: 'application/json',
// 'Content-Type': 'image/jpeg',
'Content-Type': 'multipart/form-data',
// 'Content-Type': 'application/octet-stream'
},
})
.then(response => response.json())
.then(response => {
console.log("upload succes", response);
alert("Upload success!");
// this.setState({ photo: null });
})
.catch(error => {
console.log("upload error", error);
alert("Upload failed!");
});
};
and backend node js
router.post("/updateImageprofile2", upload.single('photo'), (req, res,next) => {
console.log("I am in");
console.log('files', req.files)
console.log('file', req.file)
console.log('body', req.body)
res.status(200).json({
message: 'success!',
})
});
but on the node js console it is showing
Error: Multipart: Boundary not found
at new Multipart (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\types\multipart.js:58:11)
at Multipart (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\types\multipart.js:26:12)
at Busboy.parseHeaders (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\main.js:71:22)
at new Busboy (C:\react\udemy_react\start\emb\auth_server2\node_modules\busboy\lib\main.js:22:10)
at multerMiddleware (C:\react\udemy_react\start\emb\auth_server2\node_modules\multer\lib\make-middleware.js:33:16)
at Layer.handle [as handle_request] (C:\react\udemy_react\start\emb\auth_server2\node_modules\express\lib\router\layer.js:95:5)
So there is a button which I click then choosefile function calls and after choosing files it goes to handlephoto function where the body part formdata create or append the image data into body then send the data to node js server where I am trying to upload image on upload folder but it is not happening. Please help me , I am trying it since morning and its evening
TL;DR Try omitting the Content-Type header. If it's not set, the browser will set it for you and it'll also configure the boundary.
The referenced boundary is the boundary you must provide alongside multipart/form-data. In your example it has not been provided.
When sending a request with content of type multipart/form-data you must provide the boundary value.
POST /test HTTP/1.1
Host: foo.example
Content-Type: multipart/form-data;boundary="boundary"
--boundary
Content-Disposition: form-data; name="field1"
value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"
value2
--boundary--
MDN: HTTP POST Method
In your post request, you are providing this content type without a boundary, which results in an error when the content is parsed.
However, often the easiest solution is to omit this header entirely. In this case the browser will configure this header for you--it'll also manage the boundary for you.
I have the following piece of code which is working perfect. However, my task is to replace fetch with axios. can you please guide, what would be the correct replacement of code in axios?
const create = async (credentials, software) => {
return await fetch('/api/software/create', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
credentials: 'include',
body: JSON.stringify(software)
})
.then((response) => {
return response.json()
}).catch((err) => console.log(err))
}
create({ t: jwt.token }, data)
.then((data) => {
if (data.error) {
this.setState({ error: data.error })
} else {
this.props.dispatch(initSoftware()); //if successful get the list of softwares in redux store
}
})
The data variable is an object which hold the req.body equivalent...
The above code is written in react and the create() is called within onSubmit eventhandler.
I am sure if I use axios the create() would be eliminated.. but how? Please guide..
It shouldn't be too different than what you currently have but something like this...
const create = async (credentials, software) => {
return await axios({
url: '/api/software/create'
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
withCredentials: true,
data: JSON.stringify(software)
})
.then((response) => {
return response.data;
}).catch((err) => console.log(err))
}
create({ t: jwt.token }, data)
.then((data) => {
if (data.error) {
this.setState({ error: data.error })
} else {
this.props.dispatch(initSoftware()); //if successful get the list of softwares in redux store
}
})
Note that the data you would be looking for should be in a property called data.
For more, check out the API references here.
2021 answer: just in case you land here looking for how to make GET and POST Fetch api requests using async/await or promises as compared to axios.
I'm using jsonplaceholder fake API to demonstrate:
Fetch api GET request using async/await:
const asyncGetCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncGetCall()
Fetch api POST request using async/await:
const asyncPostCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
});
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncPostCall()
GET request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
POST request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
})
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
GET request using Axios:
const axiosGetCall = async () => {
try {
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosGetCall()
POST request using Axios:
const axiosPostCall = async () => {
try {
const { data } = await axios.post('https://jsonplaceholder.typicode.com/posts', {
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosPostCall()