Anybody able to help? This always gives me an error. Any advice? I get the following error: Error: could not handle the request. I have removed sensitive information.
const functions = require('firebase-functions');
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey("API KEY"); /*PLACEHOLDER KEY*/
const cors = require('cors')({
origin: ['https://DOMAIN.co.uk'],
methods: ['POST', 'OPTIONS'],
allowedHeaders: ['Content-Type'],
preflightContinue: false,
optionsSuccessStatus: 204
});
exports.sendEmailConfirmation = functions.https.onRequest((req, res) => {
cors(req, res, () => {
return Promise.resolve()
.then(() => {
if (req.method !== 'POST') {
const error = new Error('Only POST requests are accepted');
error.code = 405;
throw error;
}
const message = {
to: 'email#email.com',
from: 'email#email.com',
subject: 'subject',
text: 'some text',
html: 'some html'
};
return sgMail.send(message);
})
.then((response) => {
if (response.body) {
res.send(response.body);
} else {
res.end();
}
})
.catch((err) => {
console.error(err);
return Promise.reject(err);
});
});
});
It loads normally using functions, and shows no errors on there, I can't work out why it is not working.
Many thanks in advice
Related
I'm following a restApi course with Node.js, It's a blog API. my problem is when deleting a post for the unAuthorized user it first gives me a 500 error
"error": "Cannot read property 'toString' of undefined"
. but when doing it again it gives me
Post not found with id of.
Of course, it supposed to give me
not authorized to delete this post.
Update the post is also the same, I even tried to copy/paste the code from the course but the same problem.
postController
exports.deletePost = asyncHandler(async (req, res, next) => {
const post = await Post.findByIdAndDelete(req.params.id);
if (!post) {
return next(
new ErrorResponse(`Post not found with id of ${req.params.id}`, 404)
);
}
// Make sure user is post owner
if (post.user.toString() !== req.user.id) {
return next(
new ErrorResponse(
`User ${req.params.id} is not authorized to delete this post`,
401
)
);
}
post.remove();
res.status(200).json({ success: true, data: post});
});
updatePost
exports.updatePost = asyncHandler(async (req, res, next) => {
let post = await Post.findById(req.params.id);
if (!post) {
return next(
new ErrorResponse(`Post not found with id of ${req.params.id}`, 404)
);
}
// Make sure user is post owner
if (post.user.toString() !== req.user.id) {
return next(
new ErrorResponse(
`User ${req.params.id} is not authorized to update this post`,
401
)
);
}
post = await Post.findOneAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true
});
res.status(200).json({ success: true, data: post });
});
You could introduce a type check on the post.user object to ensure that the user exists within the post.
if (typeof post.user == "undefined" || post.user.toString() !== req.user.id)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
I have tried the code
if (typeof post.user == "undefined" || post.user.toString() !== req.user.id)
But after using this cause to get me an error 'User not Authorized' in my error handling.
In my case, I have to convert the req.user.id to an integer
if (post.user !== req.user.id.parseInt)
const express = require("express");
const router = express.Router();
const fetchuser = require("../middleware/Fetchuser");
const Notes = require("../models/Notes.js");
const { body, validationResult } = require("express-validator");
router.get("/fetchnotes", fetchuser, async (req, res) => {
try {
const notes = await Notes.find({ user: req.user });
res.json(notes);
} catch (error) {
console.log(error.message);
res.status(500).send("error occured");
}
});
router.post(
"/addnotes",
[
body("title").isLength({ min: 5 }),
body("description").isLength({ min: 3 }),
],
fetchuser,
async (req, res) => {
try {
const { title, description, tag } = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const note = new Notes({
title,
description,
tag,
user: req.user.id,
});
const savedNotes = await note.save();
res.json(savedNotes);
} catch (error) {
console.log(error.message);
res.status(500).send("error occured");
}
}
);
router.put("/updatenotes/:id", fetchuser, async (req, res) => {
const { title, description, tag } = req.body;
const newNote = {};
if (title) {
newNote.title = title;
}
if (description) {
newNote.description = description;
}
if (tag) {
newNote.tag = tag;
}
let note = await Notes.findById(req.params.id);
if (!note) {
return res.status(400).send("error occured");
}
if (note.user !== req.user.id.parseInt) {
return res.status(401).json("user not allowed");
}
note = await Notes.findByIdAndUpdate(
req.params.id,
{ $set: newNote },
{ new: true }
);
res.json(note);
});
module.exports = router;
I have real hard time to get custom Apollo error on the client side.
Here is the server code:
...
const schema = makeExecutableSchema({
typeDefs: [constraintDirectiveTypeDefs, ...typeDefs],
resolvers,
schemaTransforms: [constraintDirective()],
});
const server = new ApolloServer({
schema,
dataSources,
context({ req }) {
const token = req.headers.authorization;
const user = token ? getUserFromToken(token) : '';
return { user };
},
debug: false,
formatError: (err) => {
// ToDo: Generate unique token and log error
if (err!.extensions!.code == 'INTERNAL_SERVER_ERROR') {
return new ApolloError('We are having some trouble', 'ERROR', {
token: 'uniquetoken',
});
}
return err;
},
uploads: false,
});
...
Client code:
...
const ADD_CLAIM = gql`
mutation addClaim($claim: ClaimInput!) {
addClaim(claim: $claim) {
id
}
}
`;
...
const [addClaim, { data, error }] = useMutation(ADD_CLAIM);
...
const onSubmit = async () => {
try {
debugger;
const r = await addClaim({
variables: {
input: {
id: insured.insured,
date: '20/12/2020',
...
therapy: treatment.treatments.map(treat => ({
id: treat.treatId,
...
})),
},
},
});
debugger;
console.log('r', r);
} catch (err) {
debugger;
setFormError(error ? error.message : err.message);
console.log('Error:', err);
}
};
...
if (error) {
debugger;
return <div>error</div>;
}
I expect to get the custom error : "We are having some trouble".
However, no matter what I do I got: "Response not successful: Received status code 400"
I am 100% give custom error from the server:
But I receive on client side:
Moreover, when I check network tab of Developer Tools, response I do have my error:
But I cannot access it from the code.
BTW, in the playground I see my error:
Here where are my errors :
error.networkError.result.errors
What nobody knows ?
Or
const errorLink = onError(({ graphQLErrors, networkError }) => {
debugger;
console.log(graphQLErrors);
console.log(networkError);
});
const client = new ApolloClient({
...
link: ApolloLink.from( [errorLink, ...]),
});
It works as well.
Yes, sometimes GraphQL is a nasty beast
Trying to test a POST request and GET by ID. For the POST error it states: "expected 200, got 400". Then for the 3 GET by IDs, the first two is "Error: Timeout of 2000ms exceeded......", then gives me the two IDs a few minutes later. Then the third: "Expected 404, got 400".
Tried looking at docs for expect, supertest and mocha and couldnt find a solution. Those 3 is what i use for this testing
Here is the POST test
describe('POST /drinks', () => {
it('should create a new drink', (done) => {
let type = 'coffee';
let name = 'testName';
let image = 'testImage';
request(app)
.post('/drinks')
.send({
type,
name,
image
}).expect(200).expect((res) => {
expect(res.body.type, res.body.name, res.body.image).toBe(text);
}).expect((res) => {
expect(res.body.rating).toBe(number);
}).end((err, res) => {
if (err) {
return done(err);
}
Coffee.find({
type
}).then((feedData) => {
expect(feedData.length).toBe(1);
expect(feedData[0].type).toBe(text);
done();
}).catch(e => done(e));
});
});
});
Then heres the GET by ID:
describe('GET /drinks/:id', () => {
it('should return individual drink document', (done) => {
request(app)
.get(`/drinks/${feedData[0]._id.toHexString()}`)
.expect(200)
.expect(res => {
expect(res.body.drink.text).toBe(feedData[0].text);
})
.end((err, res) => {
if (err) return done(err);
done();
});
});
it('should return 404 if drink is not found', (done) => {
let hexId = new ObjectID().toHexString();
request(app)
.get(`/drinks/${hexId}`)
.expect(404)
.end((err, res) => {
if (err) return done(err);
done();
});
});
it('should return 404 for non-object ids', (done) => {
request(app)
.get('/drinks/123abc')
.expect(404)
.end((err, res) => {
if (err) return done(err);
done();
});
});
});
Heres my route for POST:
// POST a drink
exports.postDrinks = (req, res) => {
let type = req.body.type;
if (!type) {
res.status(400).send('Request parameters missing');
}
let newDrink;
// Default Drink Fields
let defaultFields = {
type,
name: req.body.name,
tastingNotes: req.body.tastingNotes,
comments: req.body.comments,
image: req.body.image,
rating: req.body.rating
}
// Determine which type and store it as that type
switch (type) {
case 'beer':
newDrink = new Beer({
...defaultFields,
style: req.body.style,
source: req.body.source,
});
break;
case 'coffee':
newDrink = new Coffee({
...defaultFields,
beanType: req.body.beanType,
brewTime: req.body.brewTime,
strength: req.body.strength
});
break;
case 'liquor':
newDrink = new Liquor({
...defaultFields,
typOfLiquor: req.body.typOfLiquor
});
break;
case 'tea':
newDrink = new Tea({
...defaultFields,
leafType: req.body.leafType,
steepTime: req.body.steepTime,
});
break;
default:
console.log('Please select an apprioriate drink');
break;
}
// Saves POST and sends it back as well. If not, then error
newDrink.save().then((drink) => {
res.send(drink);
}, (e) => {
res.status(400).send(e);
});
}
Heres my route for GET by ID:
/ GET by ID
exports.getIndividualDrink = (req, res) => {
let id = req.params.id;
// Show everything but id and v
Drink.findById(id).select('-_id -__v').then((drink) => {
// Check if theres that drink and ID is valid
if (!drink && !ObjectID.isValid(id)) {
return res.status(401).send();
}
// If there is, then send it back
res.send({
drink
});
}, (e) => {
res.status(400).send(e);
});
};
Expected should be passing, but like i said the results are:
1) POST: 'Error: expected 200, got 400'
2) First two GET by ID: 'Error: Timeout of 2000ms exceeded. ....'
3) Last GET by ID: 'Expected 404, got 400'
The 400 Bad Request error is an HTTP status code that means that the request you sent to the server, was somehow incorrect or corrupted and the server couldn't understand it.
Try to check your schema, you should post all required item if you miss something 400 is thrown.
I want to replace promises chain inside my Express routing with async/await. This makes code clean and more readable. First look at my code.
What i've had before:
app.post('/search', (req,res) => {
sendRequest(req.body).then( searchDetails => {
res.send(searchDetails);
}).catch( error => {
res.status(404).send(error)
});
});
Current code:
app.post('/search', asyncMiddleware(async (req,res) => {
const result = await sendRequest(req.body);
res.send(result);
}));
And this how looks asyncMiddleware:
const asyncMiddleware = checkedFunction => (req, res) => {
Promise
.resolve(
checkedFunction(req, res)
)
.catch( error => {
res.status(400).send(error)
});
};
The problem starts when I have routing which includes more than one error status.
app.delete('/delete/:id', authenticate, (req, res) => {
const id = req.params.id;
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
User.findOneAndDelete({
_id: id,
_user: req.user._id
}).then((todo) => {
if (!todo) {
return res.status(404).send();
}
res.send({todo});
}).catch((e) => {
res.status(400).send();
});
});
How can I make to asyncMiddleware will return status depends on error?
asyncMiddleware here checks if any error has occured or is deliberately thrown by checkedFunction, namely express route handler. If you would like to say something to asyncMiddleware, you need to wrap your route handler with it as you did for /search, then you need to throw specific errors/objects involving your error information:
app.delete('/delete/:id', authenticate, asyncMiddleware(async (req, res) => {
const id = req.params.id;
if (!ObjectID.isValid(id)) {
throw {
status: 404,
message: 'id not valid'
}
}
try {
const todo = await User.findOneAndDelete({
_id: id,
_user: req.user._id
});
if (!todo) {
throw {
status: 404,
message: 'todo not found'
}
}
res.send({todo});
} catch (e) {
throw {
status: 400,
message: 'mongodb error'
}
}
}));
then asyncMiddleware can send status in response
const asyncMiddleware = checkedFunction => (req, res) => {
Promise
.resolve(
checkedFunction(req, res)
)
.catch( error => {
res.status(error.status).send(error.message)
});
};
You can create built-in Error objects instead of custom ones to track error call stack but I don't think you need here.
I'm trying to send some data from a React form to my Express back end. To do this I'm using fetch where I'm trying to send some variable data from react. I'm console logging the data before running the fetch to see if it is there, console log can see the data.
My error states
[0] (node:2966) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'message' of undefined
So it seems like my Express back end can't see the variable data.
How I'm sending the data from react
handleSubmit = async e => {
e.preventDefault();
console.log("Submit was pressed!");
if (this.state.email === "") {
}
const { name } = this.state;
const query = this.state.query;
const subject = "kontakt fra nettside";
const message = { name, query };
console.log(message.name, message.text, "data is");
fetch(
"http://localhost:5000/api/email", variabler
{
method: "POST",
cache: "no-cache",
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true,
content_type: "application/json"
},
body: JSON.stringify(message, subject)
}
); //.then(response => response.json());
};
My file for retrieving the data from the front end in Express
const emailConfig = require("./emailConfig")();
const mailgun = require("mailgun-js")(emailConfig);
exports.sendEmail = (recipient, message, attachment) =>
new Promise((resolve, reject) => {
const data = {
from: "Test <test#test.no>", // Real email removed from this post
to: recipient,
subject: message.subject,
text: message.query,
inline: attachment,
html: message.html
};
mailgun.messages().send(data, error => {
if (error) {
return reject(error);
}
return resolve();
});
});
and sendMail.js
const express = require("express");
const sendMail = express.Router();
const emailUtil = require("./emailUtil");
const { sendEmail } = emailUtil;
sendMail.post("/", async (req, res, next) => {
// const { recipient, message } = req.body;
console.log("Request mottatt");
const recipient = "test#test.no";
const message = req.body.message;
try {
await sendEmail(recipient, message);
res.json({ message: "Your query has been sent" });
console.log("Message has been sent");
await next();
} catch (e) {
await next(e);
console.log("nah", e);
}
});
module.exports = sendMail;
I can't figure out where the error is, any ideas? :)