Skip to content

Commit

Permalink
refactor(connector-fabric): reusable error handler in REST endpoints
Browse files Browse the repository at this point in the history
1. Error-handling : Updates to the catch block of the Rest API endpoints
of fabric package by importing the utility function `handleRestEndpointException`
from cactus-core package that differentiates the user/developer errors.
2. Minor code changes in the endpoints like adding the functions and
formulating the error messages.

Co-authored-by: Peter Somogyvari <[email protected]>

Signed-off-by: ArchanaArige <[email protected]>
Signed-off-by: Peter Somogyvari <[email protected]>
  • Loading branch information
ArchanaArige authored and petermetz committed Jul 24, 2024
1 parent ecf074c commit d8a99c6
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import {
IEndpointAuthzOptions,
} from "@hyperledger/cactus-core-api";

import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";
import {
handleRestEndpointException,
registerWebServiceEndpoint,
} from "@hyperledger/cactus-core";

import { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";
import { DeployContractGoSourceV1Request } from "../generated/openapi/typescript-axios/index";
Expand Down Expand Up @@ -106,8 +109,8 @@ export class DeployContractGoSourceEndpointV1 implements IWebServiceEndpoint {
async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const verbUpper = this.getVerbLowerCase().toUpperCase();
this.log.debug(`${verbUpper} ${this.getPath()}`);

const reqTag = `${verbUpper} ${this.getPath()}`;
this.log.debug(reqTag);
try {
const { connector } = this.opts;
const reqBody = req.body as DeployContractGoSourceV1Request;
Expand All @@ -116,10 +119,13 @@ export class DeployContractGoSourceEndpointV1 implements IWebServiceEndpoint {
res.status(HttpStatus.OK);
res.json(resBody);
} catch (ex) {
this.log.error(`${fnTag} failed to serve contract deploy request`, ex);
res.status(HttpStatus.INTERNAL_SERVER_ERROR);
res.statusMessage = ex.message;
res.json({ error: ex.stack });
const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`;
await handleRestEndpointException({
errorMsg,
log: this.log,
error: ex,
res,
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import {
IEndpointAuthzOptions,
} from "@hyperledger/cactus-core-api";

import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";
import {
handleRestEndpointException,
registerWebServiceEndpoint,
} from "@hyperledger/cactus-core";

import { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";
import { DeployContractV1Request } from "../generated/openapi/typescript-axios/index";
Expand Down Expand Up @@ -87,7 +90,8 @@ export class DeployContractEndpointV1 implements IWebServiceEndpoint {
async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = `${this.className}#handleRequest()`;
const verbUpper = this.getVerbLowerCase().toUpperCase();
this.log.debug(`${verbUpper} ${this.getPath()}`);
const reqTag = `${verbUpper} ${this.getPath()}`;
this.log.debug(reqTag);

try {
const { connector } = this.opts;
Expand All @@ -96,10 +100,13 @@ export class DeployContractEndpointV1 implements IWebServiceEndpoint {
res.status(HttpStatus.OK);
res.json(resBody);
} catch (ex) {
this.log.error(`${fnTag} failed to serve contract deploy request`, ex);
res.status(HttpStatus.INTERNAL_SERVER_ERROR);
res.statusMessage = ex.message;
res.json({ error: ex.stack });
const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`;
await handleRestEndpointException({
errorMsg,
log: this.log,
error: ex,
res,
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ export interface IGetBlockEndpointV1Options {
}

export class GetBlockEndpointV1 implements IWebServiceEndpoint {
public static readonly CLASS_NAME = "GetBlockEndpointV1";

private readonly log: Logger;

public get className(): string {
return GetBlockEndpointV1.CLASS_NAME;
}

constructor(public readonly opts: IGetBlockEndpointV1Options) {
const fnTag = "GetBlockEndpointV1#constructor()";
const fnTag = `${this.className}#constructor()`;

Checks.truthy(opts, `${fnTag} options`);
Checks.truthy(opts.connector, `${fnTag} options.connector`);
Expand Down Expand Up @@ -84,14 +90,21 @@ export class GetBlockEndpointV1 implements IWebServiceEndpoint {
}

async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = "GetBlockEndpointV1#handleRequest()";
this.log.debug(`POST ${this.getPath()}`);
const fnTag = `${this.className}#handleRequest()`;
const verbUpper = this.getVerbLowerCase().toUpperCase();
const reqTag = `${verbUpper} ${this.getPath()}`;
this.log.debug(reqTag);

try {
res.status(200).send(await this.opts.connector.getBlock(req.body));
} catch (error) {
const errorMsg = `Crash while serving ${fnTag}`;
handleRestEndpointException({ errorMsg, log: this.log, error, res });
} catch (ex) {
const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`;
await handleRestEndpointException({
errorMsg,
log: this.log,
error: ex,
res,
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import {

import OAS from "../../json/openapi.json";

import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";
import {
handleRestEndpointException,
registerWebServiceEndpoint,
} from "@hyperledger/cactus-core";

import { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";

Expand All @@ -28,12 +31,18 @@ export interface IGetPrometheusExporterMetricsEndpointV1Options {
export class GetPrometheusExporterMetricsEndpointV1
implements IWebServiceEndpoint
{
public static readonly CLASS_NAME = "GetPrometheusExporterMetricsEndpointV1";

private readonly log: Logger;

public get className(): string {
return GetPrometheusExporterMetricsEndpointV1.CLASS_NAME;
}

constructor(
public readonly opts: IGetPrometheusExporterMetricsEndpointV1Options,
) {
const fnTag = "GetPrometheusExporterMetricsEndpointV1#constructor()";
const fnTag = `${this.className}#constructor()`;

Checks.truthy(opts, `${fnTag} options`);
Checks.truthy(opts.connector, `${fnTag} options.connector`);
Expand Down Expand Up @@ -83,19 +92,23 @@ export class GetPrometheusExporterMetricsEndpointV1
}

async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = "GetPrometheusExporterMetrics#handleRequest()";
const fnTag = `${this.className}#handleRequest()`;
const verbUpper = this.getVerbLowerCase().toUpperCase();
this.log.debug(`${verbUpper} ${this.getPath()}`);
const reqTag = `${verbUpper} ${this.getPath()}`;
this.log.debug(reqTag);

try {
const resBody = await this.opts.connector.getPrometheusExporterMetrics();
res.status(200);
res.send(resBody);
} catch (ex) {
this.log.error(`${fnTag} failed to serve request`, ex);
res.status(500);
res.statusMessage = ex.message;
res.json({ error: ex.stack });
const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`;
await handleRestEndpointException({
errorMsg,
log: this.log,
error: ex,
res,
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import {
IEndpointAuthzOptions,
} from "@hyperledger/cactus-core-api";

import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";
import {
handleRestEndpointException,
registerWebServiceEndpoint,
} from "@hyperledger/cactus-core";

import { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";
import { RunTransactionRequest } from "../generated/openapi/typescript-axios";
Expand All @@ -28,10 +31,16 @@ export interface IRunTransactionEndpointV1Options {
export class GetTransactionReceiptByTxIDEndpointV1
implements IWebServiceEndpoint
{
public static readonly CLASS_NAME = "GetTransactionReceiptByTxIDEndpointV1";

private readonly log: Logger;

public get className(): string {
return GetTransactionReceiptByTxIDEndpointV1.CLASS_NAME;
}

constructor(public readonly opts: IRunTransactionEndpointV1Options) {
const fnTag = "GetTransactionReceiptByTxIDEndpointV1#constructor()";
const fnTag = `${this.className}#constructor()`;

Checks.truthy(opts, `${fnTag} options`);
Checks.truthy(opts.connector, `${fnTag} options.connector`);
Expand Down Expand Up @@ -84,8 +93,10 @@ export class GetTransactionReceiptByTxIDEndpointV1
}

async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = "GetTransactionReceiptByTxIDEndpointV1#handleRequest()";
this.log.debug(`POST ${this.getPath()}`);
const fnTag = `${this.className}#handleRequest()`;
const verbUpper = this.getVerbLowerCase().toUpperCase();
const reqTag = `${verbUpper} ${this.getPath()}`;
this.log.debug(reqTag);

try {
const reqBody = req.body as RunTransactionRequest;
Expand All @@ -94,10 +105,13 @@ export class GetTransactionReceiptByTxIDEndpointV1
res.status(200);
res.json(resBody);
} catch (ex) {
this.log.error(`${fnTag} failed to serve request`, ex);
res.status(500);
res.statusMessage = ex.message;
res.json({ error: ex.stack });
const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`;
await handleRestEndpointException({
errorMsg,
log: this.log,
error: ex,
res,
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
LogLevelDesc,
Checks,
IAsyncProvider,
safeStringifyException,
} from "@hyperledger/cactus-common";

import {
Expand All @@ -15,7 +14,10 @@ import {
IEndpointAuthzOptions,
} from "@hyperledger/cactus-core-api";

import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";
import {
handleRestEndpointException,
registerWebServiceEndpoint,
} from "@hyperledger/cactus-core";

import { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";
import OAS from "../../json/openapi.json";
Expand All @@ -28,13 +30,18 @@ export interface IRunDelegatedSignTransactionEndpointV1Options {
export class RunDelegatedSignTransactionEndpointV1
implements IWebServiceEndpoint
{
public static readonly CLASS_NAME = "RunDelegatedSignTransactionEndpointV1";

private readonly log: Logger;

public get className(): string {
return RunDelegatedSignTransactionEndpointV1.CLASS_NAME;
}

constructor(
public readonly opts: IRunDelegatedSignTransactionEndpointV1Options,
) {
const fnTag = "RunDelegatedSignTransactionEndpointV1#constructor()";

const fnTag = `${this.className}#constructor()`;
Checks.truthy(opts, `${fnTag} options`);
Checks.truthy(opts.connector, `${fnTag} options.connector`);

Expand Down Expand Up @@ -84,18 +91,22 @@ export class RunDelegatedSignTransactionEndpointV1
}

async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = "RunDelegatedSignTransactionEndpointV1#handleRequest()";
this.log.debug(`POST ${this.getPath()}`);
const fnTag = `${this.className}#handleRequest()`;
const verbUpper = this.getVerbLowerCase().toUpperCase();
const reqTag = `${verbUpper} ${this.getPath()}`;
this.log.debug(reqTag);

try {
res
.status(200)
.json(await this.opts.connector.transactDelegatedSign(req.body));
} catch (error) {
this.log.error(`Crash while serving ${fnTag}`, error);
res.status(500).json({
message: "Internal Server Error",
error: safeStringifyException(error),
} catch (ex) {
const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`;
await handleRestEndpointException({
errorMsg,
log: this.log,
error: ex,
res,
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
LogLevelDesc,
Checks,
IAsyncProvider,
safeStringifyException,
} from "@hyperledger/cactus-common";

import {
Expand All @@ -15,7 +14,10 @@ import {
IEndpointAuthzOptions,
} from "@hyperledger/cactus-core-api";

import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";
import {
handleRestEndpointException,
registerWebServiceEndpoint,
} from "@hyperledger/cactus-core";

import { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";
import OAS from "../../json/openapi.json";
Expand All @@ -26,10 +28,16 @@ export interface IRunTransactionEndpointV1Options {
}

export class RunTransactionEndpointV1 implements IWebServiceEndpoint {
public static readonly CLASS_NAME = "RunTransactionEndpointV1";

private readonly log: Logger;

public get className(): string {
return RunTransactionEndpointV1.CLASS_NAME;
}

constructor(public readonly opts: IRunTransactionEndpointV1Options) {
const fnTag = "RunTransactionEndpointV1#constructor()";
const fnTag = `${this.className}#constructor()`;

Checks.truthy(opts, `${fnTag} options`);
Checks.truthy(opts.connector, `${fnTag} options.connector`);
Expand Down Expand Up @@ -80,16 +88,20 @@ export class RunTransactionEndpointV1 implements IWebServiceEndpoint {
}

async handleRequest(req: Request, res: Response): Promise<void> {
const fnTag = "RunTransactionEndpointV1#handleRequest()";
this.log.debug(`POST ${this.getPath()}`);
const fnTag = `${this.className}#handleRequest()`;
const verbUpper = this.getVerbLowerCase().toUpperCase();
const reqTag = `${verbUpper} ${this.getPath()}`;
this.log.debug(reqTag);

try {
res.status(200).json(await this.opts.connector.transact(req.body));
} catch (error) {
this.log.error(`Crash while serving ${fnTag}`, error);
res.status(500).json({
message: "Internal Server Error",
error: safeStringifyException(error),
} catch (ex) {
const errorMsg = `${fnTag} request handler fn crashed for: ${reqTag}`;
await handleRestEndpointException({
errorMsg,
log: this.log,
error: ex,
res,
});
}
}
Expand Down

0 comments on commit d8a99c6

Please sign in to comment.