From 258dd1db568da7923baf89f6fd13c5a33360fa89 Mon Sep 17 00:00:00 2001 From: Yannick Bungers Date: Sun, 27 Sep 2020 16:16:07 +0200 Subject: [PATCH] Added markdownbody-decorator which puts the markdown text directly to a variable in the route function. Content-type of the http request is checked to be text/markdown because we dealing with markdown. Technically by now there can be any content which can be encoded. There could be features in the software which do not work properly if the text can't be parsed as markdown. Signed-off-by: Yannick Bungers --- src/api/public/notes/notes.controller.ts | 57 +++++------------------- src/api/utils/markdownbody-decorator.ts | 31 +++++++++++++ 2 files changed, 42 insertions(+), 46 deletions(-) create mode 100644 src/api/utils/markdownbody-decorator.ts diff --git a/src/api/public/notes/notes.controller.ts b/src/api/public/notes/notes.controller.ts index 59e21ac39..fc3c7690e 100644 --- a/src/api/public/notes/notes.controller.ts +++ b/src/api/public/notes/notes.controller.ts @@ -1,5 +1,4 @@ import { - BadRequestException, Body, Controller, Delete, @@ -8,14 +7,12 @@ import { Param, Post, Put, - Req, } from '@nestjs/common'; -import { Request } from 'express'; -import * as getRawBody from 'raw-body'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { NotePermissionsUpdateDto } from '../../../notes/note-permissions.dto'; import { NotesService } from '../../../notes/notes.service'; import { RevisionsService } from '../../../revisions/revisions.service'; +import { MarkdownBody } from '../../utils/markdownbody-decorator'; @Controller('notes') export class NotesController { @@ -24,27 +21,13 @@ export class NotesController { private noteService: NotesService, private revisionsService: RevisionsService, ) { - this.logger.setContext(NotesController.name); + this.logger.setContext(NotesController.name); } - /** - * Extract the raw markdown from the request body and create a new note with it - * - * Implementation inspired by https://stackoverflow.com/questions/52283713/how-do-i-pass-plain-text-as-my-request-body-using-nestjs - */ @Post() - async createNote(@Req() req: Request) { - // we have to check req.readable because of raw-body issue #57 - // https://github.com/stream-utils/raw-body/issues/57 - if (req.readable) { - let bodyText: string = await getRawBody(req, 'utf-8'); - bodyText = bodyText.trim(); - this.logger.debug('Got raw markdown:\n' + bodyText); - return this.noteService.createNoteDto(bodyText); - } else { - // TODO: Better error message - throw new BadRequestException('Invalid body'); - } + async createNote(@MarkdownBody() text: string) { + this.logger.debug('Got raw markdown:\n' + text); + return this.noteService.createNoteDto(text); } @Get(':noteIdOrAlias') @@ -55,19 +38,10 @@ export class NotesController { @Post(':noteAlias') async createNamedNote( @Param('noteAlias') noteAlias: string, - @Req() req: Request, + @MarkdownBody() text: string, ) { - // we have to check req.readable because of raw-body issue #57 - // https://github.com/stream-utils/raw-body/issues/57 - if (req.readable) { - let bodyText: string = await getRawBody(req, 'utf-8'); - bodyText = bodyText.trim(); - this.logger.debug('Got raw markdown:\n' + bodyText); - return this.noteService.createNoteDto(bodyText, noteAlias); - } else { - // TODO: Better error message - throw new BadRequestException('Invalid body'); - } + this.logger.debug('Got raw markdown:\n' + text); + return this.noteService.createNoteDto(text, noteAlias); } @Delete(':noteIdOrAlias') @@ -81,19 +55,10 @@ export class NotesController { @Put(':noteIdOrAlias') async updateNote( @Param('noteIdOrAlias') noteIdOrAlias: string, - @Req() req: Request, + @MarkdownBody() text: string, ) { - // we have to check req.readable because of raw-body issue #57 - // https://github.com/stream-utils/raw-body/issues/57 - if (req.readable) { - let bodyText: string = await getRawBody(req, 'utf-8'); - bodyText = bodyText.trim(); - this.logger.debug('Got raw markdown:\n' + bodyText); - return this.noteService.updateNoteByIdOrAlias(noteIdOrAlias, bodyText); - } else { - // TODO: Better error message - throw new BadRequestException('Invalid body'); - } + this.logger.debug('Got raw markdown:\n' + text); + return this.noteService.updateNoteByIdOrAlias(noteIdOrAlias, text); } @Get(':noteIdOrAlias/content') diff --git a/src/api/utils/markdownbody-decorator.ts b/src/api/utils/markdownbody-decorator.ts new file mode 100644 index 000000000..a51eaeba3 --- /dev/null +++ b/src/api/utils/markdownbody-decorator.ts @@ -0,0 +1,31 @@ +import { + BadRequestException, + createParamDecorator, + ExecutionContext, + InternalServerErrorException, +} from '@nestjs/common'; +import * as getRawBody from 'raw-body'; + +/** + * Extract the raw markdown from the request body and create a new note with it + * + * Implementation inspired by https://stackoverflow.com/questions/52283713/how-do-i-pass-plain-text-as-my-request-body-using-nestjs + */ +export const MarkdownBody = createParamDecorator(async (_, context: ExecutionContext) => { + // we have to check req.readable because of raw-body issue #57 + // https://github.com/stream-utils/raw-body/issues/57 + const req = context.switchToHttp().getRequest(); + // Here the Content-Type of the http request is checked to be text/markdown + // because we dealing with markdown. Technically by now there can be any content which can be encoded. + // There could be features in the software which do not work properly if the text can't be parsed as markdown. + if (req.get('Content-Type') === 'text/markdown') { + if (req.readable) { + return (await getRawBody(req)).toString().trim(); + } else { + throw new InternalServerErrorException('Failed to parse request body!'); + } + } else { + throw new BadRequestException('Body Content-Type has to be text/markdown!'); + } + +});