thiagobustamante / typescript-rest

This is a lightweight annotation-based expressjs extension for typescript.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to accept text/plain body ?

msieurtoph opened this issue · comments

Hi,

First of all, thanks a lot for your awesome module.
It helped me to quickly setup a rest server without dealing with too much middlewares options and stuffs! It's really great.

But I have a problem I do not know how to solve.
I have to expose a resource which has to accept plain text body (as a CSV content for example) :

POST /myResource
Content-Type: text/plain
cache-control: no-cache

1;2;3;4;
5;6;7;8;
9;10;11;12;

I tried to deal with a @BodyOptions({type: 'text/plain'}), but the engine tries to JSON.parse the body anyway (and fail doing it, of course).
I do not know how to deactive this parsing and get the raw data in req.body property.

Can you help me please ?
I am pretty sure that @BodyOptions is the solution, but I cannot figure how to make it work.

Thanks in advance.

Hi @msieurtoph

I am still investigating this problem, but I think it should work. Are you setting the content-type header correctly for your request?

Hi @thiagobustamante

Thanks for investigating.

I am using Postman to execute my rest requests. This is the request that I'm trying to pass (I turned it to a PUT but the result still the same) :

curl -X PUT \
  http://localhost:8081/rest/reports/foo \
  -H 'Content-Type: text/plain' \
  -H 'Postman-Token: 3bee7473-fbfb-4e7c-b0ad-6512ab4325d5' \
  -H 'cache-control: no-cache' \
  -d '1;2;3;4;
5;6;7;8;
9;10;11;12;'

Here is the code I use :

@Path('/rest/reports')
export class ReportsResources {

  @Path(':key')
  @PUT
  @BodyOptions({type: 'text/plain'})
  async put_(
    @ContextRequest req: express.Request,
    @PathParam('key') key: string,
    data: any,
  ): Promise<any> {
    debug('=====================>');
    debug(`PUT /reports/${key}`, data);
    // ... some other stuffs, returning the res object ...
    debug('<---------------------');
    return res;
  }

}

And the result :

{ SyntaxError: Unexpected token 1 in JSON at position 0
    at JSON.parse (<anonymous>)
    at createStrictSyntaxError (C:\xxxxxxxxxxxx\node_modules\body-parser\lib\types\json.js:158:10)
    at parse (C:\xxxxxxxxxxxx\node_modules\body-parser\lib\types\json.js:83:15)
    at C:\xxxxxxxxxxxx\node_modules\body-parser\lib\read.js:121:18
    at invokeCallback (C:\xxxxxxxxxxxx\node_modules\raw-body\index.js:224:16)
    at done (C:\xxxxxxxxxxxx\node_modules\raw-body\index.js:213:7)
    at IncomingMessage.onEnd (C:\xxxxxxxxxxxx\node_modules\raw-body\index.js:273:7)
    at IncomingMessage.emit (events.js:194:15)
    at IncomingMessage.EventEmitter.emit (domain.js:441:20)
    at endReadableNT (_stream_readable.js:1125:12)
  expose: true,
  statusCode: 400,
  status: 400,
  body: '1;2;3;4;\n5;6;7;8;\n9;10;11;12;',
  type: 'entity.parse.failed' }

I hope it could help.

By the way, it could be really nice to have a @Raw decorator (for classes and methods) that deactives JSON parsing and set the raw body in the data parameter.

Hi @msieurtoph ,
It is fixed and available in 2.1.0 version.

I implemented also something to support your other use case (Raw bodies).

Take a look at this examples.

Before that change, we were supporting only two parsers for body (body-parser.json and body-parser.urlencoded).

That change add support for the other types of parsers available in the body-parser library.

Hi @thiagobustamante,

Sorry for my late answer.

I did not test all cases, but @BodyType(ParserType.text) and @BodyOptions({ type: 'text/csv' }) work like a charm!

Thank you very much for this fix and also for all of your work on this module.