Skip to content

Commit

Permalink
Merge pull request #10545 from jmcdo29/feat/websocket-get-pattern
Browse files Browse the repository at this point in the history
feat: create method on client to get websocket pattern
  • Loading branch information
kamilmysliwiec committed Jun 12, 2023
2 parents 8dcaef7 + ff9a577 commit 5481a01
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 2 deletions.
16 changes: 16 additions & 0 deletions integration/websockets/e2e/gateway.spec.ts
Expand Up @@ -66,5 +66,21 @@ describe('WebSocketGateway', () => {
);
});

it(`should be able to get the pattern in an interceptor`, async () => {
app = await createNestApp(ApplicationGateway);
await app.listen(3000);

ws = io('http://localhost:8080');
ws.emit('getClient', {
test: 'test',
});
await new Promise<void>(resolve =>
ws.on('popClient', data => {
expect(data.path).to.be.eql('getClient');
resolve();
}),
);
});

afterEach(() => app.close());
});
24 changes: 24 additions & 0 deletions integration/websockets/e2e/ws-gateway.spec.ts
Expand Up @@ -194,6 +194,30 @@ describe('WebSocketGateway (WsAdapter)', () => {
});
});

it('should let the execution context have a getPattern() method on getClient()', async () => {
app = await createNestApp(ApplicationGateway);
await app.listen(3000);

ws = new WebSocket('ws://localhost:8080');
await new Promise(resolve => ws.on('open', resolve));

ws.send(
JSON.stringify({
event: 'getClient',
data: {
test: 'test',
},
}),
);
await new Promise<void>(resolve =>
ws.on('message', data => {
expect(JSON.parse(data).data.path).to.be.eql('getClient');
ws.close();
resolve();
}),
);
});

afterEach(async function () {
await app.close();
});
Expand Down
11 changes: 11 additions & 0 deletions integration/websockets/src/app.gateway.ts
@@ -1,8 +1,10 @@
import { UseInterceptors } from '@nestjs/common';
import {
MessageBody,
SubscribeMessage,
WebSocketGateway,
} from '@nestjs/websockets';
import { RequestInterceptor } from './request.interceptor';

@WebSocketGateway(8080)
export class ApplicationGateway {
Expand All @@ -13,4 +15,13 @@ export class ApplicationGateway {
data,
};
}

@UseInterceptors(RequestInterceptor)
@SubscribeMessage('getClient')
getPathCalled(client, data) {
return {
event: 'popClient',
data: { ...data, path: client.pattern },
};
}
}
11 changes: 11 additions & 0 deletions integration/websockets/src/request.interceptor.ts
@@ -0,0 +1,11 @@
import { CallHandler, ExecutionContext, Injectable } from '@nestjs/common';

@Injectable()
export class RequestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
const client = context.switchToWs().getClient();
const pattern = context.switchToWs().getPattern();
client.pattern = pattern;
return next.handle();
}
}
11 changes: 11 additions & 0 deletions integration/websockets/src/server.gateway.ts
@@ -1,4 +1,6 @@
import { UseInterceptors } from '@nestjs/common';
import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';
import { RequestInterceptor } from './request.interceptor';

@WebSocketGateway()
export class ServerGateway {
Expand All @@ -9,4 +11,13 @@ export class ServerGateway {
data,
};
}

@UseInterceptors(RequestInterceptor)
@SubscribeMessage('getClient')
getPathCalled(client, data) {
return {
event: 'popClient',
data: { ...data, path: client.pattern },
};
}
}
Expand Up @@ -31,6 +31,10 @@ export interface WsArgumentsHost {
* Returns the client object.
*/
getClient<T = any>(): T;
/**
* Returns the pattern for the event
*/
getPattern(): string;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/core/helpers/execution-context-host.ts
Expand Up @@ -59,6 +59,7 @@ export class ExecutionContextHost implements ExecutionContext {
return Object.assign(this, {
getClient: () => this.getArgByIndex(0),
getData: () => this.getArgByIndex(1),
getPattern: () => this.getArgByIndex(this.getArgs().length - 1),
});
}
}
9 changes: 7 additions & 2 deletions packages/websockets/context/ws-context-creator.ts
Expand Up @@ -23,7 +23,7 @@ import {
InterceptorsContextCreator,
} from '@nestjs/core/interceptors';
import { PipesConsumer, PipesContextCreator } from '@nestjs/core/pipes';
import { PARAM_ARGS_METADATA } from '../constants';
import { MESSAGE_METADATA, PARAM_ARGS_METADATA } from '../constants';
import { WsException } from '../errors/ws-exception';
import { WsParamsFactory } from '../factories/ws-params-factory';
import { ExceptionFiltersContext } from './exception-filters-context';
Expand Down Expand Up @@ -66,7 +66,6 @@ export class WsContextCreator {
methodName,
contextType,
);

const exceptionHandler = this.exceptionFiltersContext.create(
instance,
callback,
Expand Down Expand Up @@ -110,6 +109,8 @@ export class WsContextCreator {
};

return this.wsProxy.create(async (...args: unknown[]) => {
args.push(this.reflectCallbackPattern(callback));

const initialArgs = this.contextUtils.createNullArray(argsLength);
fnCanActivate && (await fnCanActivate(args));

Expand All @@ -131,6 +132,10 @@ export class WsContextCreator {
return Reflect.getMetadata(PARAMTYPES_METADATA, instance, callback.name);
}

public reflectCallbackPattern(callback: (...args: any[]) => any): string {
return Reflect.getMetadata(MESSAGE_METADATA, callback);
}

public createGuardsFn<TContext extends string = ContextType>(
guards: any[],
instance: Controller,
Expand Down

0 comments on commit 5481a01

Please sign in to comment.