Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | 44x 44x 44x 44x 44x 44x 44x 44x 44x 72x 72x 72x 72x 72x 72x 72x 23x 23x 23x 23x 72x 72x 28x 28x 28x 12x 54x 53x 79x 50x 6x 18x 18x 70x 286x 286x 19x 19x 19x 19x | import * as OpenApiValidator from 'express-openapi-validator'; import { CardanoNodeUtil, HealthCheckResponse, HttpProviderConfigPaths, Provider, ProviderError, ProviderFailure, providerFailureToStatusCodeMap } from '@cardano-sdk/core'; import { HttpServer } from './HttpServer'; import { Logger } from 'ts-log'; import { ProviderHandler, providerHandler } from '../util'; import { RunnableModule } from '@cardano-sdk/util'; import { versionPathFromSpec } from '../util/openApi'; import express, { Router } from 'express'; import path from 'path'; const openApiOption = { ignoreUndocumented: true, validateRequests: true, validateResponses: process.env.NODE_ENV !== 'production' }; export abstract class HttpService extends RunnableModule { public router: express.Router; public slug: string; public provider: Provider; public openApiPath: string; constructor(slug: string, provider: Provider, router: express.Router, openApiPath: string, logger: Logger) { super(slug, logger); this.router = router; this.slug = slug; this.provider = provider; this.openApiPath = path.join(openApiPath, 'openApi.json'); router.use(OpenApiValidator.middleware({ apiSpec: this.openApiPath, ...openApiOption })); const healthHandler = async (_: express.Request, res: express.Response) => { logger.debug('/health'); let body: HealthCheckResponse | Error['message']; try { body = await this.healthCheck(); } catch (error) { logger.error(error); body = CardanoNodeUtil.isProviderError(error) ? error.message : 'Unknown error'; res.statusCode = 500; } res.send(body); }; this.router.get('/health', healthHandler); this.router.post('/health', healthHandler); } protected async initializeImpl(): Promise<void> { if (this.provider instanceof RunnableModule) await this.provider.initialize(); const health = await this.healthCheck(); if (!health.ok) { this.logger.warn('Service started in unhealthy state'); } } protected async startImpl(): Promise<void> { if (this.provider instanceof RunnableModule) await this.provider.start(); } protected async shutdownImpl(): Promise<void> { if (this.provider instanceof RunnableModule) await this.provider.shutdown(); } async healthCheck(): Promise<HealthCheckResponse> { return await this.provider.healthCheck(); } apiVersionPath(): string { return versionPathFromSpec(this.openApiPath); } attachProviderRoutes<T extends Provider>(provider: T, router: Router, paths: HttpProviderConfigPaths<T>) { for (const methodName in paths) { const handler = providerHandler((provider[methodName] as Function).bind(provider)); router.post(paths[methodName], handler(HttpService.routeHandler(this.logger), this.logger)); } } static routeHandler(logger: Logger): ProviderHandler { return async (args, _r, res, _n, handler) => { try { return HttpServer.sendJSON(res, await handler(args)); } catch (error) { logger.error(error); if (CardanoNodeUtil.isProviderError(error)) { const code = providerFailureToStatusCodeMap[error.reason]; return HttpServer.sendJSON(res, error, code); } return HttpServer.sendJSON(res, new ProviderError(ProviderFailure.Unhealthy, error), 500); } }; } } |