statusCodeRules.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. export function parseHttpStatusCodeRules(input) {
  2. const raw = (input ?? '').toString().trim();
  3. if (raw.length === 0) {
  4. return {
  5. ok: true,
  6. ranges: [],
  7. tokens: [],
  8. normalized: '',
  9. invalidTokens: [],
  10. };
  11. }
  12. const sanitized = raw.replace(/[,]/g, ',');
  13. const segments = sanitized.split(/[,]/g);
  14. const ranges = [];
  15. const invalidTokens = [];
  16. for (const segment of segments) {
  17. const trimmed = segment.trim();
  18. if (!trimmed) continue;
  19. const parsed = parseToken(trimmed);
  20. if (!parsed) invalidTokens.push(trimmed);
  21. else ranges.push(parsed);
  22. }
  23. if (invalidTokens.length > 0) {
  24. return {
  25. ok: false,
  26. ranges: [],
  27. tokens: [],
  28. normalized: raw,
  29. invalidTokens,
  30. };
  31. }
  32. const merged = mergeRanges(ranges);
  33. const tokens = merged.map((r) => (r.start === r.end ? `${r.start}` : `${r.start}-${r.end}`));
  34. const normalized = tokens.join(',');
  35. return {
  36. ok: true,
  37. ranges: merged,
  38. tokens,
  39. normalized,
  40. invalidTokens: [],
  41. };
  42. }
  43. function parseToken(token) {
  44. const cleaned = (token ?? '').toString().trim().replaceAll(' ', '');
  45. if (!cleaned) return null;
  46. if (cleaned.includes('-')) {
  47. const parts = cleaned.split('-');
  48. if (parts.length !== 2) return null;
  49. const [a, b] = parts;
  50. if (!isNumber(a) || !isNumber(b)) return null;
  51. const start = Number.parseInt(a, 10);
  52. const end = Number.parseInt(b, 10);
  53. if (!Number.isFinite(start) || !Number.isFinite(end)) return null;
  54. if (start > end) return null;
  55. if (start < 100 || end > 599) return null;
  56. return { start, end };
  57. }
  58. if (!isNumber(cleaned)) return null;
  59. const code = Number.parseInt(cleaned, 10);
  60. if (!Number.isFinite(code)) return null;
  61. if (code < 100 || code > 599) return null;
  62. return { start: code, end: code };
  63. }
  64. function isNumber(s) {
  65. return typeof s === 'string' && /^\d+$/.test(s);
  66. }
  67. function mergeRanges(ranges) {
  68. if (!Array.isArray(ranges) || ranges.length === 0) return [];
  69. const sorted = [...ranges].sort((a, b) => (a.start !== b.start ? a.start - b.start : a.end - b.end));
  70. const merged = [sorted[0]];
  71. for (let i = 1; i < sorted.length; i += 1) {
  72. const current = sorted[i];
  73. const last = merged[merged.length - 1];
  74. if (current.start <= last.end + 1) {
  75. last.end = Math.max(last.end, current.end);
  76. continue;
  77. }
  78. merged.push({ ...current });
  79. }
  80. return merged;
  81. }