0

I have an application in NestJS using Fastify. I want to set a the Content-Type to application/hal+json in my responses. I have the following code in a NestJS interceptor:

@Injectable()
export class SampleInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {

    context.switchToHttp().getResponse()
      .header('Content-Type', 'application/hal+json; charset=utf-8');

    return next.handle().pipe(
      map((data) => {
        const serializer = MyCustomSerializer();
        return serializer.serialize(data);
      })
    );
  }
}

However, I have the following error because I defined the Content-Type:

FastifyError [FST_ERR_REP_INVALID_PAYLOAD_TYPE]: FST_ERR_REP_INVALID_PAYLOAD_TYPE: Attempted to send payload of invalid type 'object'. Expected a string or Buffer.
    at onSendEnd (/home/user/Projects/nestjs-fastify-sample/node_modules/fastify/lib/reply.js:363:11)
    at onSendHook (/home/user/Projects/nestjs-fastify-sample/node_modules/fastify/lib/reply.js:325:5)
    at _Reply.Reply.send (/home/user/Projects/nestjs-fastify-sample/node_modules/fastify/lib/reply.js:151:3)
    at FastifyAdapter.reply (/home/user/Projects/nestjs-fastify-sample/node_modules/@nestjs/platform-fastify/adapters/fastify-adapter.js:37:25)
    at RouterResponseController.apply (/home/user/Projects/nestjs-fastify-sample/node_modules/@nestjs/core/router/router-response-controller.js:10:36)
    at /home/user/Projects/nestjs-fastify-sample/node_modules/@nestjs/core/router/router-execution-context.js:163:48
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
    at async /home/user/Projects/nestjs-fastify-sample/node_modules/@nestjs/core/router/router-execution-context.js:46:13
    at async Object.<anonymous> (/home/user/Projects/nestjs-fastify-sample/node_modules/@nestjs/core/router/router-proxy.js:8:17)

After some investigation, I noticed that if I do not define the Content-Type, the payload is a string representation of my JSON response. If not, the payload is an object. This happens because this code in fastify never runs and never serializes the payload as string.

Here is a repository for you to easily replicate the issue.

Is there a way to solve this issue?

saulotoledo
  • 1,737
  • 3
  • 19
  • 36

1 Answers1

1

To my understanding, so long as what you return from the interceptor is a string, Nest (and Fastify) will treat it like a string and return it however you want. I have an example where I'm returning an XML string so long as an incoming accept header is setup to ask for XML data back (content negotiation) and Fastify is returning it just fine, so as long as you strinigfy whatever your serializer returns, you shouldn't have a problem with a custom (different) header

Jay McDoniel
  • 57,339
  • 7
  • 135
  • 147
  • Hi. Thanks for your time. Unfortunately that does not work if you change the Content-Type while using Fastify. I added a replication package to my answer. You can clone the repository and run the application according to the Readme. – saulotoledo May 31 '20 at 12:44
  • I'm going to point out my first sentence **so long as what you return from the interceptor is a string** Nest and Fastify will not do any data processing and allow you to return whatever you want. This is how I got it to return XML without a problem. If you change `return data` to `return JSON.stringify(data)` I guarantee it will return what you expect without errors. – Jay McDoniel May 31 '20 at 15:23
  • Thank you! You're right. I didn't understand your argument before. – saulotoledo May 31 '20 at 19:24