Skip to content

Commit

Permalink
feat(common): Servers utility class
Browse files Browse the repository at this point in the history
Useful when working with HTTP servers especially for
test case authoring where there's a lot of server
creation for the purpose of allocating random ports
prior to launching an API server instance.

Fixes #260
Fixes #267

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
  • Loading branch information
petermetz committed Sep 17, 2020
1 parent c65baf8 commit ad01dee
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ import {
} from "@hyperledger/cactus-core-api";
import { ICactusApiServerOptions } from "./config/config-service";
import { CACTUS_OPEN_API_JSON } from "./openapi-spec";
import { Logger, LoggerProvider } from "@hyperledger/cactus-common";
import { Servers } from "./common/servers";
import { Logger, LoggerProvider, Servers } from "@hyperledger/cactus-common";

export interface IApiServerConstructorOptions {
pluginRegistry?: PluginRegistry;
Expand Down

This file was deleted.

1 change: 1 addition & 0 deletions packages/cactus-common/src/main/typescript/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./public-api";
export { IListenOptions, Servers } from "./servers";
67 changes: 67 additions & 0 deletions packages/cactus-common/src/main/typescript/servers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { AddressInfo, ListenOptions } from "net";
import { Server } from "http";
import { Server as SecureServer } from "https";
import { Checks } from "./checks";

export interface IListenOptions {
server: Server | SecureServer;
port: number;
hostname: string;
}

/**
* Utility class for handling common tasks for NodeJS HTTP/S server objects.
*/
export class Servers {
/**
* Returns with a promise that resolves when the server has been shut down. Rejects if anything goes wrong of if the
* parameters are invalid.
*
* @param server The server object that will be shut down.
*/
public static async shutdown(server: Server | SecureServer): Promise<void> {
if (!server) {
throw new TypeError(`Servers#shutdown() server was falsy. Need object.`);
}
return new Promise<void>((resolve, reject) => {
server.close((err: any) => {
if (err) {
reject(
new Error(
`Servers#shutdown() Failed to shut down server: ${err.stack}`
)
);
} else {
resolve();
}
});
});
}

public static async listen(options: IListenOptions): Promise<any> {
const fnTag = "Servers#listen()";

Checks.truthy(options, `${fnTag} arg options`);
Checks.truthy(options.server, `${fnTag} arg options.server`);
Checks.truthy(options.port, `${fnTag} arg options.port`);
Checks.truthy(options.hostname, `${fnTag} arg options.hostname`);
const { server, port, hostname } = options;

return new Promise((resolve, reject) => {
server.on("error", (ex) => reject(ex));

const listenOptions: ListenOptions = {
host: hostname,
port,
};

// called when the `listening` event is fired
const onListeningHandler = () => {
const addressInfo = options.server.address() as AddressInfo;
resolve(addressInfo);
};

server.listen(listenOptions, onListeningHandler);
});
}
}

0 comments on commit ad01dee

Please sign in to comment.