Skip to content

Commit

Permalink
fix(core): revert listen async and deprecate it
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec committed Jan 27, 2021
2 parents 275e71f + 4cc2d18 commit 58812f5
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 53 deletions.
47 changes: 47 additions & 0 deletions integration/nest-application/listen/e2e/express.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { ExpressAdapter } from '@nestjs/platform-express';
import { Test, TestingModule } from '@nestjs/testing';
import { expect } from 'chai';
import * as express from 'express';
import { AppModule } from '../src/app.module';
import { INestApplication } from '@nestjs/common';

describe('Listen (Express Application)', () => {
let testModule: TestingModule;
let app: INestApplication;

beforeEach(async () => {
testModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = testModule.createNestApplication(new ExpressAdapter(express()));
});

afterEach(async () => {
app.close();
});

it('should resolve with httpServer on success', async () => {
const response = await app.listen(3000);
expect(response).to.eql(app.getHttpServer());
});

it('should reject if the port is not available', async () => {
await app.listen(3000);
const secondApp = testModule.createNestApplication(
new ExpressAdapter(express()),
);
try {
await secondApp.listen(3000);
} catch (error) {
expect(error.code).to.equal('EADDRINUSE');
}
});

it('should reject if there is an invalid host', async () => {
try {
await app.listen(3000, '1');
} catch (error) {
expect(error.code).to.equal('EADDRNOTAVAIL');
}
});
});
46 changes: 46 additions & 0 deletions integration/nest-application/listen/e2e/fastify.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { FastifyAdapter } from '@nestjs/platform-fastify';
import { Test, TestingModule } from '@nestjs/testing';
import { expect } from 'chai';
import { AppModule } from '../src/app.module';
import { INestApplication } from '@nestjs/common';

describe('Listen (Fastify Application)', () => {
let testModule: TestingModule;
let app: INestApplication;

beforeEach(async () => {
testModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = testModule.createNestApplication(new FastifyAdapter());
});

afterEach(async () => {
app.close();
});

it('should resolve with httpServer on success', async () => {
const response = await app.listen(3000);
expect(response).to.eql(app.getHttpServer());
});

it('should reject if the port is not available', async () => {
await app.listen(3000);
const secondApp = testModule.createNestApplication(new FastifyAdapter());
try {
await secondApp.listen(3000);
} catch (error) {
expect(error.code).to.equal('EADDRINUSE');
}

await secondApp.close();
});

it('should reject if there is an invalid host', async () => {
try {
await app.listen(3000, '1');
} catch (error) {
expect(error.code).to.equal('EADDRNOTAVAIL');
}
});
});
12 changes: 12 additions & 0 deletions integration/nest-application/listen/src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}

@Get()
getHello(): string {
return this.appService.sayHello();
}
}
9 changes: 9 additions & 0 deletions integration/nest-application/listen/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
8 changes: 8 additions & 0 deletions integration/nest-application/listen/src/app.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
sayHello(): string {
return 'Hello World!';
}
}
2 changes: 1 addition & 1 deletion integration/websockets/e2e/error-gateway.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('ErrorGateway', () => {
providers: [ErrorGateway],
}).compile();
app = await testingModule.createNestApplication();
await app.listenAsync(3000);
await app.listen(3000);
});

