Add more control on http trigger (#21216)
add "new Response" utils to define response code or content type of http route triggered logic function responses follow up of https://github.com/twentyhq/twenty/pull/21214 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+94
-34
@@ -2,23 +2,34 @@ import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Patch,
|
||||
Post,
|
||||
Put,
|
||||
Req,
|
||||
Res,
|
||||
UseFilters,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
|
||||
import { Request } from 'express';
|
||||
import { Request, Response } from 'express';
|
||||
import { HTTPMethod } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { PublicEndpointGuard } from 'src/engine/guards/public-endpoint.guard';
|
||||
import { RouteTriggerRestApiExceptionFilter } from 'src/engine/core-modules/logic-function/logic-function-trigger/triggers/route/exceptions/route-trigger-rest-api-exception-filter';
|
||||
import { RouteTriggerService } from 'src/engine/core-modules/logic-function/logic-function-trigger/triggers/route/route-trigger.service';
|
||||
import {
|
||||
RouteTriggerResponse,
|
||||
RouteTriggerService,
|
||||
} from 'src/engine/core-modules/logic-function/logic-function-trigger/triggers/route/route-trigger.service';
|
||||
|
||||
const ALLOWED_RESPONSE_HEADERS = new Set([
|
||||
'content-type',
|
||||
'content-language',
|
||||
'content-disposition',
|
||||
'cache-control',
|
||||
'retry-after',
|
||||
]);
|
||||
|
||||
@Controller('s')
|
||||
@UseGuards(PublicEndpointGuard, NoPermissionGuard)
|
||||
@@ -27,47 +38,96 @@ export class RouteTriggerController {
|
||||
constructor(private readonly routeTriggerService: RouteTriggerService) {}
|
||||
|
||||
@Get('*path')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async get(@Req() request: Request) {
|
||||
return await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.GET,
|
||||
});
|
||||
async get(@Req() request: Request, @Res() response: Response) {
|
||||
this.sendResponse(
|
||||
response,
|
||||
await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.GET,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@Post('*path')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async post(@Req() request: Request) {
|
||||
return await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.POST,
|
||||
});
|
||||
async post(@Req() request: Request, @Res() response: Response) {
|
||||
this.sendResponse(
|
||||
response,
|
||||
await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.POST,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@Put('*path')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async put(@Req() request: Request) {
|
||||
return await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.PUT,
|
||||
});
|
||||
async put(@Req() request: Request, @Res() response: Response) {
|
||||
this.sendResponse(
|
||||
response,
|
||||
await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.PUT,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@Patch('*path')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async patch(@Req() request: Request) {
|
||||
return await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.PATCH,
|
||||
});
|
||||
async patch(@Req() request: Request, @Res() response: Response) {
|
||||
this.sendResponse(
|
||||
response,
|
||||
await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.PATCH,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@Delete('*path')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async delete(@Req() request: Request) {
|
||||
return await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.DELETE,
|
||||
});
|
||||
async delete(@Req() request: Request, @Res() response: Response) {
|
||||
this.sendResponse(
|
||||
response,
|
||||
await this.routeTriggerService.handle({
|
||||
request,
|
||||
httpMethod: HTTPMethod.DELETE,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private sendResponse(
|
||||
response: Response,
|
||||
{ statusCode, headers, body }: RouteTriggerResponse,
|
||||
) {
|
||||
response.status(statusCode);
|
||||
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
if (ALLOWED_RESPONSE_HEADERS.has(key.toLowerCase())) {
|
||||
response.setHeader(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDefined(body)) {
|
||||
response.send();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const hasContentType = isDefined(response.getHeader('content-type'));
|
||||
|
||||
if (typeof body === 'string') {
|
||||
if (!hasContentType) {
|
||||
response.setHeader('content-type', 'text/plain');
|
||||
}
|
||||
|
||||
response.send(body);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasContentType) {
|
||||
response.send(JSON.stringify(body));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
response.json(body);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user