ninja-reverse-proxy 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (525) hide show
  1. package/README.md +187 -139
  2. package/dist/balancer/contracts/balancer.interface.d.ts +8 -0
  3. package/dist/balancer/contracts/balancer.interface.d.ts.map +1 -0
  4. package/dist/balancer/contracts/balancer.interface.js +2 -0
  5. package/dist/balancer/contracts/balancer.interface.js.map +1 -0
  6. package/dist/balancer/contracts/context.types.d.ts +7 -0
  7. package/dist/balancer/contracts/context.types.d.ts.map +1 -0
  8. package/dist/balancer/contracts/context.types.js +2 -0
  9. package/dist/balancer/contracts/context.types.js.map +1 -0
  10. package/dist/balancer/contracts/strategy.interface.d.ts +6 -0
  11. package/dist/balancer/contracts/strategy.interface.d.ts.map +1 -0
  12. package/dist/balancer/contracts/strategy.interface.js +2 -0
  13. package/dist/balancer/contracts/strategy.interface.js.map +1 -0
  14. package/dist/balancer/core/load-balancer.d.ts +21 -0
  15. package/dist/balancer/core/load-balancer.d.ts.map +1 -0
  16. package/dist/balancer/core/load-balancer.js +188 -0
  17. package/dist/balancer/core/load-balancer.js.map +1 -0
  18. package/dist/balancer/core/strategy-registry.d.ts +8 -0
  19. package/dist/balancer/core/strategy-registry.d.ts.map +1 -0
  20. package/dist/balancer/core/strategy-registry.js +11 -0
  21. package/dist/balancer/core/strategy-registry.js.map +1 -0
  22. package/dist/balancer/factory/balancer.factory.d.ts +4 -0
  23. package/dist/balancer/factory/balancer.factory.d.ts.map +1 -0
  24. package/dist/balancer/factory/balancer.factory.js +35 -0
  25. package/dist/balancer/factory/balancer.factory.js.map +1 -0
  26. package/dist/balancer/index.d.ts +6 -0
  27. package/dist/balancer/index.d.ts.map +1 -0
  28. package/dist/balancer/index.js +3 -0
  29. package/dist/balancer/index.js.map +1 -0
  30. package/dist/balancer/strategies/adaptive-wrr.strategy.d.ts +8 -0
  31. package/dist/balancer/strategies/adaptive-wrr.strategy.d.ts.map +1 -0
  32. package/dist/balancer/strategies/adaptive-wrr.strategy.js +32 -0
  33. package/dist/balancer/strategies/adaptive-wrr.strategy.js.map +1 -0
  34. package/dist/balancer/strategies/consistent-hashing.strategy.d.ts +11 -0
  35. package/dist/balancer/strategies/consistent-hashing.strategy.d.ts.map +1 -0
  36. package/dist/balancer/strategies/consistent-hashing.strategy.js +45 -0
  37. package/dist/balancer/strategies/consistent-hashing.strategy.js.map +1 -0
  38. package/dist/balancer/strategies/ip-hash.strategy.d.ts +7 -0
  39. package/dist/balancer/strategies/ip-hash.strategy.d.ts.map +1 -0
  40. package/dist/balancer/strategies/ip-hash.strategy.js +24 -0
  41. package/dist/balancer/strategies/ip-hash.strategy.js.map +1 -0
  42. package/dist/balancer/strategies/least-connections.strategy.d.ts +6 -0
  43. package/dist/balancer/strategies/least-connections.strategy.d.ts.map +1 -0
  44. package/dist/balancer/strategies/least-connections.strategy.js +8 -0
  45. package/dist/balancer/strategies/least-connections.strategy.js.map +1 -0
  46. package/dist/balancer/strategies/least-response-time.strategy.d.ts +6 -0
  47. package/dist/balancer/strategies/least-response-time.strategy.d.ts.map +1 -0
  48. package/dist/balancer/strategies/least-response-time.strategy.js +8 -0
  49. package/dist/balancer/strategies/least-response-time.strategy.js.map +1 -0
  50. package/dist/balancer/strategies/power-of-two.strategy.d.ts +6 -0
  51. package/dist/balancer/strategies/power-of-two.strategy.d.ts.map +1 -0
  52. package/dist/balancer/strategies/power-of-two.strategy.js +17 -0
  53. package/dist/balancer/strategies/power-of-two.strategy.js.map +1 -0
  54. package/dist/balancer/strategies/random.strategy.d.ts +6 -0
  55. package/dist/balancer/strategies/random.strategy.d.ts.map +1 -0
  56. package/dist/balancer/strategies/random.strategy.js +8 -0
  57. package/dist/balancer/strategies/random.strategy.js.map +1 -0
  58. package/dist/balancer/strategies/resource-based.strategy.d.ts +7 -0
  59. package/dist/balancer/strategies/resource-based.strategy.d.ts.map +1 -0
  60. package/dist/balancer/strategies/resource-based.strategy.js +24 -0
  61. package/dist/balancer/strategies/resource-based.strategy.js.map +1 -0
  62. package/dist/balancer/strategies/round-robin.strategy.d.ts +7 -0
  63. package/dist/balancer/strategies/round-robin.strategy.d.ts.map +1 -0
  64. package/dist/balancer/strategies/round-robin.strategy.js +11 -0
  65. package/dist/balancer/strategies/round-robin.strategy.js.map +1 -0
  66. package/dist/balancer/strategies/sticky-sessions.strategy.d.ts +8 -0
  67. package/dist/balancer/strategies/sticky-sessions.strategy.d.ts.map +1 -0
  68. package/dist/balancer/strategies/sticky-sessions.strategy.js +20 -0
  69. package/dist/balancer/strategies/sticky-sessions.strategy.js.map +1 -0
  70. package/dist/balancer/strategies/weighted-least-connections.strategy.d.ts +6 -0
  71. package/dist/balancer/strategies/weighted-least-connections.strategy.d.ts.map +1 -0
  72. package/dist/balancer/strategies/weighted-least-connections.strategy.js +12 -0
  73. package/dist/balancer/strategies/weighted-least-connections.strategy.js.map +1 -0
  74. package/dist/balancer/strategies/weighted-round-robin.strategy.d.ts +8 -0
  75. package/dist/balancer/strategies/weighted-round-robin.strategy.d.ts.map +1 -0
  76. package/dist/balancer/strategies/weighted-round-robin.strategy.js +31 -0
  77. package/dist/balancer/strategies/weighted-round-robin.strategy.js.map +1 -0
  78. package/dist/cache/cache-manager.d.ts +25 -0
  79. package/dist/cache/cache-manager.d.ts.map +1 -0
  80. package/dist/cache/cache-manager.js +176 -0
  81. package/dist/cache/cache-manager.js.map +1 -0
  82. package/dist/cache/contracts/cache-config.interface.d.ts +25 -0
  83. package/dist/cache/contracts/cache-config.interface.d.ts.map +1 -0
  84. package/dist/cache/contracts/cache-config.interface.js +2 -0
  85. package/dist/cache/contracts/cache-config.interface.js.map +1 -0
  86. package/dist/cache/contracts/cache.interface.d.ts +8 -0
  87. package/dist/cache/contracts/cache.interface.d.ts.map +1 -0
  88. package/dist/cache/contracts/cache.interface.js +2 -0
  89. package/dist/cache/contracts/cache.interface.js.map +1 -0
  90. package/dist/cache/contracts/invalidator.interface.d.ts +6 -0
  91. package/dist/cache/contracts/invalidator.interface.d.ts.map +1 -0
  92. package/dist/cache/contracts/invalidator.interface.js +2 -0
  93. package/dist/cache/contracts/invalidator.interface.js.map +1 -0
  94. package/dist/cache/index.d.ts +3 -0
  95. package/dist/cache/index.d.ts.map +1 -0
  96. package/dist/cache/index.js +2 -0
  97. package/dist/cache/index.js.map +1 -0
  98. package/dist/cache/invalidation/debezium.invalidator.d.ts +8 -0
  99. package/dist/cache/invalidation/debezium.invalidator.d.ts.map +1 -0
  100. package/dist/cache/invalidation/debezium.invalidator.js +71 -0
  101. package/dist/cache/invalidation/debezium.invalidator.js.map +1 -0
  102. package/dist/cache/invalidation/pattern.invalidator.d.ts +9 -0
  103. package/dist/cache/invalidation/pattern.invalidator.d.ts.map +1 -0
  104. package/dist/cache/invalidation/pattern.invalidator.js +10 -0
  105. package/dist/cache/invalidation/pattern.invalidator.js.map +1 -0
  106. package/dist/cache/invalidation/tag.invalidator.d.ts +7 -0
  107. package/dist/cache/invalidation/tag.invalidator.d.ts.map +1 -0
  108. package/dist/cache/invalidation/tag.invalidator.js +17 -0
  109. package/dist/cache/invalidation/tag.invalidator.js.map +1 -0
  110. package/dist/cache/policies/cache-control.parser.d.ts +9 -0
  111. package/dist/cache/policies/cache-control.parser.d.ts.map +1 -0
  112. package/dist/cache/policies/cache-control.parser.js +18 -0
  113. package/dist/cache/policies/cache-control.parser.js.map +1 -0
  114. package/dist/cache/policies/key-builder.d.ts +11 -0
  115. package/dist/cache/policies/key-builder.d.ts.map +1 -0
  116. package/dist/cache/policies/key-builder.js +20 -0
  117. package/dist/cache/policies/key-builder.js.map +1 -0
  118. package/dist/cache/policies/stale-if-error.d.ts +4 -0
  119. package/dist/cache/policies/stale-if-error.d.ts.map +1 -0
  120. package/dist/cache/policies/stale-if-error.js +7 -0
  121. package/dist/cache/policies/stale-if-error.js.map +1 -0
  122. package/dist/cache/policies/stale-while-revalidate.d.ts +7 -0
  123. package/dist/cache/policies/stale-while-revalidate.d.ts.map +1 -0
  124. package/dist/cache/policies/stale-while-revalidate.js +13 -0
  125. package/dist/cache/policies/stale-while-revalidate.js.map +1 -0
  126. package/dist/cache/stores/hybrid.cache.d.ts +13 -0
  127. package/dist/cache/stores/hybrid.cache.d.ts.map +1 -0
  128. package/dist/cache/stores/hybrid.cache.js +36 -0
  129. package/dist/cache/stores/hybrid.cache.js.map +1 -0
  130. package/dist/cache/stores/in-memory-lru.d.ts +14 -0
  131. package/dist/cache/stores/in-memory-lru.d.ts.map +1 -0
  132. package/dist/cache/stores/in-memory-lru.js +41 -0
  133. package/dist/cache/stores/in-memory-lru.js.map +1 -0
  134. package/dist/cache/stores/redis.cache.d.ts +13 -0
  135. package/dist/cache/stores/redis.cache.d.ts.map +1 -0
  136. package/dist/cache/stores/redis.cache.js +39 -0
  137. package/dist/cache/stores/redis.cache.js.map +1 -0
  138. package/dist/config/config-schema.d.ts +3 -0
  139. package/dist/config/config-schema.d.ts.map +1 -0
  140. package/dist/config/config-schema.js +2 -0
  141. package/dist/config/config-schema.js.map +1 -0
  142. package/dist/config/config.d.ts +2 -0
  143. package/dist/config/config.d.ts.map +1 -0
  144. package/dist/config/config.js +2 -0
  145. package/dist/config/config.js.map +1 -0
  146. package/dist/config/config.loader.d.ts +266 -0
  147. package/dist/config/config.loader.d.ts.map +1 -0
  148. package/dist/config/config.loader.js +204 -0
  149. package/dist/config/config.loader.js.map +1 -0
  150. package/dist/config/index.d.ts +10 -0
  151. package/dist/config/index.d.ts.map +1 -0
  152. package/dist/config/index.js +10 -0
  153. package/dist/config/index.js.map +1 -0
  154. package/dist/config/schemas/admin.schema.d.ts +7 -0
  155. package/dist/config/schemas/admin.schema.d.ts.map +1 -0
  156. package/dist/config/schemas/admin.schema.js +11 -0
  157. package/dist/config/schemas/admin.schema.js.map +1 -0
  158. package/dist/config/schemas/balancer.schema.d.ts +32 -0
  159. package/dist/config/schemas/balancer.schema.d.ts.map +1 -0
  160. package/dist/config/schemas/balancer.schema.js +52 -0
  161. package/dist/config/schemas/balancer.schema.js.map +1 -0
  162. package/dist/config/schemas/cache.schema.d.ts +25 -0
  163. package/dist/config/schemas/cache.schema.d.ts.map +1 -0
  164. package/dist/config/schemas/cache.schema.js +57 -0
  165. package/dist/config/schemas/cache.schema.js.map +1 -0
  166. package/dist/config/schemas/discovery.schema.d.ts +8 -0
  167. package/dist/config/schemas/discovery.schema.d.ts.map +1 -0
  168. package/dist/config/schemas/discovery.schema.js +13 -0
  169. package/dist/config/schemas/discovery.schema.js.map +1 -0
  170. package/dist/config/schemas/observability.schema.d.ts +48 -0
  171. package/dist/config/schemas/observability.schema.d.ts.map +1 -0
  172. package/dist/config/schemas/observability.schema.js +56 -0
  173. package/dist/config/schemas/observability.schema.js.map +1 -0
  174. package/dist/config/schemas/ratelimit.schema.d.ts +36 -0
  175. package/dist/config/schemas/ratelimit.schema.d.ts.map +1 -0
  176. package/dist/config/schemas/ratelimit.schema.js +51 -0
  177. package/dist/config/schemas/ratelimit.schema.js.map +1 -0
  178. package/dist/config/schemas/resilience.schema.d.ts +36 -0
  179. package/dist/config/schemas/resilience.schema.d.ts.map +1 -0
  180. package/dist/config/schemas/resilience.schema.js +91 -0
  181. package/dist/config/schemas/resilience.schema.js.map +1 -0
  182. package/dist/config/schemas/server.schema.d.ts +512 -0
  183. package/dist/config/schemas/server.schema.d.ts.map +1 -0
  184. package/dist/config/schemas/server.schema.js +104 -0
  185. package/dist/config/schemas/server.schema.js.map +1 -0
  186. package/dist/config/server-schema.d.ts +2 -0
  187. package/dist/config/server-schema.d.ts.map +1 -0
  188. package/dist/config/server-schema.js +2 -0
  189. package/dist/config/server-schema.js.map +1 -0
  190. package/dist/{server-schema.d.ts → core/cluster/ipc.protocol.d.ts} +4 -8
  191. package/dist/core/cluster/ipc.protocol.d.ts.map +1 -0
  192. package/dist/{server-schema.js → core/cluster/ipc.protocol.js} +5 -4
  193. package/dist/core/cluster/ipc.protocol.js.map +1 -0
  194. package/dist/core/cluster/master.d.ts +10 -0
  195. package/dist/core/cluster/master.d.ts.map +1 -0
  196. package/dist/core/cluster/master.js +875 -0
  197. package/dist/core/cluster/master.js.map +1 -0
  198. package/dist/core/cluster/worker.d.ts +2 -0
  199. package/dist/core/cluster/worker.d.ts.map +1 -0
  200. package/dist/core/cluster/worker.js +313 -0
  201. package/dist/core/cluster/worker.js.map +1 -0
  202. package/dist/core/pipeline/context.d.ts +12 -0
  203. package/dist/core/pipeline/context.d.ts.map +1 -0
  204. package/dist/core/pipeline/context.js +10 -0
  205. package/dist/core/pipeline/context.js.map +1 -0
  206. package/dist/core/pipeline/middleware.pipeline.d.ts +8 -0
  207. package/dist/core/pipeline/middleware.pipeline.d.ts.map +1 -0
  208. package/dist/core/pipeline/middleware.pipeline.js +18 -0
  209. package/dist/core/pipeline/middleware.pipeline.js.map +1 -0
  210. package/dist/core/proxy/connection.pool.d.ts +6 -0
  211. package/dist/core/proxy/connection.pool.d.ts.map +1 -0
  212. package/dist/core/proxy/connection.pool.js +18 -0
  213. package/dist/core/proxy/connection.pool.js.map +1 -0
  214. package/dist/core/proxy/http.handler.d.ts +18 -0
  215. package/dist/core/proxy/http.handler.d.ts.map +1 -0
  216. package/dist/core/proxy/http.handler.js +35 -0
  217. package/dist/core/proxy/http.handler.js.map +1 -0
  218. package/dist/core/proxy/upstream.client.d.ts +12 -0
  219. package/dist/core/proxy/upstream.client.d.ts.map +1 -0
  220. package/dist/core/proxy/upstream.client.js +13 -0
  221. package/dist/core/proxy/upstream.client.js.map +1 -0
  222. package/dist/core/proxy/websocket.handler.d.ts +12 -0
  223. package/dist/core/proxy/websocket.handler.d.ts.map +1 -0
  224. package/dist/core/proxy/websocket.handler.js +77 -0
  225. package/dist/core/proxy/websocket.handler.js.map +1 -0
  226. package/dist/core/router/route.matcher.d.ts +7 -0
  227. package/dist/core/router/route.matcher.d.ts.map +1 -0
  228. package/dist/core/router/route.matcher.js +16 -0
  229. package/dist/core/router/route.matcher.js.map +1 -0
  230. package/dist/core/router/route.types.d.ts +17 -0
  231. package/dist/core/router/route.types.d.ts.map +1 -0
  232. package/dist/core/router/route.types.js +2 -0
  233. package/dist/core/router/route.types.js.map +1 -0
  234. package/dist/core/router/router.d.ts +8 -0
  235. package/dist/core/router/router.d.ts.map +1 -0
  236. package/dist/core/router/router.js +14 -0
  237. package/dist/core/router/router.js.map +1 -0
  238. package/dist/discovery/contracts/registry.interface.d.ts +13 -0
  239. package/dist/discovery/contracts/registry.interface.d.ts.map +1 -0
  240. package/dist/discovery/contracts/registry.interface.js +2 -0
  241. package/dist/discovery/contracts/registry.interface.js.map +1 -0
  242. package/dist/discovery/health/active.probe.d.ts +10 -0
  243. package/dist/discovery/health/active.probe.d.ts.map +1 -0
  244. package/dist/discovery/health/active.probe.js +46 -0
  245. package/dist/discovery/health/active.probe.js.map +1 -0
  246. package/dist/discovery/health/health.manager.d.ts +18 -0
  247. package/dist/discovery/health/health.manager.d.ts.map +1 -0
  248. package/dist/discovery/health/health.manager.js +76 -0
  249. package/dist/discovery/health/health.manager.js.map +1 -0
  250. package/dist/discovery/health/passive.probe.d.ts +12 -0
  251. package/dist/discovery/health/passive.probe.d.ts.map +1 -0
  252. package/dist/discovery/health/passive.probe.js +12 -0
  253. package/dist/discovery/health/passive.probe.js.map +1 -0
  254. package/dist/discovery/index.d.ts +7 -0
  255. package/dist/discovery/index.d.ts.map +1 -0
  256. package/dist/discovery/index.js +6 -0
  257. package/dist/discovery/index.js.map +1 -0
  258. package/dist/{Serviceregistry.d.ts → discovery/registry/dynamic.registry.d.ts} +7 -3
  259. package/dist/discovery/registry/dynamic.registry.d.ts.map +1 -0
  260. package/dist/discovery/registry/dynamic.registry.js +138 -0
  261. package/dist/discovery/registry/dynamic.registry.js.map +1 -0
  262. package/dist/discovery/target-node.d.ts +12 -0
  263. package/dist/discovery/target-node.d.ts.map +1 -0
  264. package/dist/discovery/target-node.js +8 -0
  265. package/dist/discovery/target-node.js.map +1 -0
  266. package/dist/index.js +52 -16
  267. package/dist/index.js.map +1 -1
  268. package/dist/middleware/auth.middleware.d.ts +3 -0
  269. package/dist/middleware/auth.middleware.d.ts.map +1 -0
  270. package/dist/middleware/auth.middleware.js +15 -0
  271. package/dist/middleware/auth.middleware.js.map +1 -0
  272. package/dist/middleware/body-limit.middleware.d.ts +3 -0
  273. package/dist/middleware/body-limit.middleware.d.ts.map +1 -0
  274. package/dist/middleware/body-limit.middleware.js +12 -0
  275. package/dist/middleware/body-limit.middleware.js.map +1 -0
  276. package/dist/middleware/cache.middleware.d.ts +4 -0
  277. package/dist/middleware/cache.middleware.d.ts.map +1 -0
  278. package/dist/middleware/cache.middleware.js +16 -0
  279. package/dist/middleware/cache.middleware.js.map +1 -0
  280. package/dist/middleware/circuit.middleware.d.ts +3 -0
  281. package/dist/middleware/circuit.middleware.d.ts.map +1 -0
  282. package/dist/middleware/circuit.middleware.js +11 -0
  283. package/dist/middleware/circuit.middleware.js.map +1 -0
  284. package/dist/middleware/cors.middleware.d.ts +3 -0
  285. package/dist/middleware/cors.middleware.d.ts.map +1 -0
  286. package/dist/middleware/cors.middleware.js +19 -0
  287. package/dist/middleware/cors.middleware.js.map +1 -0
  288. package/dist/middleware/logging.middleware.d.ts +3 -0
  289. package/dist/middleware/logging.middleware.d.ts.map +1 -0
  290. package/dist/middleware/logging.middleware.js +9 -0
  291. package/dist/middleware/logging.middleware.js.map +1 -0
  292. package/dist/middleware/rate-limit.middleware.d.ts +4 -0
  293. package/dist/middleware/rate-limit.middleware.d.ts.map +1 -0
  294. package/dist/middleware/rate-limit.middleware.js +29 -0
  295. package/dist/middleware/rate-limit.middleware.js.map +1 -0
  296. package/dist/middleware/tracing.middleware.d.ts +3 -0
  297. package/dist/middleware/tracing.middleware.d.ts.map +1 -0
  298. package/dist/middleware/tracing.middleware.js +18 -0
  299. package/dist/middleware/tracing.middleware.js.map +1 -0
  300. package/dist/observability/health/readiness.d.ts +14 -0
  301. package/dist/observability/health/readiness.d.ts.map +1 -0
  302. package/dist/observability/health/readiness.js +23 -0
  303. package/dist/observability/health/readiness.js.map +1 -0
  304. package/dist/observability/index.d.ts +12 -0
  305. package/dist/observability/index.d.ts.map +1 -0
  306. package/dist/observability/index.js +8 -0
  307. package/dist/observability/index.js.map +1 -0
  308. package/dist/observability/logger/logger.d.ts +19 -0
  309. package/dist/observability/logger/logger.d.ts.map +1 -0
  310. package/dist/observability/logger/logger.js +83 -0
  311. package/dist/observability/logger/logger.js.map +1 -0
  312. package/dist/observability/logger/tenant-log.streamer.d.ts +29 -0
  313. package/dist/observability/logger/tenant-log.streamer.d.ts.map +1 -0
  314. package/dist/observability/logger/tenant-log.streamer.js +80 -0
  315. package/dist/observability/logger/tenant-log.streamer.js.map +1 -0
  316. package/dist/observability/metrics/histogram.registry.d.ts +43 -0
  317. package/dist/observability/metrics/histogram.registry.d.ts.map +1 -0
  318. package/dist/observability/metrics/histogram.registry.js +87 -0
  319. package/dist/observability/metrics/histogram.registry.js.map +1 -0
  320. package/dist/observability/metrics/prometheus.exporter.d.ts +19 -0
  321. package/dist/observability/metrics/prometheus.exporter.d.ts.map +1 -0
  322. package/dist/observability/metrics/prometheus.exporter.js +107 -0
  323. package/dist/observability/metrics/prometheus.exporter.js.map +1 -0
  324. package/dist/observability/metrics/system.metrics.d.ts +10 -0
  325. package/dist/observability/metrics/system.metrics.d.ts.map +1 -0
  326. package/dist/observability/metrics/system.metrics.js +20 -0
  327. package/dist/observability/metrics/system.metrics.js.map +1 -0
  328. package/dist/observability/tracing/tracer.d.ts +16 -0
  329. package/dist/observability/tracing/tracer.d.ts.map +1 -0
  330. package/dist/observability/tracing/tracer.js +24 -0
  331. package/dist/observability/tracing/tracer.js.map +1 -0
  332. package/dist/ratelimit/algorithms/fixed-window.d.ts +6 -0
  333. package/dist/ratelimit/algorithms/fixed-window.d.ts.map +1 -0
  334. package/dist/ratelimit/algorithms/fixed-window.js +20 -0
  335. package/dist/ratelimit/algorithms/fixed-window.js.map +1 -0
  336. package/dist/ratelimit/algorithms/leaking-bucket.d.ts +5 -0
  337. package/dist/ratelimit/algorithms/leaking-bucket.d.ts.map +1 -0
  338. package/dist/ratelimit/algorithms/leaking-bucket.js +17 -0
  339. package/dist/ratelimit/algorithms/leaking-bucket.js.map +1 -0
  340. package/dist/ratelimit/algorithms/sliding-window-counter.d.ts +5 -0
  341. package/dist/ratelimit/algorithms/sliding-window-counter.d.ts.map +1 -0
  342. package/dist/ratelimit/algorithms/sliding-window-counter.js +24 -0
  343. package/dist/ratelimit/algorithms/sliding-window-counter.js.map +1 -0
  344. package/dist/ratelimit/algorithms/sliding-window-log.d.ts +5 -0
  345. package/dist/ratelimit/algorithms/sliding-window-log.d.ts.map +1 -0
  346. package/dist/ratelimit/algorithms/sliding-window-log.js +16 -0
  347. package/dist/ratelimit/algorithms/sliding-window-log.js.map +1 -0
  348. package/dist/ratelimit/algorithms/token-bucket.d.ts +5 -0
  349. package/dist/ratelimit/algorithms/token-bucket.d.ts.map +1 -0
  350. package/dist/ratelimit/algorithms/token-bucket.js +19 -0
  351. package/dist/ratelimit/algorithms/token-bucket.js.map +1 -0
  352. package/dist/ratelimit/contracts/limiter.interface.d.ts +11 -0
  353. package/dist/ratelimit/contracts/limiter.interface.d.ts.map +1 -0
  354. package/dist/ratelimit/contracts/limiter.interface.js +2 -0
  355. package/dist/ratelimit/contracts/limiter.interface.js.map +1 -0
  356. package/dist/ratelimit/contracts/storage.interface.d.ts +6 -0
  357. package/dist/ratelimit/contracts/storage.interface.d.ts.map +1 -0
  358. package/dist/ratelimit/contracts/storage.interface.js +2 -0
  359. package/dist/ratelimit/contracts/storage.interface.js.map +1 -0
  360. package/dist/ratelimit/index.d.ts +16 -0
  361. package/dist/ratelimit/index.d.ts.map +1 -0
  362. package/dist/ratelimit/index.js +12 -0
  363. package/dist/ratelimit/index.js.map +1 -0
  364. package/dist/ratelimit/policies/multi-dimension.policy.d.ts +14 -0
  365. package/dist/ratelimit/policies/multi-dimension.policy.d.ts.map +1 -0
  366. package/dist/ratelimit/policies/multi-dimension.policy.js +13 -0
  367. package/dist/ratelimit/policies/multi-dimension.policy.js.map +1 -0
  368. package/dist/ratelimit/policies/soft-limit.policy.d.ts +8 -0
  369. package/dist/ratelimit/policies/soft-limit.policy.d.ts.map +1 -0
  370. package/dist/ratelimit/policies/soft-limit.policy.js +16 -0
  371. package/dist/ratelimit/policies/soft-limit.policy.js.map +1 -0
  372. package/dist/ratelimit/rate-limiter.d.ts +48 -0
  373. package/dist/ratelimit/rate-limiter.d.ts.map +1 -0
  374. package/dist/ratelimit/rate-limiter.js +420 -0
  375. package/dist/ratelimit/rate-limiter.js.map +1 -0
  376. package/dist/ratelimit/storage/hybrid.store.d.ts +10 -0
  377. package/dist/ratelimit/storage/hybrid.store.d.ts.map +1 -0
  378. package/dist/ratelimit/storage/hybrid.store.js +58 -0
  379. package/dist/ratelimit/storage/hybrid.store.js.map +1 -0
  380. package/dist/ratelimit/storage/memory.store.d.ts +8 -0
  381. package/dist/ratelimit/storage/memory.store.d.ts.map +1 -0
  382. package/dist/ratelimit/storage/memory.store.js +20 -0
  383. package/dist/ratelimit/storage/memory.store.js.map +1 -0
  384. package/dist/ratelimit/storage/redis.store.d.ts +10 -0
  385. package/dist/ratelimit/storage/redis.store.d.ts.map +1 -0
  386. package/dist/ratelimit/storage/redis.store.js +20 -0
  387. package/dist/ratelimit/storage/redis.store.js.map +1 -0
  388. package/dist/resilience/bulkhead/bulkhead.d.ts +11 -0
  389. package/dist/resilience/bulkhead/bulkhead.d.ts.map +1 -0
  390. package/dist/resilience/bulkhead/bulkhead.js +38 -0
  391. package/dist/resilience/bulkhead/bulkhead.js.map +1 -0
  392. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.d.ts +17 -0
  393. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.d.ts.map +1 -0
  394. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.js +33 -0
  395. package/dist/resilience/circuit-breaker/adaptive.circuit-breaker.js.map +1 -0
  396. package/dist/resilience/circuit-breaker/circuit-breaker.manager.d.ts +9 -0
  397. package/dist/resilience/circuit-breaker/circuit-breaker.manager.d.ts.map +1 -0
  398. package/dist/resilience/circuit-breaker/circuit-breaker.manager.js +22 -0
  399. package/dist/resilience/circuit-breaker/circuit-breaker.manager.js.map +1 -0
  400. package/dist/resilience/circuit-breaker/classic.circuit-breaker.d.ts +15 -0
  401. package/dist/resilience/circuit-breaker/classic.circuit-breaker.d.ts.map +1 -0
  402. package/dist/resilience/circuit-breaker/classic.circuit-breaker.js +39 -0
  403. package/dist/resilience/circuit-breaker/classic.circuit-breaker.js.map +1 -0
  404. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.d.ts +6 -0
  405. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.d.ts.map +1 -0
  406. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.js +2 -0
  407. package/dist/resilience/circuit-breaker/contracts/circuit-breaker.interface.js.map +1 -0
  408. package/dist/resilience/circuit-breaker/states/closed.state.d.ts +5 -0
  409. package/dist/resilience/circuit-breaker/states/closed.state.d.ts.map +1 -0
  410. package/dist/resilience/circuit-breaker/states/closed.state.js +7 -0
  411. package/dist/resilience/circuit-breaker/states/closed.state.js.map +1 -0
  412. package/dist/resilience/circuit-breaker/states/half-open.state.d.ts +5 -0
  413. package/dist/resilience/circuit-breaker/states/half-open.state.d.ts.map +1 -0
  414. package/dist/resilience/circuit-breaker/states/half-open.state.js +7 -0
  415. package/dist/resilience/circuit-breaker/states/half-open.state.js.map +1 -0
  416. package/dist/resilience/circuit-breaker/states/open.state.d.ts +5 -0
  417. package/dist/resilience/circuit-breaker/states/open.state.d.ts.map +1 -0
  418. package/dist/resilience/circuit-breaker/states/open.state.js +7 -0
  419. package/dist/resilience/circuit-breaker/states/open.state.js.map +1 -0
  420. package/dist/resilience/index.d.ts +13 -0
  421. package/dist/resilience/index.d.ts.map +1 -0
  422. package/dist/resilience/index.js +11 -0
  423. package/dist/resilience/index.js.map +1 -0
  424. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.d.ts +2 -0
  425. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.d.ts.map +1 -0
  426. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.js +7 -0
  427. package/dist/resilience/retry/backoff/decorrelated-jitter.backoff.js.map +1 -0
  428. package/dist/resilience/retry/backoff/equal-jitter.backoff.d.ts +2 -0
  429. package/dist/resilience/retry/backoff/equal-jitter.backoff.d.ts.map +1 -0
  430. package/dist/resilience/retry/backoff/equal-jitter.backoff.js +6 -0
  431. package/dist/resilience/retry/backoff/equal-jitter.backoff.js.map +1 -0
  432. package/dist/resilience/retry/backoff/exponential.backoff.d.ts +2 -0
  433. package/dist/resilience/retry/backoff/exponential.backoff.d.ts.map +1 -0
  434. package/dist/resilience/retry/backoff/exponential.backoff.js +4 -0
  435. package/dist/resilience/retry/backoff/exponential.backoff.js.map +1 -0
  436. package/dist/resilience/retry/backoff/full-jitter.backoff.d.ts +2 -0
  437. package/dist/resilience/retry/backoff/full-jitter.backoff.d.ts.map +1 -0
  438. package/dist/resilience/retry/backoff/full-jitter.backoff.js +5 -0
  439. package/dist/resilience/retry/backoff/full-jitter.backoff.js.map +1 -0
  440. package/dist/resilience/retry/contracts/retry.interface.d.ts +5 -0
  441. package/dist/resilience/retry/contracts/retry.interface.d.ts.map +1 -0
  442. package/dist/resilience/retry/contracts/retry.interface.js +2 -0
  443. package/dist/resilience/retry/contracts/retry.interface.js.map +1 -0
  444. package/dist/resilience/retry/retry-budget.d.ts +17 -0
  445. package/dist/resilience/retry/retry-budget.d.ts.map +1 -0
  446. package/dist/resilience/retry/retry-budget.js +37 -0
  447. package/dist/resilience/retry/retry-budget.js.map +1 -0
  448. package/dist/resilience/retry/retry-handler.d.ts +7 -0
  449. package/dist/resilience/retry/retry-handler.d.ts.map +1 -0
  450. package/dist/resilience/retry/retry-handler.js +24 -0
  451. package/dist/resilience/retry/retry-handler.js.map +1 -0
  452. package/dist/server.d.ts +5 -9
  453. package/dist/server.d.ts.map +1 -1
  454. package/dist/server.js +12 -645
  455. package/dist/server.js.map +1 -1
  456. package/dist/types/balancer.types.d.ts +18 -0
  457. package/dist/types/balancer.types.d.ts.map +1 -0
  458. package/dist/types/balancer.types.js +2 -0
  459. package/dist/types/balancer.types.js.map +1 -0
  460. package/dist/types/common.types.d.ts +11 -0
  461. package/dist/types/common.types.d.ts.map +1 -0
  462. package/dist/types/common.types.js +2 -0
  463. package/dist/types/common.types.js.map +1 -0
  464. package/dist/types/config.types.d.ts +8 -0
  465. package/dist/types/config.types.d.ts.map +1 -0
  466. package/dist/types/config.types.js +2 -0
  467. package/dist/types/config.types.js.map +1 -0
  468. package/dist/types/http.types.d.ts +14 -0
  469. package/dist/types/http.types.d.ts.map +1 -0
  470. package/dist/types/http.types.js +2 -0
  471. package/dist/types/http.types.js.map +1 -0
  472. package/dist/types/index.d.ts +7 -0
  473. package/dist/types/index.d.ts.map +1 -0
  474. package/dist/types/index.js +2 -0
  475. package/dist/types/index.js.map +1 -0
  476. package/dist/types/resilience.types.d.ts +31 -0
  477. package/dist/types/resilience.types.d.ts.map +1 -0
  478. package/dist/types/resilience.types.js +2 -0
  479. package/dist/types/resilience.types.js.map +1 -0
  480. package/dist/types/upstream.types.d.ts +28 -0
  481. package/dist/types/upstream.types.d.ts.map +1 -0
  482. package/dist/types/upstream.types.js +2 -0
  483. package/dist/types/upstream.types.js.map +1 -0
  484. package/package.json +9 -3
  485. package/config.example.yaml +0 -99
  486. package/dist/Serviceregistry.d.ts.map +0 -1
  487. package/dist/Serviceregistry.js +0 -95
  488. package/dist/Serviceregistry.js.map +0 -1
  489. package/dist/auto-scaler.d.ts +0 -27
  490. package/dist/auto-scaler.d.ts.map +0 -1
  491. package/dist/auto-scaler.js +0 -133
  492. package/dist/auto-scaler.js.map +0 -1
  493. package/dist/cache.d.ts +0 -22
  494. package/dist/cache.d.ts.map +0 -1
  495. package/dist/cache.js +0 -112
  496. package/dist/cache.js.map +0 -1
  497. package/dist/config-schema.d.ts +0 -53
  498. package/dist/config-schema.d.ts.map +0 -1
  499. package/dist/config-schema.js +0 -78
  500. package/dist/config-schema.js.map +0 -1
  501. package/dist/config.d.ts +0 -47
  502. package/dist/config.d.ts.map +0 -1
  503. package/dist/config.js +0 -73
  504. package/dist/config.js.map +0 -1
  505. package/dist/health.d.ts +0 -5
  506. package/dist/health.d.ts.map +0 -1
  507. package/dist/health.js +0 -72
  508. package/dist/health.js.map +0 -1
  509. package/dist/loadBalancer.d.ts +0 -31
  510. package/dist/loadBalancer.d.ts.map +0 -1
  511. package/dist/loadBalancer.js +0 -171
  512. package/dist/loadBalancer.js.map +0 -1
  513. package/dist/metrics.d.ts +0 -14
  514. package/dist/metrics.d.ts.map +0 -1
  515. package/dist/metrics.js +0 -70
  516. package/dist/metrics.js.map +0 -1
  517. package/dist/rate-limiter.d.ts +0 -16
  518. package/dist/rate-limiter.d.ts.map +0 -1
  519. package/dist/rate-limiter.js +0 -59
  520. package/dist/rate-limiter.js.map +0 -1
  521. package/dist/server-schema.d.ts.map +0 -1
  522. package/dist/server-schema.js.map +0 -1
  523. package/monitoring/docker-compose.monitoring.yml +0 -22
  524. package/monitoring/prometheus.yml +0 -11
  525. package/monitoring/retry.t +0 -16