it(`should handle error`, async () => {
Expand Down
4 changes: 2 additions & 2 deletions integration/websockets/e2e/gateway-ack.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('WebSocketGateway (ack)', () => {

it(`should handle message with ack (http)`, async () => {
app = await createNestApp(AckGateway);
await app.listenAsync(3000);
await app.listen(3000);

ws = io.connect('http://localhost:8080');
await new Promise<void>(resolve =>
Expand All @@ -30,7 +30,7 @@ describe('WebSocketGateway (ack)', () => {

it(`should handle message with ack & without data (http)`, async () => {
app = await createNestApp(AckGateway);
await app.listenAsync(3000);
await app.listen(3000);

ws = io.connect('http://localhost:8080');
await new Promise<void>(resolve =>
Expand Down
6 changes: 3 additions & 3 deletions integration/websockets/e2e/gateway.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('WebSocketGateway', () => {

it(`should handle message (2nd port)`, async () => {
app = await createNestApp(ApplicationGateway);
await app.listenAsync(3000);
await app.listen(3000);

ws = io.connect('http://localhost:8080');
ws.emit('push', {
Expand All @@ -35,7 +35,7 @@ describe('WebSocketGateway', () => {

it(`should handle message (http)`, async () => {
app = await createNestApp(ServerGateway);
await app.listenAsync(3000);
await app.listen(3000);

ws = io.connect('http://localhost:3000');
ws.emit('push', {
Expand All @@ -51,7 +51,7 @@ describe('WebSocketGateway', () => {

it(`should handle message (2 gateways)`, async () => {
app = await createNestApp(ApplicationGateway, NamespaceGateway);
await app.listenAsync(3000);
await app.listen(3000);

ws = io.connect('http://localhost:8080');
io.connect('http://localhost:8080/test').emit('push', {});
Expand Down
6 changes: 3 additions & 3 deletions integration/websockets/e2e/ws-gateway.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('WebSocketGateway (WsAdapter)', () => {

it(`should handle message (2nd port)`, async () => {
app = await createNestApp(ApplicationGateway);
await app.listenAsync(3000);
await app.listen(3000);

ws = new WebSocket('ws://localhost:8080');
await new Promise(resolve => ws.on('open', resolve));
Expand All @@ -44,7 +44,7 @@ describe('WebSocketGateway (WsAdapter)', () => {

it(`should handle message (http)`, async () => {
app = await createNestApp(ServerGateway);
await app.listenAsync(3000);
await app.listen(3000);

ws = new WebSocket('ws://localhost:3000');
await new Promise(resolve => ws.on('open', resolve));
Expand All @@ -69,7 +69,7 @@ describe('WebSocketGateway (WsAdapter)', () => {
this.retries(10);

app = await createNestApp(ApplicationGateway, CoreGateway);
await app.listenAsync(3000);
await app.listen(3000);

// open websockets delay
await new Promise(resolve => setTimeout(resolve, 1000));
Expand Down
15 changes: 8 additions & 7 deletions packages/common/interfaces/nest-application.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,23 @@ export interface INestApplication extends INestApplicationContext {
callback?: () => void,
): Promise<any>;

/**
* Returns the url the application is listening at, based on OS and IP version. Returns as an IP value either in IPv6 or IPv4
*
* @returns {Promise<string>} The IP where the server is listening
*/
getUrl(): Promise<string>;

/**
* Starts the application (can be awaited).
* @deprecated use "listen" instead.
*
* @param {number|string} port
* @param {string} [hostname]
* @returns {Promise}
*/
listenAsync(port: number | string, hostname?: string): Promise<any>;

/**
* Returns the url the application is listening at, based on OS and IP version. Returns as an IP value either in IPv6 or IPv4
*
* @returns {Promise<string>} The IP where the server is listening
*/
getUrl(): Promise<string>;

/**
* Registers a prefix for every HTTP route path.
*
Expand Down
85 changes: 48 additions & 37 deletions packages/core/nest-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,58 +235,69 @@ export class NestApplication
this.httpAdapter.enableCors(options);
}

public async listen(
port: number | string,
callback?: () => void,
): Promise<any>;
public async listen(
port: number | string,
hostname: string,
callback?: () => void,
): Promise<any>;
public async listen(port: number | string): Promise<any>;
public async listen(port: number | string, hostname: string): Promise<any>;
public async listen(port: number | string, ...args: any[]): Promise<any> {
!this.isInitialized && (await this.init());
this.isListening = true;
this.httpAdapter.listen(port, ...args);
return this.httpServer;
}

public listenAsync(port: number | string, hostname?: string): Promise<any> {
return new Promise(resolve => {
const server: any = this.listen(port, hostname, () => resolve(server));
return new Promise((resolve, reject) => {
const errorHandler = (e: any) => {
this.logger.error(e?.toString?.());
reject(e);
};
this.httpServer.once('error', errorHandler);

this.httpAdapter.listen(port, ...args, () => {
const address = this.httpServer.address();
if (address) {
this.httpServer.removeListener('error', errorHandler);
this.isListening = true;
resolve(this.httpServer);
}
});
});
}

public listenAsync(port: number | string, ...args: any[]): Promise<any> {
this.logger.warn(
'DEPRECATED! "listenAsync" method is deprecated and will be removed in the next major release. Please, use "listen" instead.',
);
return this.listen(port, ...(args as [any]));
}

public async getUrl(): Promise<string> {
return new Promise((resolve, reject) => {
if (!this.isListening) {
this.logger.error(MESSAGES.CALL_LISTEN_FIRST);
reject(MESSAGES.CALL_LISTEN_FIRST);
}
this.httpServer.on('listening', () => {
const address = this.httpServer.address();
if (typeof address === 'string') {
if (platform() === 'win32') {
return address;
}
const basePath = encodeURIComponent(address);
return `${this.getProtocol()}+unix://${basePath}`;
}
let host = this.host();
if (address && address.family === 'IPv6') {
if (host === '::') {
host = '[::1]';
} else {
host = `[${host}]`;
}
} else if (host === '0.0.0.0') {
host = '127.0.0.1';
}
resolve(`${this.getProtocol()}://${host}:${address.port}`);
});
const address = this.httpServer.address();
resolve(this.formatAddress(address));
});
}

private formatAddress(address: any): string {
if (typeof address === 'string') {
if (platform() === 'win32') {
return address;
}
const basePath = encodeURIComponent(address);
return `${this.getProtocol()}+unix://${basePath}`;
}
let host = this.host();
if (address && address.family === 'IPv6') {
if (host === '::') {
host = '[::1]';
} else {
host = `[${host}]`;
}
} else if (host === '0.0.0.0') {
host = '127.0.0.1';
}

return `${this.getProtocol()}://${host}:${address.port}`;
}

public setGlobalPrefix(prefix: string): this {
this.config.setGlobalPrefix(prefix);
return this;
Expand Down

0 comments on commit 58812f5

Please sign in to comment.