Skip to content

Commit

Permalink
Split session and proxy functionality for better API
Browse files Browse the repository at this point in the history
  • Loading branch information
projkov committed Aug 23, 2024
1 parent 219d897 commit fa0d08c
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 34 deletions.
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { RequestModule } from './modules/requests/request.module';
import { SessionModule } from './modules/sessions/session.module';
import { TestRunModule } from './modules/test_runs/testRun.module';
import { ConfigModule } from '@nestjs/config';
import { ProxyAppModule } from './modules/proxyapp/proxyapp.module';

@Module({
imports: [
Expand All @@ -24,6 +25,7 @@ import { ConfigModule } from '@nestjs/config';
SessionModule,
RequestModule,
TestRunModule,
ProxyAppModule,
],
})
export class AppModule {}
42 changes: 42 additions & 0 deletions src/modules/proxyapp/proxyapp.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { All, Controller, Param, Req, Res } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiParam } from '@nestjs/swagger';
import { createRequestObject } from 'src/utils/data';
import { captureResponseBody } from 'src/utils/responses';
import { RequestService } from '../requests/request.service';
import { SessionService } from '../sessions/session.service';
import { Request, Response } from 'express';

@ApiTags('app')
@Controller('app')
export class ProxyAppController {
// eslint-disable-next-line @typescript-eslint/ban-types
private sessionListeners = new Map<string, Function>();

constructor(
private readonly sessionService: SessionService,
private readonly requestService: RequestService,
) {}

@All(':id/**')
@ApiOperation({ summary: 'Proxy request to the target URL' })
@ApiParam({ name: 'id', description: 'Session ID' })
async proxyRequestGet(@Param('id') id: string, @Req() req: Request, @Res() res: Response) {
const session = await this.sessionService.findOne(id);
const proxyMiddleware = await this.sessionService.getProxyMiddleware(id);
const responsePromise = captureResponseBody(res);

// TODO: Implement the logic to manage listener
if (!this.sessionListeners.has(id)) {
const listener = async (req: Request, res: Response) => {
proxyMiddleware(req, res);
const responseBody = await responsePromise;
const target = await this.sessionService.getTarget(id);
await this.requestService.create(createRequestObject(id, target, session, req, res, responseBody));
};
this.sessionListeners.set(id, listener);
}

const listener = this.sessionListeners.get(id);
listener(req, res);
}
}
10 changes: 10 additions & 0 deletions src/modules/proxyapp/proxyapp.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { ProxyAppController } from './proxyapp.controller';
import { SessionModule } from '../sessions/session.module';
import { RequestModule } from '../requests/request.module';

@Module({
imports: [SessionModule, RequestModule],
controllers: [ProxyAppController],
})
export class ProxyAppModule {}
35 changes: 3 additions & 32 deletions src/modules/sessions/session.controller.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { Controller, Post, Body, Param, Req, Res, All } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiParam } from '@nestjs/swagger';
import { Controller, Post, Body } from '@nestjs/common';
import { ApiTags, ApiOperation } from '@nestjs/swagger';
import { SessionService } from './session.service';
import { CreateSessionDto } from './session.dto';
import { RequestService } from '../requests/request.service';
import { Request, Response } from 'express';
import { createRequestObject } from 'src/utils/data';
import { captureResponseBody } from 'src/utils/responses';

@ApiTags('sessions')
@Controller('sessions')
export class SessionController {
// eslint-disable-next-line @typescript-eslint/ban-types
private sessionListeners = new Map<string, Function>();

constructor(
private readonly sessionService: SessionService,
private readonly requestService: RequestService,
Expand All @@ -25,29 +19,6 @@ export class SessionController {
const backendUrl = process.env.BACKEND_URL || 'http://localhost:8080';
const sessionEntity = await this.sessionService.create(createSessionDto);

return { ...sessionEntity, baseUrl: `${backendUrl}/sessions/${sessionEntity.id}` };
}

@All(':id/**')
@ApiOperation({ summary: 'Proxy request to the target URL' })
@ApiParam({ name: 'id', description: 'Session ID' })
async proxyRequestGet(@Param('id') id: string, @Req() req: Request, @Res() res: Response) {
const session = await this.sessionService.findOne(id);
const proxyMiddleware = await this.sessionService.getProxyMiddleware(id);
const responsePromise = captureResponseBody(res);

// TODO: Implement the logic to manage listener
if (!this.sessionListeners.has(id)) {
const listener = async (req: Request, res: Response) => {
proxyMiddleware(req, res);
const responseBody = await responsePromise;
const target = await this.sessionService.getTarget(id);
await this.requestService.create(createRequestObject(id, target, session, req, res, responseBody));
};
this.sessionListeners.set(id, listener);
}

const listener = this.sessionListeners.get(id);
listener(req, res);
return { ...sessionEntity, baseUrl: `${backendUrl}/app/${sessionEntity.id}` };
}
}
2 changes: 1 addition & 1 deletion src/modules/sessions/session.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class SessionService {
return createProxyMiddleware({
target,
changeOrigin: true,
pathRewrite: { [`^/sessions/${id}`]: '' },
pathRewrite: { [`^/app/${id}`]: '' },
on: {
proxyReq: fixRequestBody,
},
Expand Down
2 changes: 1 addition & 1 deletion src/utils/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function createRequestObject(
res: Pick<Response, 'statusCode'>,
responseBody: string,
): CreateRequestDto {
const searchRequest = req.originalUrl.replace(`/sessions/${id}`, target);
const searchRequest = req.originalUrl.replace(`/app/${id}`, target);
const searchReqObj = parseSearchRequest(searchRequest);
return {
session: session,
Expand Down

0 comments on commit fa0d08c

Please sign in to comment.