How to accept REST webhook in RedwoodJS?

(I’m a hobbyist, sorry if this is too basic)

My pet project will need to receive webhooks from 3rd party apps like zoom and slack.

How to accept a REST webhook in RedwoodJS?

  • since it’s rather backend and not a page I’ll put it in api/
    *`on the other hand it’s exposed on the web and i guess i need a route for it

Could someone give me a pointer?

Sure thing!

Remember that Redwood is focused on the JAMstack, so the web site is totally static and served from a CDN—there’s no server to handle webhooks or do any traditional “server” work.

However, any functions you create in the api side will be available to the internet. If you deploy to Netlify, then a function you create at api/src/functions/webhook.js will be available to the internet at https://mysite.netlify.com/.netlify/functions/webhook

Check out the Netlify Functions documentation for how to format those: https://docs.netlify.com/functions/build-with-javascript/#format Functions are deployed on AWS Lambda so they’re subject to all the limitations there (file size, total run time, etc). The simplest one you could create would look something like:

exports.handler = function(event, context, callback) {
  callback(null, {
    statusCode: 200,
    body: "Hello, World"
  });
}

You can have the function read/write from your database by importing the PrismaClient and then writing queries. Although it isn’t written as a function, check out api/prisma/seeds.js for an example of using PrismaClient from scratch, without the Redwood graphql helpers.

If you run into any issues let me know! I struggled for a while wrapping my head around learning serverless + React + graphQL + Prisma all simultaneously so I understand how hard it can be getting started. No question is too basic. :slight_smile:

8 Likes

Thanks, that’s what I needed and more!

Will report back here how it goes and can’t wait to turn back to the more “redwood” side when working in /api and /web

1 Like

I can’t find it in the docs now, but when working with Prisma it’s much easier to write your function handler as an async version rather than the callback version (callback version is in the code snippet above). The async version looks like:

exports.handler = async (event , context) => { 
  return { 
    statusCode: 200, 
    body : "Hello, world!" 
  }
}

Then you can do await and async with the PrismaClient calls and everything should work much smoother than trying to shoehorn everything into a callback function.

This seems to indeed be very simple: api/src/functions/hook.js:

const { PrismaClient } = require('@prisma/client')
const dotenv = require('dotenv')
dotenv.config()
const db = new PrismaClient()

exports.handler = async (event, context) => {
  await db.hookMessage.create({ data: { message: JSON.stringify(event) }})
  db.disconnect()   

  return {
    statusCode: 200,
    body: event,
  }
}

Only thing I’m not sure about is whether i need to close the db connection but i guess in a lambda it doesn’t really matter.

This works fine locally. I could not confirm whether it works with netlify yet. I have an error there, but not sure it’s really related to the hook + githubt is down.

1 Like

Looks good to me! Prisma does recommend that you disconnect when you’re done, just to be safe.

1 Like

Yup, without proper configuration an unclosed connection to your DB could be kept open & idle on the DB side for days, and even keep some locks active on some data or tables.

Nasty business ^^

Hi @janmechtel - I have an update for you that I hope you’ll like:

Documentation for webhooks in RedwoodJS introduced in v0.31 is now available.

Common signature verification methods are supported:

Hope this helps.

I deployed my project on Vercel but I don’t know where to get my webhook URL. Please how I can know my webhook URL if a save the webhook file in ‘…api/src/functions/’ ?

Let’s say you had a function in /api/src/functions/webhook/webhook.js then after you deployed the URL would be:

https://example.com/.redwood/functions/webhook.js

You can even pass some options to it via query string variables:

https://example.com/.redwood/functions/webhook.js?foo=bar

And then access them inside of the function in event.queryStringParameters:

export const handler = async (event) => {
  const { foo } = event.queryStringParameters

  console.info(foo)
}
1 Like