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!'); + } + +});