Reputation: 639
I have a small Nest JS application where I am trying to develop a GET Rest API.
My Entity looks like:
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
@Entity({name: 'workingEnvs'})
export class WorkingEnvironment {
@PrimaryColumn({
name: 'id',
type: 'varchar',
length: 32,
default: "defaultId",
}) id: string;
@Column({
name: 'name',
type: 'varchar',
length: 32,
default: "workingEnv-420",
}) name: string;
@Column({
name: 'something',
type: 'varchar',
length: 32,
default: "practice",
}) something: string;
@Column({ default: true}) isAvailable: boolean;
}
My relevant portion controller looks like (the route):
@Get()
async getCollection(@Res() response) {
const wes = await this.weService.findAll();
return response.status(HttpStatus.OK).json({
wes,
});
}
And my service code looks like:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from "typeorm";
import { WorkingEnvironment } from './workingenv.entity';
@Injectable()
export class WorkingEnvService {
constructor(
@InjectRepository(WorkingEnvironment)
private weRepository: Repository<WorkingEnvironment>
) {}
// GET collection service
async findAll(): Promise<WorkingEnvironment[]> {
return await this.weRepository.find();
}
}
When I am calling the REST API with GET
:
The data I am getting (correct as I don't have any data):
{"wes":[]}
But my node Js app is crashing with this error:
node:internal/errors:463
ErrorCaptureStackTrace(err);
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:370:5)
at ServerResponse.setHeader (node:_http_outgoing:573:11)
at ServerResponse.header (C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\express\lib\response.js:771:10)
at ServerResponse.send (C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\express\lib\response.js:267:15)
at ExpressAdapter.reply (C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\@nestjs\platform-express\adapters\express-adapter.js:24:57)
at ExceptionsHandler.handleUnknownError (C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\@nestjs\core\exceptions\base-exception-filter.js:33:24)
at ExceptionsHandler.catch (C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\@nestjs\core\exceptions\base-exception-filter.js:17:25)
at ExceptionsHandler.next (C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\@nestjs\core\exceptions\exceptions-handler.js:16:20)
at C:\Users\pradipm\clients\CloudManager\cm_2\occm\service-infra\nest-services\node_modules\@nestjs\core\router\router-proxy.js:13:35 {
code: 'ERR_HTTP_HEADERS_SENT'
}
What I am missing here?
Further information:
This is how my app.module.ts looks like (relevant portion):
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3307,
username: 'root',
password: 'root',
database: 'workingenv',
entities: [WorkingEnvironment],
}),
WorkingEnvModule,
],
controllers: [PortableController],
providers: [PortableService, {
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
}],
And here is the APP_INTERCEPTOR
:
import { constants, utils } from "@app/common";
import { CallHandler, ExecutionContext, HttpException, Injectable, NestInterceptor } from "@nestjs/common";
import { Observable } from "rxjs";
import { catchError, tap } from 'rxjs/operators';
import { LoggerService } from "./logger.service";
const _ = require('lodash')
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
constructor(private logger: LoggerService) { }
now() {
const ts = process.hrtime()
return (ts[0] * 1e3) + (ts[1] / 1e6)
}
log(response: any, context: ExecutionContext, startTime: number, isError: Boolean = false) {
const req = context.switchToHttp().getRequest();
const { method, url, body } = req;
let statusCode = context.switchToHttp().getResponse().statusCode
if(isError && response instanceof HttpException) {
statusCode = response.getStatus();
}
const endTime = this.now()
if(!_.includes(url, 'health')) {
const requestId = req.headers[constants.requestIdHeaderName]
this.logger.access(
`\t${requestId}\t${statusCode}\t${method}\t${url}\t${endTime - startTime}\t${req.user?.sub}\t${JSON.stringify(utils.scrub(body))}\t${JSON.stringify(utils.scrub(response))}`,
);
}
}
public intercept(context: ExecutionContext, call$: CallHandler): Observable<unknown> {
const startTime = this.now()
return call$.handle().pipe(
tap({
next: (val: unknown): void => {
this.log(val, context, startTime);
},
error: (err: Error): void => {
this.log(err, context, startTime, true);
},
}),
catchError(err => {
throw err
})
);
}
}
Upvotes: 1
Views: 1579
Reputation: 190
just return your services response:
return this.weService.findAll();
or remove return
response.status(HttpStatus.OK).json(JSON.stringify(wes));
Upvotes: 2