mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
feat(core): change listen to reject on server bind failures
pr update
This commit is contained in:
47
integration/nest-application/listen/e2e/express.spec.ts
Normal file
47
integration/nest-application/listen/e2e/express.spec.ts
Normal file
@@ -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
integration/nest-application/listen/e2e/fastify.spec.ts
Normal file
46
integration/nest-application/listen/e2e/fastify.spec.ts
Normal file
@@ -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
integration/nest-application/listen/src/app.controller.ts
Normal file
12
integration/nest-application/listen/src/app.controller.ts
Normal file
@@ -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
integration/nest-application/listen/src/app.module.ts
Normal file
9
integration/nest-application/listen/src/app.module.ts
Normal file
@@ -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
integration/nest-application/listen/src/app.service.ts
Normal file
8
integration/nest-application/listen/src/app.service.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
sayHello(): string {
|
||||
return 'Hello World!';
|
||||
}
|
||||
}
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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 =>
|
||||
@@ -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 =>
|
||||
|
||||
@@ -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', {
|
||||
@@ -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', {
|
||||
@@ -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', {});
|
||||
|
||||
@@ -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));
|
||||
@@ -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));
|
||||
@@ -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));
|
||||
|
||||
34237
package-lock.json
generated
34237
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -54,15 +54,6 @@ export interface INestApplication extends INestApplicationContext {
|
||||
*/
|
||||
getUrl(): Promise<string>;
|
||||
|
||||
/**
|
||||
* Starts the application (can be awaited).
|
||||
*
|
||||
* @param {number|string} port
|
||||
* @param {string} [hostname]
|
||||
* @returns {Promise}
|
||||
*/
|
||||
listenAsync(port: number | string, hostname?: string): Promise<any>;
|
||||
|
||||
/**
|
||||
* Registers a prefix for every HTTP route path.
|
||||
*
|
||||
|
||||
@@ -228,25 +228,26 @@ 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 => {
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -256,30 +257,33 @@ export class NestApplication
|
||||
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) {
|
||||
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;
|
||||
|
||||
@@ -11,7 +11,7 @@ async function bootstrap() {
|
||||
* transport: Transport.TCP,
|
||||
* options: { retryAttempts: 5, retryDelay: 3000 },
|
||||
* });
|
||||
* await app.listenAsync();
|
||||
* await app.listen();
|
||||
*
|
||||
*/
|
||||
const app = await NestFactory.create(AppModule);
|
||||
|
||||
@@ -15,7 +15,7 @@ async function bootstrap() {
|
||||
* protoPath: join(__dirname, './hero/hero.proto'),
|
||||
* }
|
||||
* });
|
||||
* await app.listenAsync();
|
||||
* await app.listen();
|
||||
*
|
||||
*/
|
||||
const app = await NestFactory.create(AppModule);
|
||||
|
||||
Reference in New Issue
Block a user