feat(events-backend,events-node): improve parser interface

Signed-off-by: Rogerio Angeliski <angeliski@hotmail.com>
This commit is contained in:
Rogerio Angeliski
2025-02-26 20:18:14 -03:00
parent 144661b05f
commit cf75bca4f3
7 changed files with 58 additions and 7 deletions
@@ -209,7 +209,7 @@ describe('HttpPostIngressEventPublisher', () => {
expect.objectContaining({
error: {
message:
'Unsupported media type: text/plain. You need to provide a custom body parser for this media type using events extension.',
'Unsupported media type: text/plain. You need to provide a custom body parser for this media type using the EventsExtensionPoint.',
name: 'UnsupportedMediaTypeError',
statusCode: 415,
},
@@ -259,6 +259,47 @@ describe('HttpPostIngressEventPublisher', () => {
expect(response.status).toBe(202);
});
it('with a invalid media type', async () => {
const config = new ConfigReader({
events: {
http: {
topics: ['testA'],
},
},
});
const router = Router();
const app = express().use(router);
const events = new TestEventsService();
const publisher = HttpPostIngressEventPublisher.fromConfig({
config,
events,
logger,
});
publisher.bind(router);
router.use(middleware.error());
const response = await request(app)
.post('/http/testA')
.type('not-valid-content/plain')
.timeout(1000)
.send('Textual information');
expect(response.status).toBe(415);
expect(response.body).toEqual(
expect.objectContaining({
error: {
message:
'Unsupported media type: not-valid-content/plain. You need to provide a custom body parser for this media type using the EventsExtensionPoint.',
name: 'UnsupportedMediaTypeError',
statusCode: 415,
},
request: { method: 'POST', url: '/http/testA' },
response: { statusCode: 415 },
}),
);
});
it('with a custom application/json body parser implementation', async () => {
const config = new ConfigReader({
events: {
@@ -273,7 +314,11 @@ describe('HttpPostIngressEventPublisher', () => {
const events = new TestEventsService();
const customParse = jest.fn();
const bodyParser: HttpBodyParser = async (req, _topic) => {
const bodyParser: HttpBodyParser = async (
req,
_parsedMediaType,
_topic,
) => {
customParse();
return {
bodyParsed: JSON.parse(req.body.toString('utf-8')),
@@ -103,7 +103,7 @@ export class HttpPostIngressEventPublisher {
router.post(path, async (request, response) => {
const requestContentType = contentType.parse(request);
const bodyParser = this.bodyParsers[requestContentType.type];
const bodyParser = this.bodyParsers[requestContentType.type ?? ''];
if (!bodyParser) {
throw new UnsupportedMediaTypeError(requestContentType.type);
@@ -111,6 +111,7 @@ export class HttpPostIngressEventPublisher {
const { bodyParsed, bodyBuffer, encoding } = await bodyParser(
request,
requestContentType,
topic,
);
@@ -14,11 +14,11 @@
* limitations under the License.
*/
import { HttpBodyParser } from '@backstage/plugin-events-node';
import contentType from 'content-type';
import { UnsupportedCharsetError } from '../errors';
export const HttpApplicationJsonBodyParser: HttpBodyParser = async (
request,
parsedMediaType,
topic,
) => {
const requestBody = request.body;
@@ -29,16 +29,15 @@ export const HttpApplicationJsonBodyParser: HttpBodyParser = async (
}
const bodyBuffer: Buffer = requestBody;
const parsedContentType = contentType.parse(request);
const encoding = parsedContentType.parameters.charset ?? 'utf-8';
const encoding = parsedMediaType.parameters.charset ?? 'utf-8';
if (!Buffer.isEncoding(encoding)) {
throw new UnsupportedCharsetError(encoding);
}
const bodyString = bodyBuffer.toString(encoding);
const bodyParsed =
parsedContentType.type === 'application/json'
parsedMediaType.type === 'application/json'
? JSON.parse(bodyString)
: bodyString;
return { bodyParsed, bodyBuffer, encoding };