@yourrentals/cloudevent-receiver-nestjs
v0.7.2
Published
This library defines a plugin for NestJS to receive messages from the message bus.
Downloads
215
Keywords
Readme
@yourrentals/cloudevent-receiver-nestjs
This library defines a plugin for NestJS to receive messages from the message bus.
Installation
yarn add @yourrentals/cloudevent-receiver-nestjs @golevelup/nestjs-discovery
Usage
This plugin requires NestJS Raw Body parsing for signature verification, and CloudEvent Body Parser for CloudEvent parsing (in structured mode)
import { NestFactory } from '@nestjs/core';
import type { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from './app.module';
// in the "bootstrap" function
const app = await NestFactory.create<NestExpressApplication>(AppModule, {
rawBody: true,
});
// Support CloudEvent - Structured mode parsing
app.useBodyParser('json', {
type: 'application/cloudevents+json',
});
await app.listen(3000);
import {
CloudEventReceiverModule,
EventHandler,
WebhookSignatureV1HmacPlugin,
CloudEvent
} from '@yourrentals/cloudevent-receiver-nestjs'
@Injectable()
class MessagebusHandlerService {
@EventHandler('my-queue')
async handleMyQueue(event: CloudEvent) {
// ...
}
@EventHandler('my-other-queue', false /* event is not CloudEvent */)
async handleSqsQueue(event: Message) {
// ...
}
}
@Module({
imports: [
CloudEventReceiverModule.forRoot({
pathPrefix: '/message-bus',
verifierPlugins: [new WebhookSignatureV1HmacPlugin('secret')],
}),
],
providers: [MessagebusHandlerService],
})
import Axios from 'axios';
const main = async () => {
// Queue name defined in the receiver are automatically registered
await Axios.post('http://localhost:3000/message-bus/my-queue', {
headers: {
'ce-specversion': '1.0',
'ce-type': 'my-event',
'ce-source': 'my-source',
'ce-id': 'my-id',
'ce-time': '2020-01-01T00:00:00Z',
'ce-datacontenttype': 'application/json',
'ce-dataschema': 'http://myschema.com',
'ce-subject': 'my-subject',
'ce-signature': 'my-signature',
},
body: {
foo: 'bar',
},
});
};
Authentication
NestJS usually have global authentication that will impede operations of this module, as the routes are considered public route. To disable authentication for the routes, you can use the routeDecorator
module option:
import { Module, SetMetadata } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import {
CloudEventReceiverModule,
WebhookSignatureV1HmacPlugin,
} from '@yourrentals/cloudevent-receiver-nestjs';
import { APP_GUARD } from '@nestjs/core';
import { AuthGuardGuard } from './auth-guard/auth-guard.guard';
@Module({
imports: [
CloudEventReceiverModule.forRoot({
// Set the route decorator so that your authentication guard will treat the route as public
routeDecorator: SetMetadata('isPublic', true),
verifierPlugins: [new WebhookSignatureV1HmacPlugin('secret2')],
}),
],
controllers: [AppController],
providers: [AppService, { provide: APP_GUARD, useClass: AuthGuardGuard }],
})
export class AppModule {}
Raw Mode
The library can receive messages from any sources so long that it implements the Webhook Signature.
To disable parsing as cloudevent, set the isCloudEvent
option in decorator to false
.
By default, the event type is assumed to be a SQS Message
import { Injectable } from '@nestjs/common';
import {
EventHandler,
SqsMessage,
} from '@yourrentals/cloudevent-receiver-nestjs';
@Injectable()
export class AppService {
@EventHandler('test', /* isCloudEvent */ false)
async handle(event: SqsMessage) {
console.log(event);
}
}
Errors
The library defines the following errors:
| Error | Description | Expected HTTP status code | Retryable | |------------------------|-----------------------------------------|---------------------------|-----------| | InvalidSignatureError | The signature of the message is invalid | 401 | No | | UnparsableMessageError | The message is not a valid CloudEvent | 400 | No | | NotFoundError | The queue name is not registered | 404 | Yes | | ConflictError | The queue name is already registered | 409 | Yes | | TooManyRequestsError | The queue is currently busy | 429 | Yes | | ClientError | Any other client error | 400 | No | | ServerError | Any other server error | 500 | Yes |