services-api-handler.class.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { RouterOptions, json } from 'express';
  2. import { ServiceCheckData } from '../../../common/lib/http-check-data.module';
  3. import { HttpStatusException } from '../../../common/lib/http-status.exception';
  4. import { ControllerPool } from '../ctrl/controller-pool.interface';
  5. import { ServiceChangedStatus } from '../ctrl/database.class';
  6. import { WebHandler } from './web-handler.base';
  7. export class ServicesAPIHandler extends WebHandler {
  8. constructor(protected ctrlPool: ControllerPool, options?: RouterOptions) {
  9. super(ctrlPool, options);
  10. this.router.use(json());
  11. this.router.use(this.avoidCache);
  12. this.router.get('/:serverID', async (req, res, next) => {
  13. try {
  14. const serverID = this.validateNumber(req.params.serverID, 'server id');
  15. const services = await this.ctrlPool.db.getHttpCheckConfigs(serverID);
  16. res.send(services);
  17. } catch (err) {
  18. next(err);
  19. }
  20. });
  21. this.router.put('/:serverID', async (req, res, next) => {
  22. try {
  23. const serverID = this.validateNumber(req.params.serverID, 'server id');
  24. const result = await this.ctrlPool.db.saveHttpCheckConfig(serverID, req.body);
  25. if (result.status !== ServiceChangedStatus.None) {
  26. await this.ctrlPool.httpChecks.updateCheck(result.status, result.result);
  27. }
  28. res.send(result.result);
  29. } catch (err) {
  30. next(err);
  31. }
  32. });
  33. this.router.delete('/:serverID/:serviceID', async (req, res, next) => {
  34. try {
  35. const serverID = this.validateNumber(req.params.serverID, 'server id');
  36. const serviceID = this.validateNumber(req.params.serviceID, 'service id');
  37. const deleted = await this.ctrlPool.db.deleteHealthCheckConfig(serverID, serviceID);
  38. if (deleted) {
  39. await this.ctrlPool.httpChecks.updateCheck(ServiceChangedStatus.Deactivated, { id: serviceID } as HttpCheckConfig);
  40. }
  41. res.send({ deleted });
  42. } catch (err) {
  43. next(err);
  44. }
  45. });
  46. this.router.get('/:serverID/:serviceID', async (req, res, next) => {
  47. try {
  48. const serverID = this.validateNumber(req.params.serverID, 'server id');
  49. const serviceID = this.validateNumber(req.params.serviceID, 'service id');
  50. const result = await this.ctrlPool.db.getHttpCheckConfigByID(serverID, serviceID);
  51. res.send(result);
  52. } catch (err) {
  53. next(err);
  54. }
  55. });
  56. this.router.get('/:serverID/:serviceID/data', async (req, res, next) => {
  57. try {
  58. const serverID = this.validateNumber(req.params.serverID, 'server id');
  59. const serviceID = this.validateNumber(req.params.serviceID, 'service id');
  60. const qStart = (req.query.start || '').toString();
  61. const qEnd = (req.query.end || '').toString();
  62. if (!qStart || !qEnd) throw new HttpStatusException("QueryParams 'start' and 'end' are mandatory.", 400);
  63. const start = new Date(qStart);
  64. const end = new Date(qEnd);
  65. if ([start.toString(), end.toString()].includes('Invalid Date')) {
  66. throw new HttpStatusException("QueryParams 'start' and 'end' must be parseable dates or unix epoch timestamps (ms).", 400);
  67. }
  68. const data = await this.ctrlPool.db.queryServiceCheckData(serverID, serviceID, start, end);
  69. res.send({
  70. start,
  71. end,
  72. data
  73. } as QueryResponse<ServiceCheckData[]>);
  74. } catch (err) {
  75. next(err);
  76. }
  77. });
  78. this.router.get('/:serverID/:serviceID/logs', async (req, res, next) => {
  79. try {
  80. const serverID = this.validateNumber(req.params.serverID, 'server id');
  81. const serviceID = this.validateNumber(req.params.serviceID, 'service id');
  82. const qStart = (req.query.start || '').toString();
  83. const qEnd = (req.query.end || '').toString();
  84. if (!qStart || !qEnd) throw new HttpStatusException("QueryParams 'start' and 'end' are mandatory.", 400);
  85. const start = new Date(qStart);
  86. const end = new Date(qEnd);
  87. if ([start.toString(), end.toString()].includes('Invalid Date')) {
  88. throw new HttpStatusException("QueryParams 'start' and 'end' must be parseable dates or unix epoch timestamps (ms).", 400);
  89. }
  90. const data = await this.ctrlPool.db.queryServiceCheckLogs(serverID, serviceID, start, end);
  91. res.send({
  92. start,
  93. end,
  94. data
  95. } as QueryResponse<ServiceCheckData[]>);
  96. } catch (err) {
  97. next(err);
  98. }
  99. });
  100. }
  101. private validateNumber(id: string, field: string) {
  102. const num = Number(id);
  103. if (Number.isNaN(num)) {
  104. throw new HttpStatusException(`Not a valid ${field}: ${id}`, 400);
  105. }
  106. return num;
  107. }
  108. }