package/dist/server.js CHANGED
@@ -1,647 +1,14 @@
1
- import http from "http";
2
- import https from "https";
3
- import { readFileSync, promises as fs } from "fs";
4
- import path from "path";
5
- import net from "net";
6
- import cluster, { Worker } from "node:cluster";
7
- import { rootConfigSchema } from "./config-schema.js";
8
- import zlib from "zlib";
9
- import { workerMessageSchema, workerMessageReplySchema, } from "./server-schema.js";
10
- import { initialHealthCheck, startHealthChecks } from "./health.js";
11
- import { RateLimiter } from "./rate-limiter.js";
12
- import { LoadBalancer } from "./loadBalancer.js";
13
- import { registry } from "./Serviceregistry.js";
14
- import { Cache } from "./cache.js";
15
- import { MetricsRegistry } from "./metrics.js";
16
- let WORKER_POOL = [];
17
- let ACTIVE_CONFIG;
18
- let lb;
19
- let cache;
20
- let metricsRegistry;
21
- const HEALTHY_UPSTREAMS = new Set();
22
- const rateLimiters = new Map();
23
- async function writeAccessLog(logPath, clientIp, method, url, statusCode, bytesSent, latencyMs, userAgent) {
24
- if (!logPath)
25
- return;
26
- const timestamp = new Date().toISOString();
27
- const logLine = `${clientIp} - - [${timestamp}] "${method} ${url} HTTP/1.1" ${statusCode} ${bytesSent} "-" "${userAgent}" ${latencyMs.toFixed(2)}ms\n`;
28
- try {
29
- const fullPath = path.resolve(logPath);
30
- await fs.mkdir(path.dirname(fullPath), { recursive: true });
31
- await fs.appendFile(fullPath, logLine, "utf8");
32
- }
33
- catch (err) {
34
- console.error(`[Logger Error] Failed to write access log: ${err.message}`);
35
- }
36
- }
37
- function parseCookies(cookieHeader) {
38
- const list = {};
39
- if (!cookieHeader)
40
- return list;
41
- cookieHeader.split(";").forEach((cookie) => {
42
- const parts = cookie.split("=");
43
- if (parts[0]) {
44
- list[parts[0].trim()] = parts.slice(1).join("=").trim();
45
- }
46
- });
47
- return list;
48
- }
49
- export async function reloadServerConfig(newConfig) {
50
- console.log("[Master] Hot-reload initiated. Spawning replacement workers...");
51
- ACTIVE_CONFIG = newConfig;
52
- lb = new LoadBalancer({
53
- strategy: newConfig.server.loadBalancing.strategy,
54
- upstreams: newConfig.server.upstreams,
55
- failureThreshold: newConfig.server.loadBalancing.failureThreshold,
56
- recoveryTimeMs: newConfig.server.loadBalancing.recoveryTimeMs,
57
- });
58
- // Re-add dynamically registered services from registry
59
- registry.getAll().forEach((service) => {
60
- if (!lb.hasUpstream(service.id)) {
61
- lb.addUpstream(service.id, 1);
62
- }
63
- });
64
- const oldWorkers = [...WORKER_POOL];
65
- WORKER_POOL.length = 0;
66
- const targetWorkers = newConfig.server.workers ?? 2;
67
- for (let i = 0; i < targetWorkers; i++) {
68
- const worker = cluster.fork({
69
- APP_CONFIG: JSON.stringify(newConfig),
70
- });
71
- WORKER_POOL.push(worker);
72
- }
73
- console.log(`[Master] Retiring ${oldWorkers.length} old workers...`);
74
- for (const oldWorker of oldWorkers) {
75
- try {
76
- oldWorker.send(JSON.stringify({ type: "GRACEFUL_SHUTDOWN" }));
77
- setTimeout(() => {
78
- if (!oldWorker.isDead()) {
79
- oldWorker.kill("SIGTERM");
80
- }
81
- }, 15000);
82
- }
83
- catch { }
84
- }
85
- }
86
- export async function createServer(config) {
87
- ACTIVE_CONFIG = config.config;
88
- const { port, workerCount } = config;
89
- ACTIVE_CONFIG.server.upstreams.map((e) => HEALTHY_UPSTREAMS.add(e.id));
90
- if (cluster.isPrimary) {
91
- const sslOptions = {
92
- key: readFileSync("key.pem"),
93
- cert: readFileSync("cert.pem"),
94
- };
95
- ACTIVE_CONFIG.server.paths.forEach((p) => {
96
- if (p.rateLimit) {
97
- rateLimiters.set(p.path, new RateLimiter({
98
- windowMs: p.rateLimit.windowMs,
99
- maxRequests: p.rateLimit.maxRequests,
100
- }));
101
- }
102
- });
103
- cache = new Cache({
104
- enabled: ACTIVE_CONFIG.server.cache.enabled,
105
- host: ACTIVE_CONFIG.server.cache.host,
106
- port: ACTIVE_CONFIG.server.cache.port,
107
- ttlSeconds: ACTIVE_CONFIG.server.cache.ttlSeconds,
108
- });
109
- await cache.connect();
110
- metricsRegistry = new MetricsRegistry(HEALTHY_UPSTREAMS);
111
- lb = new LoadBalancer({
112
- strategy: ACTIVE_CONFIG.server.loadBalancing.strategy,
113
- upstreams: ACTIVE_CONFIG.server.upstreams,
114
- failureThreshold: ACTIVE_CONFIG.server.loadBalancing.failureThreshold,
115
- recoveryTimeMs: ACTIVE_CONFIG.server.loadBalancing.recoveryTimeMs,
116
- });
117
- registry.onRegister((service) => {
118
- HEALTHY_UPSTREAMS.add(service.id);
119
- if (!lb.hasUpstream(service.id)) {
120
- lb.addUpstream(service.id, 1);
121
- }
122
- });
123
- ACTIVE_CONFIG.server.upstreams.forEach((u) => {
124
- registry.register({ id: u.id, url: u.url });
125
- });
126
- cluster.on("exit", (worker) => {
127
- const idx = WORKER_POOL.indexOf(worker);
128
- if (idx !== -1) {
129
- WORKER_POOL.splice(idx, 1);
130
- const newWorker = cluster.fork({
131
- APP_CONFIG: JSON.stringify(ACTIVE_CONFIG),
132
- });
133
- WORKER_POOL.push(newWorker);
134
- }
135
- });
136
- for (let i = 0; i < workerCount; i++) {
137
- const worker = cluster.fork({
138
- APP_CONFIG: JSON.stringify(ACTIVE_CONFIG),
139
- });
140
- WORKER_POOL.push(worker);
141
- }
142
- function dispatchToWorker(payload, clientIp, res, attempt = 0, attemptedUpstreams = new Set(), startTime = performance.now()) {
143
- const pathRule = ACTIVE_CONFIG.server.paths.find((p) => payload.url.startsWith(p.path));
144
- let upstreamId = null;
145
- if (pathRule?.sticky) {
146
- const cookies = parseCookies(payload.headers.cookie);
147
- const stickId = cookies["NINJA_ROUTE"];
148
- if (stickId &&
149
- HEALTHY_UPSTREAMS.has(stickId) &&
150
- !attemptedUpstreams.has(stickId)) {
151
- upstreamId = stickId;
152
- }
153
- }
154
- if (!upstreamId) {
155
- upstreamId = lb.pickFiltered(HEALTHY_UPSTREAMS, clientIp, attemptedUpstreams);
156
- }
157
- if (!upstreamId) {
158
- res.writeHead(503, { "Content-Type": "application/json" });
159
- res.end(JSON.stringify({ error: "No healthy upstreams available" }));
160
- metricsRegistry.recordRequest(payload.requestType, payload.url, 503, "none", performance.now() - startTime);
161
- return;
162
- }
163
- attemptedUpstreams.add(upstreamId);
164
- metricsRegistry.recordActiveConnection(upstreamId, 1);
165
- const serviceInstance = registry.get(upstreamId);
166
- if (!serviceInstance) {
167
- res.writeHead(503);
168
- res.end("Service not found in registry");
169
- return;
170
- }
171
- const enrichedPayload = {
172
- ...payload,
173
- upstreamId,
174
- upstreamUrl: serviceInstance.url,
175
- };
176
- const worker = WORKER_POOL[attempt % WORKER_POOL.length];
177
- if (!worker) {
178
- res.writeHead(500);
179
- res.end("No worker available");
180
- return;
181
- }
182
- const requestId = `${Date.now()}-${Math.random()}`;
183
- worker.send(JSON.stringify({
184
- ...enrichedPayload,
185
- requestId,
186
- }));
187
- let timer;
188
- const handler = async (raw) => {
189
- const parsed = JSON.parse(raw);
190
- if (parsed.requestId !== requestId)
191
- return;
192
- worker.off("message", handler);
193
- clearTimeout(timer);
194
- const reply = await workerMessageReplySchema.parseAsync(parsed);
195
- const retryConfig = ACTIVE_CONFIG.server.loadBalancing.retry;
196
- if (reply.errorCode ||
197
- (reply.statusCode &&
198
- retryConfig.statusCodes.includes(reply.statusCode))) {
199
- console.log(`[CircuitBreaker] Failure on ${upstreamId}: errorCode=${reply.errorCode}, status=${reply.statusCode}`);
200
- lb.recordFailure(upstreamId);
201
- if (attempt < retryConfig.maxAttempts) {
202
- metricsRegistry.recordActiveConnection(upstreamId, -1);
203
- dispatchToWorker(payload, clientIp, res, attempt + 1, attemptedUpstreams, startTime);
204
- }
205
- else {
206
- metricsRegistry.recordActiveConnection(upstreamId, -1);
207
- res.writeHead(reply.statusCode ?? 502);
208
- res.end(reply.error || "Bad Gateway");
209
- metricsRegistry.recordRequest(payload.requestType, payload.url, reply.statusCode ?? 502, upstreamId, performance.now() - startTime);
210
- writeAccessLog(ACTIVE_CONFIG.server.accessLog, clientIp, payload.requestType, payload.url, reply.statusCode ?? 502, 0, performance.now() - startTime, payload.headers["user-agent"] ?? "-");
211
- }
212
- }
213
- else {
214
- lb.recordSuccess(upstreamId);
215
- metricsRegistry.recordActiveConnection(upstreamId, -1);
216
- metricsRegistry.recordRequest(payload.requestType, payload.url, reply.statusCode ?? 200, upstreamId, performance.now() - startTime);
217
- if (payload.requestType === "GET") {
218
- metricsRegistry.recordCacheOp("miss");
219
- }
220
- let responseData = reply.data;
221
- if (reply.isCompressed && reply.encoding === "gzip") {
222
- responseData = Buffer.from(reply.data, "base64");
223
- }
224
- if (payload.requestType === "GET" && !reply.isCompressed) {
225
- const cacheKey = cache.buildKey(payload.requestType, new URL(payload.url, "http://dummy").pathname);
226
- await cache.set(cacheKey, reply.data);
227
- }
228
- const responseHeaders = {
229
- "Access-Control-Allow-Origin": "*",
230
- "Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS",
231
- "Access-Control-Allow-Headers": "*",
232
- "Access-Control-Allow-Credentials": "true",
233
- ...(reply.headers || {}),
234
- };
235
- delete responseHeaders["content-length"];
236
- delete responseHeaders["transfer-encoding"];
237
- delete responseHeaders["connection"];
238
- if (pathRule?.sticky) {
239
- responseHeaders["Set-Cookie"] =
240
- `NINJA_ROUTE=${upstreamId}; Path=/; HttpOnly; SameSite=Lax`;
241
- }
242
- res.writeHead(reply.statusCode ?? 200, responseHeaders);
243
- res.end(responseData);
244
- writeAccessLog(ACTIVE_CONFIG.server.accessLog, clientIp, payload.requestType, payload.url, reply.statusCode ?? 200, Buffer.byteLength(responseData), performance.now() - startTime, payload.headers["user-agent"] ?? "-");
245
- }
246
- };
247
- timer = setTimeout(() => {
248
- worker.off("message", handler);
249
- metricsRegistry.recordActiveConnection(upstreamId, -1);
250
- res.writeHead(504);
251
- res.end("Gateway Timeout");
252
- metricsRegistry.recordRequest(payload.requestType, payload.url, 504, upstreamId, performance.now() - startTime);
253
- writeAccessLog(ACTIVE_CONFIG.server.accessLog, clientIp, payload.requestType, payload.url, 504, 0, performance.now() - startTime, payload.headers["user-agent"] ?? "-");
254
- }, ACTIVE_CONFIG.server.readTimeoutMs);
255
- worker.on("message", handler);
256
- }
257
- function handleWebSocketUpgrade(req, socket, head) {
258
- const url = new URL(req.url, `http://${req.headers.host}`);
259
- const pathRule = ACTIVE_CONFIG.server.paths.find((p) => url.pathname.startsWith(p.path));
260
- if (!pathRule) {
261
- socket.destroy();
262
- return;
263
- }
264
- const clientIP = req.headers["x-forwarded-for"] ??
265
- socket.remoteAddress ??
266
- "unknown";
267
- const upstreamId = lb.pickFiltered(HEALTHY_UPSTREAMS, clientIP, new Set());
268
- if (!upstreamId) {
269
- socket.destroy();
270
- return;
271
- }
272
- const serviceInstance = registry.get(upstreamId);
273
- if (!serviceInstance) {
274
- socket.destroy();
275
- return;
276
- }
277
- const upstreamUrl = new URL(serviceInstance.url);
278
- const targetSocket = net.connect({
279
- host: upstreamUrl.hostname,
280
- port: parseInt(upstreamUrl.port || "80"),
281
- }, () => {
282
- let rawRequest = `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n`;
283
- for (const [key, val] of Object.entries(req.headers)) {
284
- if (Array.isArray(val)) {
285
- val.forEach((v) => {
286
- rawRequest += `${key}: ${v}\r\n`;
287
- });
288
- }
289
- else {
290
- rawRequest += `${key}: ${val}\r\n`;
291
- }
292
- }
293
- rawRequest += "\r\n";
294
- targetSocket.write(rawRequest);
295
- if (head && head.length > 0) {
296
- targetSocket.write(head);
297
- }
298
- socket.pipe(targetSocket);
299
- targetSocket.pipe(socket);
300
- });
301
- targetSocket.on("error", () => {
302
- socket.destroy();
303
- });
304
- socket.on("error", () => {
305
- targetSocket.destroy();
306
- });
307
- }
308
- const httpServer = http.createServer((req, res) => {
309
- if (req.url?.startsWith("/__registry")) {
310
- httpsServer.emit("request", req, res);
311
- return;
312
- }
313
- const httpsUrl = `https://${req.headers.host?.replace(String(port), String(ACTIVE_CONFIG.server.httpsPort ?? 8443))}${req.url}`;
314
- res.writeHead(301, { Location: httpsUrl });
315
- res.end();
316
- });
317
- httpServer.on("upgrade", handleWebSocketUpgrade);
318
- const httpsServer = https.createServer(sslOptions, async (req, res) => {
319
- const clientIP = req.headers["x-forwarded-for"] ??
320
- req.socket.remoteAddress ??
321
- "unknown";
322
- if (req.method === "OPTIONS") {
323
- res.writeHead(204, {
324
- "Access-Control-Allow-Origin": "*",
325
- "Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS",
326
- "Access-Control-Allow-Headers": "*",
327
- "Access-Control-Allow-Credentials": "true",
328
- });
329
- res.end();
330
- return;
331
- }
332
- if (req.url === "/__lb-stats") {
333
- res.writeHead(200, { "Content-Type": "application/json" });
334
- res.end(JSON.stringify({
335
- strategy: ACTIVE_CONFIG.server.loadBalancing.strategy,
336
- upstreams: lb.getStats(),
337
- healthyUpstreams: [...HEALTHY_UPSTREAMS],
338
- }, null, 2));
339
- return;
340
- }
341
- if (req.url === "/metrics" || req.url === "/__metrics") {
342
- res.writeHead(200, {
343
- "Content-Type": "text/plain; version=0.0.4; charset=utf-8",
344
- });
345
- const allUpstreams = [
346
- ...new Set([
347
- ...ACTIVE_CONFIG.server.upstreams.map((u) => u.id),
348
- ...registry.getAll().map((s) => s.id),
349
- ]),
350
- ];
351
- res.end(metricsRegistry.getExpositionFormat(allUpstreams));
352
- return;
353
- }
354
- if (req.url === "/__registry") {
355
- res.writeHead(200, { "Content-Type": "application/json" });
356
- res.end(JSON.stringify(registry.getStats(), null, 2));
357
- return;
358
- }
359
- if (req.url === "/__cache-stats") {
360
- res.writeHead(200, { "Content-Type": "application/json" });
361
- res.end(JSON.stringify(cache.getStats(), null, 2));
362
- return;
363
- }
364
- if (req.url === "/__registry/register" && req.method === "POST") {
365
- let body = "";
366
- req.on("data", (chunk) => {
367
- body += chunk;
368
- });
369
- req.on("end", () => {
370
- try {
371
- const { id, url, metadata } = JSON.parse(body);
372
- if (!id || !url) {
373
- res.writeHead(400);
374
- res.end(JSON.stringify({ error: "id and url are required" }));
375
- return;
376
- }
377
- const service = registry.register({ id, url, metadata });
378
- res.writeHead(201, { "Content-Type": "application/json" });
379
- res.end(JSON.stringify({ message: `Service ${id} registered!`, service }));
380
- }
381
- catch {
382
- res.writeHead(400);
383
- res.end(JSON.stringify({ error: "Invalid JSON body" }));
384
- }
385
- });
386
- return;
387
- }
388
- const url = new URL(req.url, `https://${req.headers.host}`);
389
- const pathRule = ACTIVE_CONFIG.server.paths.find((p) => url.pathname.startsWith(p.path));
390
- if (pathRule?.rateLimit) {
391
- const routeLimiter = rateLimiters.get(pathRule.path);
392
- if (routeLimiter && !routeLimiter.isAllowed(clientIP)) {
393
- const retryAfter = Math.ceil((routeLimiter.getResetTime(clientIP) - Date.now()) / 1000);
394
- res.writeHead(429, {
395
- "Content-Type": "application/json",
396
- "Retry-After": retryAfter.toString(),
397
- "X-RateLimit-Remaining": "0",
398
- });
399
- res.end(JSON.stringify({
400
- error: "Too Many Requests",
401
- retryAfter: `${retryAfter}s`,
402
- }));
403
- return;
404
- }
405
- }
406
- if (req.method === "GET") {
407
- const skipCache = url.pathname.startsWith("/api/upload/");
408
- if (!skipCache) {
409
- const cacheKey = cache.buildKey("GET", url.pathname);
410
- const cached = await cache.get(cacheKey);
411
- if (cached) {
412
- res.writeHead(200, { "X-Cache": "HIT" });
413
- res.end(cached);
414
- metricsRegistry.recordCacheOp("hit");
415
- metricsRegistry.recordRequest("GET", req.url ?? "", 200, "cache", 0);
416
- writeAccessLog(ACTIVE_CONFIG.server.accessLog, clientIP, req.method, req.url ?? "", 200, Buffer.byteLength(cached), 0, req.headers["user-agent"] ?? "-");
417
- return;
418
- }
419
- }
420
- }
421
- if (["POST", "PUT", "PATCH", "DELETE"].includes(req.method ?? "")) {
422
- await cache.invalidate(url.pathname);
423
- }
424
- const chunks = [];
425
- req.on("data", (chunk) => {
426
- chunks.push(chunk);
427
- });
428
- req.on("end", () => {
429
- const bodyBuffer = Buffer.concat(chunks);
430
- const body = bodyBuffer.length > 0 ? bodyBuffer.toString("binary") : null;
431
- const payload = {
432
- requestType: (req.method ??
433
- "GET"),
434
- headers: req.headers,
435
- body: body,
436
- url: `${req.url}`,
437
- };
438
- dispatchToWorker(payload, clientIP, res);
439
- });
440
- });
441
- httpsServer.on("upgrade", handleWebSocketUpgrade);
442
- let isShuttingDown = false;
443
- async function gracefulShutdown(signal) {
444
- if (isShuttingDown)
445
- return;
446
- isShuttingDown = true;
447
- console.log(`\n[Master] Received ${signal} — draining and shutting down...`);
448
- await cache.disconnect();
449
- httpServer.close();
450
- httpsServer.close(() => {
451
- process.exit(0);
452
- });
453
- }
454
- process.on("SIGTERM", () => void gracefulShutdown("SIGTERM"));
455
- process.on("SIGINT", () => void gracefulShutdown("SIGINT"));
456
- await new Promise((res) => setTimeout(res, 3000));
457
- await initialHealthCheck(ACTIVE_CONFIG.server.upstreams, HEALTHY_UPSTREAMS);
458
- httpServer.listen(port);
459
- httpsServer.listen(ACTIVE_CONFIG.server.httpsPort ?? 8443, () => {
460
- startHealthChecks(ACTIVE_CONFIG.server.upstreams, HEALTHY_UPSTREAMS, lb);
461
- });
462
- }
463
- else {
464
- const workerConfig = await rootConfigSchema.parseAsync(JSON.parse(process.env.APP_CONFIG));
465
- process.on("message", (msgStr) => {
466
- try {
467
- const msg = JSON.parse(msgStr);
468
- if (msg.type === "GRACEFUL_SHUTDOWN") {
469
- console.log(`[Worker ${process.pid}] Gracefully draining connections...`);
470
- // Let process exit naturally after connections close
471
- }
472
- }
473
- catch { }
474
- });
475
- process.on("message", async (message) => {
476
- const msg = await workerMessageSchema.parseAsync(JSON.parse(message));
477
- const raw = JSON.parse(message);
478
- const upstreamUrl = raw.upstreamUrl;
479
- const requestUrl = msg.url;
480
- const rule = workerConfig.server.paths.find((e) => requestUrl.startsWith(e.path));
481
- if (!rule) {
482
- const reply = {
483
- requestId: raw.requestId,
484
- errorCode: "404",
485
- error: "Route not found",
486
- data: "",
487
- };
488
- if (process.send)
489
- process.send(JSON.stringify(reply));
490
- return;
491
- }
492
- let finalUpstreamUrl;
493
- if (upstreamUrl) {
494
- finalUpstreamUrl = new URL(upstreamUrl);
495
- }
496
- else {
497
- const upstream = workerConfig.server.upstreams.find((e) => e.id === rule.upstream[0]);
498
- if (!upstream) {
499
- const reply = {
500
- requestId: raw.requestId,
501
- errorCode: "500",
502
- error: "Upstream not found",
503
- data: "",
504
- };
505
- if (process.send)
506
- process.send(JSON.stringify(reply));
507
- return;
508
- }
509
- finalUpstreamUrl = new URL(upstream.url);
510
- }
511
- const agent = new http.Agent({
512
- keepAlive: true,
513
- maxSockets: 5000,
514
- });
515
- let connectTimeoutTimer;
516
- let readTimeoutTimer;
517
- const proxyReq = http.request({
518
- host: finalUpstreamUrl.hostname,
519
- port: finalUpstreamUrl.port,
520
- path: requestUrl,
521
- method: msg.requestType,
522
- agent: agent,
523
- headers: {
524
- ...msg.headers,
525
- "X-Forwarded-For": msg.headers["x-forwarded-for"] || "unknown",
526
- "X-Real-IP": "127.0.0.1",
527
- "X-Proxy-By": "Ninja-Reverse-Proxy",
528
- ...(msg.body && {
529
- "Content-Length": Buffer.byteLength(msg.body).toString(),
530
- }),
531
- },
532
- }, (upstreamRes) => {
533
- clearTimeout(connectTimeoutTimer);
534
- const chunks = [];
535
- upstreamRes.on("data", (chunk) => {
536
- chunks.push(chunk);
537
- });
538
- upstreamRes.on("end", () => {
539
- clearTimeout(readTimeoutTimer);
540
- const bodyBuffer = Buffer.concat(chunks);
541
- const acceptEncoding = msg.headers["accept-encoding"] || "";
542
- const contentType = upstreamRes.headers["content-type"] || "";
543
- const isCompressible = /json|text|javascript|css/.test(contentType);
544
- const upstreamEncoding = upstreamRes.headers["content-encoding"];
545
- // Strip content-encoding from upstream headers — we decompress first,
546
- // then optionally re-compress via the proxy's own compression layer.
547
- const forwardHeaders = { ...upstreamRes.headers };
548
- delete forwardHeaders["content-encoding"];
549
- const sendReply = (rawBody) => {
550
- if (workerConfig.server.compression &&
551
- isCompressible &&
552
- acceptEncoding.includes("gzip")) {
553
- zlib.gzip(rawBody, (err, compressed) => {
554
- const reply = {
555
- requestId: raw.requestId,
556
- data: err
557
- ? rawBody.toString("utf8")
558
- : compressed.toString("base64"),
559
- isCompressed: !err,
560
- encoding: err ? undefined : "gzip",
561
- statusCode: upstreamRes.statusCode ?? 200,
562
- headers: err
563
- ? forwardHeaders
564
- : { ...forwardHeaders, "content-encoding": "gzip" },
565
- };
566
- if (process.send)
567
- process.send(JSON.stringify(reply));
568
- });
569
- }
570
- else {
571
- const reply = {
572
- requestId: raw.requestId,
573
- data: rawBody.toString("utf8"),
574
- statusCode: upstreamRes.statusCode ?? 200,
575
- headers: forwardHeaders,
576
- };
577
- if (process.send)
578
- process.send(JSON.stringify(reply));
579
- }
580
- };
581
- if (upstreamEncoding === "gzip") {
582
- zlib.gunzip(bodyBuffer, (err, decompressed) => {
583
- if (err) {
584
- // Decompression failed — send raw bytes as base64 with original headers
585
- const reply = {
586
- requestId: raw.requestId,
587
- data: bodyBuffer.toString("base64"),
588
- isCompressed: true,
589
- encoding: "gzip",
590
- statusCode: upstreamRes.statusCode ?? 200,
591
- headers: upstreamRes.headers,
592
- };
593
- if (process.send)
594
- process.send(JSON.stringify(reply));
595
- }
596
- else {
597
- sendReply(decompressed);
598
- }
599
- });
600
- }
601
- else {
602
- sendReply(bodyBuffer);
603
- }
604
- });
605
- });
606
- connectTimeoutTimer = setTimeout(() => {
607
- proxyReq.destroy();
608
- const reply = {
609
- requestId: raw.requestId,
610
- errorCode: "504",
611
- error: "Connect Timeout",
612
- data: "",
613
- };
614
- if (process.send)
615
- process.send(JSON.stringify(reply));
616
- }, workerConfig.server.connectTimeoutMs);
617
- readTimeoutTimer = setTimeout(() => {
618
- proxyReq.destroy();
619
- const reply = {
620
- requestId: raw.requestId,
621
- errorCode: "504",
622
- error: "Read Timeout",
623
- data: "",
624
- };
625
- if (process.send)
626
- process.send(JSON.stringify(reply));
627
- }, workerConfig.server.readTimeoutMs);
628
- proxyReq.on("error", (err) => {
629
- clearTimeout(connectTimeoutTimer);
630
- clearTimeout(readTimeoutTimer);
631
- const reply = {
632
- requestId: raw.requestId,
633
- errorCode: "502",
634
- error: `Upstream connection failed: ${err.message}`,
635
- data: "",
636
- };
637
- if (process.send)
638
- process.send(JSON.stringify(reply));
639
- });
640
- if (msg.body) {
641
- proxyReq.write(Buffer.from(msg.body, "binary"));
642
- }
643
- proxyReq.end();
644
- });
645
- }
1
+ import http from 'http';
2
+ import https from 'https';
3
+ import { readFileSync } from 'fs';
4
+ export function createHttpServer(handler) {
5
+ return http.createServer(handler);
6
+ }
7
+ export function createHttpsServer(config, handler) {
8
+ const sslOptions = {
9
+ key: readFileSync('key.pem'),
10
+ cert: readFileSync('cert.pem'),
11
+ };
12
+ return https.createServer(sslOptions, handler);
646
13
  }
647
14
  //# sourceMappingURL=server.js.map