Add pubsub subscription to trigger webhook

This commit is contained in:
Hongbo Wu
2022-05-26 10:35:43 +08:00
parent c84668e6b0
commit 7b0ebb9dbf
2 changed files with 88 additions and 0 deletions

View File

@ -0,0 +1,86 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import express from 'express'
import { readPushSubscription } from '../../datalayer/pubsub'
import { getRepository } from '../../entity/utils'
import { Webhook } from '../../entity/webhook'
import axios, { Method } from 'axios'
export function webhooksServiceRouter() {
const router = express.Router()
router.post('/:action', async (req, res) => {
console.log('trigger webhook of action', req.params.action)
const { message: msgStr, expired } = readPushSubscription(req)
if (!msgStr) {
res.status(400).send('Bad Request')
return
}
if (expired) {
console.log('discarding expired message')
res.status(200).send('Expired')
return
}
try {
const data = JSON.parse(msgStr)
const { userId, type } = data
if (!userId || !type) {
console.log('No userId or type found in message')
res.status(400).send('Bad Request')
return
}
// example: PAGE_CREATED
const eventType = `${type as string}_${req.params.action}`.toUpperCase()
const webhooks = await getRepository(Webhook)
.createQueryBuilder()
.where('userId = :userId', { userId })
.andWhere(':eventType = ANY(eventTypes)', { eventType })
.andWhere('enabled = true')
.getMany()
if (webhooks.length <= 0) {
console.log(
'No active webhook found for user',
userId,
'and eventType',
eventType
)
res.status(200).send('No webhook found')
return
}
// trigger webhooks
for (const webhook of webhooks) {
const url = webhook.url
const method = webhook.method as Method
const body = JSON.stringify({
action: req.params.action,
userId,
[type]: data,
})
console.log('triggering webhook', url, method, body)
await axios.request({
url,
method,
headers: {
'Content-Type': webhook.contentType,
},
data: body,
})
}
res.status(200).send('OK')
} catch (err) {
console.log('trigger webhook failed', err)
res.status(500).send(err)
}
})
return router
}

View File

@ -42,6 +42,7 @@ import { corsConfig } from './utils/corsConfig'
import { initElasticsearch } from './elastic'
import { uploadServiceRouter } from './routers/svc/upload'
import rateLimit from 'express-rate-limit'
import { webhooksServiceRouter } from './routers/svc/webhooks'
const PORT = process.env.PORT || 4000
@ -111,6 +112,7 @@ export const createApp = (): {
app.use('/svc/pubsub/newsletters', newsletterServiceRouter())
app.use('/svc/pubsub/emails', emailsServiceRouter())
app.use('/svc/pubsub/upload', uploadServiceRouter())
app.use('/svc/pubsub/webhooks', webhooksServiceRouter())
app.use('/svc/reminders', remindersServiceRouter())
app.use('/svc/pdf-attachments', pdfAttachmentsRouter())