From 93cf9c2c561545e532bc6788e900fea8873056c5 Mon Sep 17 00:00:00 2001 From: David Mehren Date: Sat, 19 Sep 2020 14:51:12 +0200 Subject: [PATCH] NotesController: Use custom logic to access raw markdown NestJS does not support content-types other than application/json. Therefore we need to directly access the request object to get the raw body content. Signed-off-by: David Mehren --- package.json | 1 + src/api/public/notes/notes.controller.ts | 27 ++++++++++++++++++++++-- yarn.lock | 12 ++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 41bb7c760..8f7006537 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "class-transformer": "^0.2.3", "class-validator": "^0.12.2", "connect-typeorm": "^1.1.4", + "raw-body": "^2.4.1", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^6.5.4", diff --git a/src/api/public/notes/notes.controller.ts b/src/api/public/notes/notes.controller.ts index 7d64834ff..33d23bfd3 100644 --- a/src/api/public/notes/notes.controller.ts +++ b/src/api/public/notes/notes.controller.ts @@ -1,27 +1,50 @@ import { + BadRequestException, Body, Controller, Delete, Get, Header, + Logger, Param, Post, Put, + Req, } from '@nestjs/common'; +import { Request } from 'express'; +import * as getRawBody from 'raw-body'; import { NotePermissionsUpdateDto } from '../../../notes/note-permissions.dto'; import { NotesService } from '../../../notes/notes.service'; import { RevisionsService } from '../../../revisions/revisions.service'; @Controller('notes') export class NotesController { + private readonly logger = new Logger(NotesController.name); + constructor( private noteService: NotesService, private revisionsService: RevisionsService, ) {} + /** + * 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() - createNote(@Body() noteContent: string) { - return this.noteService.createNote(noteContent); + @Header('content-type', 'text/markdown') + 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.createNote(bodyText); + } else { + // TODO: Better error message + throw new BadRequestException('Invalid body'); + } } @Get(':noteIdOrAlias') diff --git a/yarn.lock b/yarn.lock index 1dd3417ae..bfe54b370 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3622,7 +3622,7 @@ http-errors@1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" -http-errors@~1.7.2: +http-errors@1.7.3, http-errors@~1.7.2: version "1.7.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== @@ -5944,6 +5944,16 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" + integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== + dependencies: + bytes "3.1.0" + http-errors "1.7.3" + iconv-lite "0.4.24" + unpipe "1.0.0" + rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"