Reputation: 187
I'm building an express api with node.js. I'd like to send an email after a user creates an account. I've tried a couple of ways of doing that, but they don't seem to fit my needs, here's some pseudo code:
1. Pass the function that sends the email "at the end" of the route. Basically, just call the function that sends the email at the end of the route that creates the user account:
app.post("/users", (req, res) => {
const { email, password } = req.body;
// create user...
sendEmailTo(email);
}
My concern with this approach is that the /POST users route is now no longer only for creating a user, but every time it creates one it also sends an email, which may be bad for future use cases where we'd like to create a user separately from the user signup form.
2. Have a unique route specifically for sending emails. In this case, we'd have to make two request to the api, one for creating a user, and another one for sending the email:
app.post("/send", (req, res) => {
const { recipientEmail } = req.body;
sendEmailTo(recipientEmail);
}
What I don't like about this approach is that my api is not an "email" api, I'd like to leave it free for all users to explore and use, I don't want users to just be able to send emails in behalf of the api by requesting this route.
I'm sure there must be other ways of doing this like using some type of callbacks or queues, yet I have found nothing researching for hours, everything is basically a rehearsal of the two options above. Taking into account the need for separation of concerns, how would you go on about sending an email after a request? do I only have these two options?
Upvotes: 0
Views: 1284
Reputation: 3020
As I mentioned in the comments, you could just split your route handler in more fine-grained middlewares that would be reusable across all of your routes.
A route-level middleware is very similar to a route handler, except for the fact that instead of producing a response, it actually just does some more focused job and then forwards the request currently being processed to the next middleware or route handler in line. It does this with the extra next
function parameter that is injected by express.
In your scenario, you could do something like this:
app.post(
"/users",
createUser,
sendEmail,
send201Response
)
async function createUser(req, res, next) {
// Create user...
next();
}
async function sendEmail(req, res, next) {
// Send email...
next();
}
function send201Response(req, res) {
res.sendStatus(201);
}
Then if another use case happens to involve creating a user in a similar way for instance, you could do:
app.post(
"/otherendpoint",
createUser,
// Add other middleware/route handlers...
)
Upvotes: 1
Reputation: 696
If you are concerned with people using the "/send" route, then you probably want the first option. In the future if you want to create a user but not send an email, then you can just add conditionals to not send the email in certain cases. For example, you could add another property to the body in order to determine if the email should be sent.
app.post("/users", (req, res) => {
const { email, password, sendEmail } = req.body;
// create user...
if(sendEmail === true) sendEmailTo(email);
}
Upvotes: 1