@morojs/moro 1.7.30 → 1.8.1
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.
- package/README.md +89 -46
- package/dist/core/auth/morojs-adapter.js +95 -45
- package/dist/core/auth/morojs-adapter.js.map +1 -1
- package/dist/core/config/config-manager.js.map +1 -1
- package/dist/core/config/config-sources.js +119 -48
- package/dist/core/config/config-sources.js.map +1 -1
- package/dist/core/config/config-validator.js +189 -8
- package/dist/core/config/config-validator.js.map +1 -1
- package/dist/core/config/file-loader.js.map +1 -1
- package/dist/core/config/index.js.map +1 -1
- package/dist/core/config/schema.js +35 -4
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/config/utils.js.map +1 -1
- package/dist/core/database/adapters/drizzle.js +2 -2
- package/dist/core/database/adapters/drizzle.js.map +1 -1
- package/dist/core/database/adapters/index.js.map +1 -1
- package/dist/core/database/adapters/mongodb.d.ts +1 -0
- package/dist/core/database/adapters/mongodb.js +16 -0
- package/dist/core/database/adapters/mongodb.js.map +1 -1
- package/dist/core/database/adapters/mysql.d.ts +1 -0
- package/dist/core/database/adapters/mysql.js +13 -2
- package/dist/core/database/adapters/mysql.js.map +1 -1
- package/dist/core/database/adapters/postgresql.js +2 -2
- package/dist/core/database/adapters/postgresql.js.map +1 -1
- package/dist/core/database/adapters/redis.js.map +1 -1
- package/dist/core/database/adapters/sql-safety.js +5 -4
- package/dist/core/database/adapters/sql-safety.js.map +1 -1
- package/dist/core/database/adapters/sqlite.js.map +1 -1
- package/dist/core/database/index.js.map +1 -1
- package/dist/core/docs/index.js +11 -7
- package/dist/core/docs/index.js.map +1 -1
- package/dist/core/docs/openapi-generator.js +8 -6
- package/dist/core/docs/openapi-generator.js.map +1 -1
- package/dist/core/docs/schema-to-openapi.js +3 -3
- package/dist/core/docs/schema-to-openapi.js.map +1 -1
- package/dist/core/docs/simple-docs.js.map +1 -1
- package/dist/core/docs/swagger-ui.js.map +1 -1
- package/dist/core/docs/zod-to-openapi.js +2 -2
- package/dist/core/docs/zod-to-openapi.js.map +1 -1
- package/dist/core/events/event-bus.js +14 -5
- package/dist/core/events/event-bus.js.map +1 -1
- package/dist/core/events/index.js.map +1 -1
- package/dist/core/framework.d.ts +41 -3
- package/dist/core/framework.js +342 -95
- package/dist/core/framework.js.map +1 -1
- package/dist/core/graphql/adapter.js.map +1 -1
- package/dist/core/graphql/adapters/graphql-js-adapter.js.map +1 -1
- package/dist/core/graphql/core.js.map +1 -1
- package/dist/core/graphql/index.js.map +1 -1
- package/dist/core/graphql/loader.js.map +1 -1
- package/dist/core/graphql/types.js.map +1 -1
- package/dist/core/grpc/adapters/grpc-js-adapter.js +4 -0
- package/dist/core/grpc/adapters/grpc-js-adapter.js.map +1 -1
- package/dist/core/grpc/adapters/index.js.map +1 -1
- package/dist/core/grpc/grpc-adapter.js.map +1 -1
- package/dist/core/grpc/grpc-manager.js.map +1 -1
- package/dist/core/grpc/index.js.map +1 -1
- package/dist/core/grpc/middleware/auth.js +1 -1
- package/dist/core/grpc/middleware/auth.js.map +1 -1
- package/dist/core/grpc/middleware/logging.js.map +1 -1
- package/dist/core/grpc/middleware/validation.js +1 -1
- package/dist/core/grpc/middleware/validation.js.map +1 -1
- package/dist/core/grpc/types.d.ts +7 -7
- package/dist/core/grpc/types.js.map +1 -1
- package/dist/core/http/http-server.d.ts +17 -23
- package/dist/core/http/http-server.js +109 -249
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/http2-server.d.ts +6 -16
- package/dist/core/http/http2-server.js +40 -83
- package/dist/core/http/http2-server.js.map +1 -1
- package/dist/core/http/index.d.ts +1 -0
- package/dist/core/http/index.js +3 -0
- package/dist/core/http/index.js.map +1 -1
- package/dist/core/http/moro-engine-server.d.ts +263 -0
- package/dist/core/http/moro-engine-server.js +1962 -0
- package/dist/core/http/moro-engine-server.js.map +1 -0
- package/dist/core/http/utils/compression.d.ts +47 -0
- package/dist/core/http/utils/compression.js +132 -0
- package/dist/core/http/utils/compression.js.map +1 -0
- package/dist/core/http/utils/lazy-event-emitter.d.ts +11 -0
- package/dist/core/http/utils/lazy-event-emitter.js +69 -0
- package/dist/core/http/utils/lazy-event-emitter.js.map +1 -0
- package/dist/core/http/utils/multipart-parser.d.ts +32 -0
- package/dist/core/http/utils/multipart-parser.js +215 -0
- package/dist/core/http/utils/multipart-parser.js.map +1 -0
- package/dist/core/http/utils/query-parser.d.ts +1 -0
- package/dist/core/http/utils/query-parser.js +44 -0
- package/dist/core/http/utils/query-parser.js.map +1 -0
- package/dist/core/http/utils/size.d.ts +33 -0
- package/dist/core/http/utils/size.js +37 -0
- package/dist/core/http/utils/size.js.map +1 -0
- package/dist/core/http/utils/ssl-config.d.ts +69 -0
- package/dist/core/http/utils/ssl-config.js +116 -0
- package/dist/core/http/utils/ssl-config.js.map +1 -0
- package/dist/core/http/utils/uws-worker-clustering.js +45 -32
- package/dist/core/http/utils/uws-worker-clustering.js.map +1 -1
- package/dist/core/http/uws-http-server.d.ts +25 -3
- package/dist/core/http/uws-http-server.js +465 -86
- package/dist/core/http/uws-http-server.js.map +1 -1
- package/dist/core/jobs/cron-parser.js +7 -5
- package/dist/core/jobs/cron-parser.js.map +1 -1
- package/dist/core/jobs/index.js.map +1 -1
- package/dist/core/jobs/job-executor.d.ts +1 -1
- package/dist/core/jobs/job-executor.js.map +1 -1
- package/dist/core/jobs/job-scheduler.d.ts +3 -3
- package/dist/core/jobs/job-scheduler.js.map +1 -1
- package/dist/core/jobs/job-state-manager.d.ts +3 -3
- package/dist/core/jobs/job-state-manager.js +25 -4
- package/dist/core/jobs/job-state-manager.js.map +1 -1
- package/dist/core/jobs/leader-election.d.ts +15 -0
- package/dist/core/jobs/leader-election.js +158 -69
- package/dist/core/jobs/leader-election.js.map +1 -1
- package/dist/core/jobs/types.d.ts +4 -4
- package/dist/core/jobs/types.js.map +1 -1
- package/dist/core/jobs/utils.d.ts +1 -1
- package/dist/core/jobs/utils.js +7 -3
- package/dist/core/jobs/utils.js.map +1 -1
- package/dist/core/logger/filters.js +3 -2
- package/dist/core/logger/filters.js.map +1 -1
- package/dist/core/logger/index.js.map +1 -1
- package/dist/core/logger/logger.js +56 -25
- package/dist/core/logger/logger.js.map +1 -1
- package/dist/core/logger/outputs.js.map +1 -1
- package/dist/core/mail/adapters/console-adapter.js.map +1 -1
- package/dist/core/mail/adapters/index.js.map +1 -1
- package/dist/core/mail/adapters/nodemailer-adapter.js.map +1 -1
- package/dist/core/mail/adapters/resend-adapter.js.map +1 -1
- package/dist/core/mail/adapters/sendgrid-adapter.js.map +1 -1
- package/dist/core/mail/adapters/ses-adapter.js.map +1 -1
- package/dist/core/mail/index.js.map +1 -1
- package/dist/core/mail/mail-adapter.js.map +1 -1
- package/dist/core/mail/mail-manager.d.ts +10 -0
- package/dist/core/mail/mail-manager.js +21 -5
- package/dist/core/mail/mail-manager.js.map +1 -1
- package/dist/core/mail/template-engine.js.map +1 -1
- package/dist/core/mail/types.js.map +1 -1
- package/dist/core/middleware/built-in/auth/core.js +3 -3
- package/dist/core/middleware/built-in/auth/core.js.map +1 -1
- package/dist/core/middleware/built-in/auth/helpers.js +4 -4
- package/dist/core/middleware/built-in/auth/helpers.js.map +1 -1
- package/dist/core/middleware/built-in/auth/hook.js.map +1 -1
- package/dist/core/middleware/built-in/auth/index.js.map +1 -1
- package/dist/core/middleware/built-in/auth/jwt-helpers.d.ts +4 -4
- package/dist/core/middleware/built-in/auth/jwt-helpers.js.map +1 -1
- package/dist/core/middleware/built-in/auth/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/auth/providers.js.map +1 -1
- package/dist/core/middleware/built-in/body-parsers/index.js.map +1 -1
- package/dist/core/middleware/built-in/body-size/core.js +2 -2
- package/dist/core/middleware/built-in/body-size/core.js.map +1 -1
- package/dist/core/middleware/built-in/body-size/hook.js.map +1 -1
- package/dist/core/middleware/built-in/body-size/index.js.map +1 -1
- package/dist/core/middleware/built-in/body-size/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/file.js +3 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/file.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/index.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/memory.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/cache/redis.js.map +1 -1
- package/dist/core/middleware/built-in/cache/adapters/index.js.map +1 -1
- package/dist/core/middleware/built-in/cache/core.js.map +1 -1
- package/dist/core/middleware/built-in/cache/hook.js +3 -3
- package/dist/core/middleware/built-in/cache/hook.js.map +1 -1
- package/dist/core/middleware/built-in/cache/index.js.map +1 -1
- package/dist/core/middleware/built-in/cache/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudfront.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/cdn/index.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/adapters/index.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/core.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/hook.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/index.js.map +1 -1
- package/dist/core/middleware/built-in/cdn/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/compression/core.d.ts +3 -0
- package/dist/core/middleware/built-in/compression/core.js +28 -34
- package/dist/core/middleware/built-in/compression/core.js.map +1 -1
- package/dist/core/middleware/built-in/compression/hook.js.map +1 -1
- package/dist/core/middleware/built-in/compression/index.js.map +1 -1
- package/dist/core/middleware/built-in/compression/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/cookie/core.js.map +1 -1
- package/dist/core/middleware/built-in/cookie/hook.js.map +1 -1
- package/dist/core/middleware/built-in/cookie/index.js.map +1 -1
- package/dist/core/middleware/built-in/cookie/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/cors/core.js.map +1 -1
- package/dist/core/middleware/built-in/cors/hook.js.map +1 -1
- package/dist/core/middleware/built-in/cors/index.js.map +1 -1
- package/dist/core/middleware/built-in/cors/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/csp/core.js.map +1 -1
- package/dist/core/middleware/built-in/csp/hook.js.map +1 -1
- package/dist/core/middleware/built-in/csp/index.js.map +1 -1
- package/dist/core/middleware/built-in/csp/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/csrf/core.js +1 -1
- package/dist/core/middleware/built-in/csrf/core.js.map +1 -1
- package/dist/core/middleware/built-in/csrf/hook.js.map +1 -1
- package/dist/core/middleware/built-in/csrf/index.js.map +1 -1
- package/dist/core/middleware/built-in/csrf/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/error-tracker/index.js.map +1 -1
- package/dist/core/middleware/built-in/error-tracker/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/graphql/core.js.map +1 -1
- package/dist/core/middleware/built-in/graphql/helpers.js.map +1 -1
- package/dist/core/middleware/built-in/graphql/hook.js.map +1 -1
- package/dist/core/middleware/built-in/graphql/index.js.map +1 -1
- package/dist/core/middleware/built-in/graphql/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/graphql/subscriptions.js.map +1 -1
- package/dist/core/middleware/built-in/helmet/core.js.map +1 -1
- package/dist/core/middleware/built-in/helmet/hook.js.map +1 -1
- package/dist/core/middleware/built-in/helmet/index.js.map +1 -1
- package/dist/core/middleware/built-in/helmet/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/http2/core.js.map +1 -1
- package/dist/core/middleware/built-in/http2/hook.js.map +1 -1
- package/dist/core/middleware/built-in/http2/index.js.map +1 -1
- package/dist/core/middleware/built-in/http2/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/index.js.map +1 -1
- package/dist/core/middleware/built-in/performance-monitor/index.js.map +1 -1
- package/dist/core/middleware/built-in/performance-monitor/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/range/core.js +4 -1
- package/dist/core/middleware/built-in/range/core.js.map +1 -1
- package/dist/core/middleware/built-in/range/hook.js.map +1 -1
- package/dist/core/middleware/built-in/range/index.js.map +1 -1
- package/dist/core/middleware/built-in/range/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/rate-limit/core.js.map +1 -1
- package/dist/core/middleware/built-in/rate-limit/hook.js.map +1 -1
- package/dist/core/middleware/built-in/rate-limit/index.js.map +1 -1
- package/dist/core/middleware/built-in/rate-limit/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger/index.js.map +1 -1
- package/dist/core/middleware/built-in/request-logger/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/session/core.js +4 -4
- package/dist/core/middleware/built-in/session/core.js.map +1 -1
- package/dist/core/middleware/built-in/session/hook.js.map +1 -1
- package/dist/core/middleware/built-in/session/index.js.map +1 -1
- package/dist/core/middleware/built-in/session/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/sse/core.js.map +1 -1
- package/dist/core/middleware/built-in/sse/hook.js.map +1 -1
- package/dist/core/middleware/built-in/sse/index.js.map +1 -1
- package/dist/core/middleware/built-in/sse/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/static/core.js.map +1 -1
- package/dist/core/middleware/built-in/static/hook.js.map +1 -1
- package/dist/core/middleware/built-in/static/index.js.map +1 -1
- package/dist/core/middleware/built-in/static/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/template/core.js +1 -1
- package/dist/core/middleware/built-in/template/core.js.map +1 -1
- package/dist/core/middleware/built-in/template/hook.js.map +1 -1
- package/dist/core/middleware/built-in/template/index.js.map +1 -1
- package/dist/core/middleware/built-in/template/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/upload/core.js.map +1 -1
- package/dist/core/middleware/built-in/upload/hook.js.map +1 -1
- package/dist/core/middleware/built-in/upload/index.js.map +1 -1
- package/dist/core/middleware/built-in/upload/middleware.js.map +1 -1
- package/dist/core/middleware/built-in/validation/core.js.map +1 -1
- package/dist/core/middleware/built-in/validation/hook.js.map +1 -1
- package/dist/core/middleware/built-in/validation/index.js.map +1 -1
- package/dist/core/middleware/built-in/validation/middleware.js.map +1 -1
- package/dist/core/middleware/index.js +2 -2
- package/dist/core/middleware/index.js.map +1 -1
- package/dist/core/modules/auto-discovery.js +11 -7
- package/dist/core/modules/auto-discovery.js.map +1 -1
- package/dist/core/modules/index.js.map +1 -1
- package/dist/core/modules/modules.js +18 -13
- package/dist/core/modules/modules.js.map +1 -1
- package/dist/core/networking/adapters/engine-adapter.d.ts +23 -0
- package/dist/core/networking/adapters/engine-adapter.js +365 -0
- package/dist/core/networking/adapters/engine-adapter.js.map +1 -0
- package/dist/core/networking/adapters/index.d.ts +1 -0
- package/dist/core/networking/adapters/index.js +1 -0
- package/dist/core/networking/adapters/index.js.map +1 -1
- package/dist/core/networking/adapters/socketio-adapter.d.ts +1 -0
- package/dist/core/networking/adapters/socketio-adapter.js +12 -1
- package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
- package/dist/core/networking/adapters/uws-adapter.js +27 -16
- package/dist/core/networking/adapters/uws-adapter.js.map +1 -1
- package/dist/core/networking/adapters/ws-adapter.d.ts +15 -0
- package/dist/core/networking/adapters/ws-adapter.js +120 -6
- package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
- package/dist/core/networking/index.js.map +1 -1
- package/dist/core/networking/service-discovery.js +7 -5
- package/dist/core/networking/service-discovery.js.map +1 -1
- package/dist/core/networking/websocket-adapter.d.ts +22 -3
- package/dist/core/networking/websocket-adapter.js.map +1 -1
- package/dist/core/networking/websocket-manager.js +70 -67
- package/dist/core/networking/websocket-manager.js.map +1 -1
- package/dist/core/pooling/object-pool-manager.js +6 -0
- package/dist/core/pooling/object-pool-manager.js.map +1 -1
- package/dist/core/queue/adapters/bull-adapter.js.map +1 -1
- package/dist/core/queue/adapters/index.js.map +1 -1
- package/dist/core/queue/adapters/kafka-adapter.js +2 -2
- package/dist/core/queue/adapters/kafka-adapter.js.map +1 -1
- package/dist/core/queue/adapters/memory-adapter.js +6 -6
- package/dist/core/queue/adapters/memory-adapter.js.map +1 -1
- package/dist/core/queue/adapters/rabbitmq-adapter.d.ts +50 -0
- package/dist/core/queue/adapters/rabbitmq-adapter.js +176 -20
- package/dist/core/queue/adapters/rabbitmq-adapter.js.map +1 -1
- package/dist/core/queue/adapters/sqs-adapter.d.ts +12 -2
- package/dist/core/queue/adapters/sqs-adapter.js +75 -24
- package/dist/core/queue/adapters/sqs-adapter.js.map +1 -1
- package/dist/core/queue/index.js.map +1 -1
- package/dist/core/queue/middleware/index.js.map +1 -1
- package/dist/core/queue/middleware/monitoring.d.ts +1 -1
- package/dist/core/queue/middleware/monitoring.js.map +1 -1
- package/dist/core/queue/middleware/priority.js +2 -1
- package/dist/core/queue/middleware/priority.js.map +1 -1
- package/dist/core/queue/middleware/rate-limit.js.map +1 -1
- package/dist/core/queue/queue-adapter.js.map +1 -1
- package/dist/core/queue/queue-manager.js.map +1 -1
- package/dist/core/queue/types.d.ts +8 -8
- package/dist/core/queue/types.js.map +1 -1
- package/dist/core/routing/app-integration.js.map +1 -1
- package/dist/core/routing/create-router.js.map +1 -1
- package/dist/core/routing/index.js.map +1 -1
- package/dist/core/routing/path-matcher.js.map +1 -1
- package/dist/core/routing/radix-tree.js.map +1 -1
- package/dist/core/routing/router.js.map +1 -1
- package/dist/core/routing/unified-router.js +12 -4
- package/dist/core/routing/unified-router.js.map +1 -1
- package/dist/core/runtime/aws-lambda-adapter.js.map +1 -1
- package/dist/core/runtime/base-adapter.js +2 -2
- package/dist/core/runtime/base-adapter.js.map +1 -1
- package/dist/core/runtime/cloudflare-workers-adapter.js +2 -0
- package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
- package/dist/core/runtime/index.js.map +1 -1
- package/dist/core/runtime/node-adapter.js +19 -17
- package/dist/core/runtime/node-adapter.js.map +1 -1
- package/dist/core/runtime/vercel-edge-adapter.js +2 -0
- package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
- package/dist/core/utilities/circuit-breaker.d.ts +1 -0
- package/dist/core/utilities/circuit-breaker.js +25 -2
- package/dist/core/utilities/circuit-breaker.js.map +1 -1
- package/dist/core/utilities/container.js +9 -9
- package/dist/core/utilities/container.js.map +1 -1
- package/dist/core/utilities/hooks.js +28 -6
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/core/utilities/index.js.map +1 -1
- package/dist/core/utilities/module-path.js.map +1 -1
- package/dist/core/utilities/package-utils.d.ts +68 -0
- package/dist/core/utilities/package-utils.js +198 -1
- package/dist/core/utilities/package-utils.js.map +1 -1
- package/dist/core/utilities/response-helpers.js +1 -1
- package/dist/core/utilities/response-helpers.js.map +1 -1
- package/dist/core/validation/adapters.js.map +1 -1
- package/dist/core/validation/error-handler.js.map +1 -1
- package/dist/core/validation/index.js.map +1 -1
- package/dist/core/validation/schema-interface.js.map +1 -1
- package/dist/core/workers/facade.js.map +1 -1
- package/dist/core/workers/index.js.map +1 -1
- package/dist/core/workers/worker-entry.d.ts +1 -0
- package/dist/core/workers/worker-entry.js +12 -0
- package/dist/core/workers/worker-entry.js.map +1 -0
- package/dist/core/workers/worker-manager.d.ts +23 -2
- package/dist/core/workers/worker-manager.js +117 -17
- package/dist/core/workers/worker-manager.js.map +1 -1
- package/dist/core/workers/worker.js +8 -6
- package/dist/core/workers/worker.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/moro.d.ts +20 -1
- package/dist/moro.js +230 -70
- package/dist/moro.js.map +1 -1
- package/dist/types/auth.d.ts +4 -4
- package/dist/types/auth.js.map +1 -1
- package/dist/types/cache.js.map +1 -1
- package/dist/types/cdn.js.map +1 -1
- package/dist/types/config.d.ts +100 -15
- package/dist/types/config.js.map +1 -1
- package/dist/types/core.js.map +1 -1
- package/dist/types/database.js.map +1 -1
- package/dist/types/discovery.js.map +1 -1
- package/dist/types/events.js.map +1 -1
- package/dist/types/hooks.js.map +1 -1
- package/dist/types/http.js.map +1 -1
- package/dist/types/logger.js.map +1 -1
- package/dist/types/module.js.map +1 -1
- package/dist/types/runtime.js.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/package.json +32 -17
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// src/core/http-server.ts
|
|
2
2
|
import { IncomingMessage, ServerResponse, createServer } from 'http';
|
|
3
|
+
import { createServer as createHttpsServer } from 'https';
|
|
3
4
|
import * as zlib from 'zlib';
|
|
4
5
|
import { promisify } from 'util';
|
|
5
6
|
import { randomUUID } from 'crypto';
|
|
6
7
|
import { createFrameworkLogger } from '../logger/index.js';
|
|
8
|
+
import { parseMultipart as parseMultipartBuffer, } from './utils/multipart-parser.js';
|
|
9
|
+
import { parseRawQueryString } from './utils/query-parser.js';
|
|
7
10
|
import { PathMatcher } from '../routing/path-matcher.js';
|
|
8
11
|
import { ObjectPoolManager } from '../pooling/object-pool-manager.js';
|
|
9
12
|
const gzip = promisify(zlib.gzip);
|
|
@@ -39,26 +42,9 @@ const TYPE_SHORTHANDS = {
|
|
|
39
42
|
css: 'text/css; charset=utf-8',
|
|
40
43
|
form: 'application/x-www-form-urlencoded',
|
|
41
44
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return result;
|
|
46
|
-
const pairs = queryString.split('&');
|
|
47
|
-
const pairsLen = pairs.length;
|
|
48
|
-
for (let i = 0; i < pairsLen; i++) {
|
|
49
|
-
const pair = pairs[i];
|
|
50
|
-
const equalIndex = pair.indexOf('=');
|
|
51
|
-
if (equalIndex === -1) {
|
|
52
|
-
result[decodeURIComponent(pair)] = '';
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
const key = decodeURIComponent(pair.substring(0, equalIndex));
|
|
56
|
-
const value = decodeURIComponent(pair.substring(equalIndex + 1));
|
|
57
|
-
result[key] = value;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return result;
|
|
61
|
-
}
|
|
45
|
+
// Canonical query parsing shared with the uWS/engine transports - identical
|
|
46
|
+
// req.query semantics everywhere ('+' as space, malformed escapes tolerated).
|
|
47
|
+
const parseQueryString = parseRawQueryString;
|
|
62
48
|
function parseCookieHeader(cookieHeader) {
|
|
63
49
|
const cookies = {};
|
|
64
50
|
if (!cookieHeader)
|
|
@@ -67,6 +53,8 @@ function parseCookieHeader(cookieHeader) {
|
|
|
67
53
|
const cookiePartsLen = cookieParts.length;
|
|
68
54
|
for (let i = 0; i < cookiePartsLen; i++) {
|
|
69
55
|
const cookie = cookieParts[i];
|
|
56
|
+
if (cookie === undefined)
|
|
57
|
+
continue;
|
|
70
58
|
const equalIndex = cookie.indexOf('=');
|
|
71
59
|
if (equalIndex > 0) {
|
|
72
60
|
const name = cookie.substring(0, equalIndex).trim();
|
|
@@ -197,7 +185,7 @@ export class MoroIncomingMessage extends IncomingMessage {
|
|
|
197
185
|
if (v === undefined) {
|
|
198
186
|
const forwardedProto = this.headers['x-forwarded-proto'];
|
|
199
187
|
v = forwardedProto
|
|
200
|
-
? forwardedProto.split(',')[0].trim()
|
|
188
|
+
? (forwardedProto.split(',')[0] ?? '').trim()
|
|
201
189
|
: this.socket?.encrypted
|
|
202
190
|
? 'https'
|
|
203
191
|
: 'http';
|
|
@@ -277,7 +265,7 @@ export class MoroIncomingMessage extends IncomingMessage {
|
|
|
277
265
|
const ct = (this.headers['content-type'] || '');
|
|
278
266
|
if (!ct)
|
|
279
267
|
return false;
|
|
280
|
-
const mime = ct.split(';')[0].trim().toLowerCase();
|
|
268
|
+
const mime = (ct.split(';')[0] ?? '').trim().toLowerCase();
|
|
281
269
|
const t = type.toLowerCase();
|
|
282
270
|
if (t.indexOf('/') === -1) {
|
|
283
271
|
// e.g. 'json' → match */json or +json suffix
|
|
@@ -295,7 +283,7 @@ export class MoroIncomingMessage extends IncomingMessage {
|
|
|
295
283
|
const wanted = Array.isArray(types) ? types : [types];
|
|
296
284
|
if (accept === '*/*' || accept === '')
|
|
297
285
|
return wanted[0] || false;
|
|
298
|
-
const acceptTypes = accept.split(',').map(s => s.split(';')[0].trim().toLowerCase());
|
|
286
|
+
const acceptTypes = accept.split(',').map(s => (s.split(';')[0] ?? '').trim().toLowerCase());
|
|
299
287
|
for (const w of wanted) {
|
|
300
288
|
const wl = w.toLowerCase();
|
|
301
289
|
const wMime = wl.indexOf('/') === -1 ? `application/${wl}` : wl;
|
|
@@ -322,7 +310,7 @@ export class MoroIncomingMessage extends IncomingMessage {
|
|
|
322
310
|
.split(',')
|
|
323
311
|
.map(s => {
|
|
324
312
|
const parts = s.trim().split(';');
|
|
325
|
-
const tag = parts[0].toLowerCase();
|
|
313
|
+
const tag = (parts[0] ?? '').toLowerCase();
|
|
326
314
|
const qPart = parts.find(p => p.trim().startsWith('q='));
|
|
327
315
|
const q = qPart ? parseFloat(qPart.trim().slice(2)) : 1;
|
|
328
316
|
return { tag, q: isNaN(q) ? 0 : q };
|
|
@@ -485,7 +473,8 @@ export class MoroServerResponse extends ServerResponse {
|
|
|
485
473
|
}
|
|
486
474
|
const cookieValue = encodeURIComponent(value);
|
|
487
475
|
let cookieString = `${name}=${cookieValue}`;
|
|
488
|
-
|
|
476
|
+
// maxAge: 0 is meaningful (immediate expiry - clearCookie relies on it)
|
|
477
|
+
if (options.maxAge !== undefined && options.maxAge !== null)
|
|
489
478
|
cookieString += `; Max-Age=${options.maxAge}`;
|
|
490
479
|
if (options.expires)
|
|
491
480
|
cookieString += `; Expires=${options.expires.toUTCString()}`;
|
|
@@ -497,8 +486,9 @@ export class MoroServerResponse extends ServerResponse {
|
|
|
497
486
|
cookieString += `; SameSite=${options.sameSite}`;
|
|
498
487
|
if (options.domain)
|
|
499
488
|
cookieString += `; Domain=${options.domain}`;
|
|
500
|
-
|
|
501
|
-
|
|
489
|
+
// Path defaults to '/' (Express behavior) so clearCookie() from a nested
|
|
490
|
+
// route can clear a cookie originally set at the site root.
|
|
491
|
+
cookieString += `; Path=${options.path ?? '/'}`;
|
|
502
492
|
const existingCookies = this.getHeader('Set-Cookie') || [];
|
|
503
493
|
// Avoid spread operator - direct array manipulation
|
|
504
494
|
const cookies = Array.isArray(existingCookies) ? existingCookies : [existingCookies];
|
|
@@ -708,7 +698,9 @@ export class MoroServerResponse extends ServerResponse {
|
|
|
708
698
|
return this;
|
|
709
699
|
}
|
|
710
700
|
for (const key in headers) {
|
|
711
|
-
|
|
701
|
+
const value = headers[key];
|
|
702
|
+
if (value !== undefined)
|
|
703
|
+
this.setHeader(key, value);
|
|
712
704
|
}
|
|
713
705
|
return this;
|
|
714
706
|
}
|
|
@@ -804,10 +796,15 @@ export class MoroServerResponse extends ServerResponse {
|
|
|
804
796
|
// Set Content-Type from extension if not already set
|
|
805
797
|
if (!this.getHeader('Content-Type')) {
|
|
806
798
|
// fire-and-forget mime lookup; not awaited to keep signature chainable
|
|
807
|
-
this._server
|
|
799
|
+
void this._server
|
|
800
|
+
.getMimeType(filename.substring(filename.lastIndexOf('.')))
|
|
801
|
+
.then(mime => {
|
|
808
802
|
if (!this.getHeader('Content-Type') && !this.headersSent) {
|
|
809
803
|
this.setHeader('Content-Type', mime);
|
|
810
804
|
}
|
|
805
|
+
})
|
|
806
|
+
.catch(() => {
|
|
807
|
+
// best-effort content-type inference
|
|
811
808
|
});
|
|
812
809
|
}
|
|
813
810
|
}
|
|
@@ -866,6 +863,10 @@ export class MoroServerResponse extends ServerResponse {
|
|
|
866
863
|
}
|
|
867
864
|
export class MoroHttpServer {
|
|
868
865
|
server;
|
|
866
|
+
/** Multipart limits threaded to parseMultipart at the call site. */
|
|
867
|
+
multipartLimits;
|
|
868
|
+
/** TCP backlog for listen(), when configured. */
|
|
869
|
+
listenBacklog;
|
|
869
870
|
routes = [];
|
|
870
871
|
globalMiddleware = [];
|
|
871
872
|
/** @internal read by MoroServerResponse prototype methods */
|
|
@@ -923,7 +924,23 @@ export class MoroHttpServer {
|
|
|
923
924
|
BoundResponse.prototype._server = boundServer;
|
|
924
925
|
this.RequestClass = BoundRequest;
|
|
925
926
|
this.ResponseClass = BoundResponse;
|
|
926
|
-
|
|
927
|
+
const limits = options?.limits;
|
|
928
|
+
// maxHeaderSize is a createServer option (not a mutable property), so it
|
|
929
|
+
// must be passed here.
|
|
930
|
+
const serverOpts = {
|
|
931
|
+
IncomingMessage: BoundRequest,
|
|
932
|
+
ServerResponse: BoundResponse,
|
|
933
|
+
...(limits?.maxHeaderSize && { maxHeaderSize: limits.maxHeaderSize }),
|
|
934
|
+
};
|
|
935
|
+
if (options?.ssl) {
|
|
936
|
+
// In-process HTTPS. The https ServerOptions extends the http one, so the
|
|
937
|
+
// IncomingMessage/ServerResponse subclass injection carries over.
|
|
938
|
+
this.server = createHttpsServer({ ...serverOpts, ...options.ssl }, this.handleRequest.bind(this));
|
|
939
|
+
this.logger.info('HTTPS server created (in-process TLS)', 'HttpServer');
|
|
940
|
+
}
|
|
941
|
+
else {
|
|
942
|
+
this.server = createServer(serverOpts, this.handleRequest.bind(this));
|
|
943
|
+
}
|
|
927
944
|
// Configure body size limits from options
|
|
928
945
|
if (options?.maxBodySize) {
|
|
929
946
|
this.maxBodySize = options.maxBodySize;
|
|
@@ -931,15 +948,25 @@ export class MoroHttpServer {
|
|
|
931
948
|
if (options?.maxUploadSize) {
|
|
932
949
|
this.maxUploadSize = options.maxUploadSize;
|
|
933
950
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
//
|
|
938
|
-
//
|
|
939
|
-
//
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
this.server.
|
|
951
|
+
if (limits?.multipart)
|
|
952
|
+
this.multipartLimits = limits.multipart;
|
|
953
|
+
// Timeouts: the previous hardcodes (keepAlive 5000, headers 6000) become
|
|
954
|
+
// the documented defaults; a configured value overrides them. Socket idle
|
|
955
|
+
// timeout stays 0 (disabled) unless set - a non-zero value arms a
|
|
956
|
+
// per-request timer that shows up in CPU profiles under load.
|
|
957
|
+
const t = limits?.timeouts ?? {};
|
|
958
|
+
this.server.keepAliveTimeout = t.keepAlive ?? 5000;
|
|
959
|
+
this.server.headersTimeout = t.headers ?? 6000;
|
|
960
|
+
this.server.timeout = t.idle ?? 0;
|
|
961
|
+
if (t.request)
|
|
962
|
+
this.server.requestTimeout = t.request;
|
|
963
|
+
if (limits?.maxConnections && limits.maxConnections > 0) {
|
|
964
|
+
this.server.maxConnections = limits.maxConnections;
|
|
965
|
+
}
|
|
966
|
+
if (limits?.maxHeaders)
|
|
967
|
+
this.server.maxHeadersCount = limits.maxHeaders;
|
|
968
|
+
if (limits?.backlog !== undefined)
|
|
969
|
+
this.listenBacklog = limits.backlog;
|
|
943
970
|
}
|
|
944
971
|
// Direct router dispatch - called after global middleware, before the legacy
|
|
945
972
|
// route table. Returning true (or a promise of true) means the request was handled.
|
|
@@ -1218,7 +1245,11 @@ export class MoroHttpServer {
|
|
|
1218
1245
|
const paramNames = route.paramNames;
|
|
1219
1246
|
const paramNamesLen = paramNames.length;
|
|
1220
1247
|
for (let i = 0; i < paramNamesLen; i++) {
|
|
1221
|
-
|
|
1248
|
+
const paramName = paramNames[i];
|
|
1249
|
+
const value = matches[i + 1];
|
|
1250
|
+
if (paramName !== undefined && value !== undefined) {
|
|
1251
|
+
params[paramName] = value;
|
|
1252
|
+
}
|
|
1222
1253
|
}
|
|
1223
1254
|
httpReq.params = params;
|
|
1224
1255
|
}
|
|
@@ -1284,18 +1315,23 @@ export class MoroHttpServer {
|
|
|
1284
1315
|
}
|
|
1285
1316
|
}
|
|
1286
1317
|
if (!httpRes.headersSent) {
|
|
1318
|
+
// A malformed body is a client error: default to 400 (parity with the
|
|
1319
|
+
// engine/uWS transports), not the generic 500.
|
|
1320
|
+
const isBadRequest = error?.statusCode === 400;
|
|
1321
|
+
const defaultStatus = isBadRequest ? 400 : 500;
|
|
1322
|
+
const defaultError = isBadRequest ? 'Invalid request body' : 'Internal server error';
|
|
1287
1323
|
// Ensure response is properly enhanced before using custom methods
|
|
1288
1324
|
if (typeof httpRes.status === 'function' && typeof httpRes.json === 'function') {
|
|
1289
|
-
httpRes.status(
|
|
1325
|
+
httpRes.status(defaultStatus).json({
|
|
1290
1326
|
success: false,
|
|
1291
|
-
error:
|
|
1327
|
+
error: defaultError,
|
|
1292
1328
|
requestId: httpReq.requestId,
|
|
1293
1329
|
});
|
|
1294
1330
|
}
|
|
1295
1331
|
else {
|
|
1296
1332
|
// Defensive fallback - check each method individually
|
|
1297
1333
|
if (typeof httpRes.setHeader === 'function') {
|
|
1298
|
-
httpRes.statusCode =
|
|
1334
|
+
httpRes.statusCode = defaultStatus;
|
|
1299
1335
|
httpRes.setHeader('Content-Type', 'application/json');
|
|
1300
1336
|
}
|
|
1301
1337
|
else {
|
|
@@ -1308,7 +1344,7 @@ export class MoroHttpServer {
|
|
|
1308
1344
|
if (typeof httpRes.end === 'function') {
|
|
1309
1345
|
httpRes.end(JSON.stringify({
|
|
1310
1346
|
success: false,
|
|
1311
|
-
error:
|
|
1347
|
+
error: defaultError,
|
|
1312
1348
|
requestId: httpReq.requestId,
|
|
1313
1349
|
}));
|
|
1314
1350
|
}
|
|
@@ -1447,12 +1483,12 @@ export class MoroHttpServer {
|
|
|
1447
1483
|
error.received = contentLength;
|
|
1448
1484
|
return Promise.reject(error);
|
|
1449
1485
|
}
|
|
1450
|
-
//
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
//
|
|
1486
|
+
// Buffer every body up to maxSize and parse it into its real shape. The
|
|
1487
|
+
// incremental limit check below already bounds memory, and every other
|
|
1488
|
+
// backend (uWS, engine) returns the parsed body here - previously bodies
|
|
1489
|
+
// between maxSize/2 and maxSize resolved to a { type, parser } descriptor
|
|
1490
|
+
// object instead, so handlers/validation on the Node backend silently saw
|
|
1491
|
+
// a bogus shape for the exact same request that parsed normally elsewhere.
|
|
1456
1492
|
return new Promise((resolve, reject) => {
|
|
1457
1493
|
const chunks = [];
|
|
1458
1494
|
let totalLength = 0;
|
|
@@ -1474,9 +1510,14 @@ export class MoroHttpServer {
|
|
|
1474
1510
|
try {
|
|
1475
1511
|
// Single-chunk fast path (most JSON bodies arrive in one chunk);
|
|
1476
1512
|
// otherwise concat with the known total length to avoid a re-scan
|
|
1477
|
-
const
|
|
1513
|
+
const firstChunk = chunks[0];
|
|
1514
|
+
const body = chunks.length === 1 && firstChunk !== undefined
|
|
1515
|
+
? firstChunk
|
|
1516
|
+
: Buffer.concat(chunks, totalLength);
|
|
1478
1517
|
if (contentType.includes('application/json')) {
|
|
1479
|
-
|
|
1518
|
+
// Empty JSON body -> null (parity with the engine/uWS servers, and
|
|
1519
|
+
// avoids JSON.parse('') throwing and 500ing an empty POST).
|
|
1520
|
+
resolve(totalLength === 0 ? null : JSON.parse(body.toString()));
|
|
1480
1521
|
}
|
|
1481
1522
|
else if (contentType.includes('application/x-www-form-urlencoded')) {
|
|
1482
1523
|
resolve(this.parseUrlEncoded(body.toString()));
|
|
@@ -1489,132 +1530,12 @@ export class MoroHttpServer {
|
|
|
1489
1530
|
}
|
|
1490
1531
|
}
|
|
1491
1532
|
catch (error) {
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
/**
|
|
1499
|
-
* Create a streaming body parser for large payloads
|
|
1500
|
-
* Returns a streaming interface instead of buffering
|
|
1501
|
-
*/
|
|
1502
|
-
createStreamingBodyParser(req, contentType, maxSize) {
|
|
1503
|
-
let totalLength = 0;
|
|
1504
|
-
const chunks = [];
|
|
1505
|
-
return new Promise((resolve, reject) => {
|
|
1506
|
-
const streamParser = {
|
|
1507
|
-
// Streaming JSON parser for large JSON payloads
|
|
1508
|
-
json: () => this.streamJsonParse(req, maxSize),
|
|
1509
|
-
// Streaming form data parser
|
|
1510
|
-
form: () => this.streamFormParse(req, maxSize),
|
|
1511
|
-
// Raw stream access
|
|
1512
|
-
stream: () => ({
|
|
1513
|
-
onData: (callback) => {
|
|
1514
|
-
req.on('data', (chunk) => {
|
|
1515
|
-
totalLength += chunk.length;
|
|
1516
|
-
if (totalLength > maxSize) {
|
|
1517
|
-
reject(new Error('Request body too large'));
|
|
1518
|
-
return;
|
|
1519
|
-
}
|
|
1520
|
-
callback(chunk);
|
|
1521
|
-
});
|
|
1522
|
-
},
|
|
1523
|
-
onEnd: (callback) => {
|
|
1524
|
-
req.on('end', callback);
|
|
1525
|
-
},
|
|
1526
|
-
onError: (callback) => {
|
|
1527
|
-
req.on('error', callback);
|
|
1528
|
-
},
|
|
1529
|
-
}),
|
|
1530
|
-
// Traditional buffered parsing (fallback)
|
|
1531
|
-
buffer: async () => {
|
|
1532
|
-
return new Promise((resolveBuffer, rejectBuffer) => {
|
|
1533
|
-
req.on('data', (chunk) => {
|
|
1534
|
-
totalLength += chunk.length;
|
|
1535
|
-
if (totalLength > maxSize) {
|
|
1536
|
-
rejectBuffer(new Error('Request body too large'));
|
|
1537
|
-
return;
|
|
1538
|
-
}
|
|
1539
|
-
chunks.push(chunk);
|
|
1540
|
-
});
|
|
1541
|
-
req.on('end', () => {
|
|
1542
|
-
try {
|
|
1543
|
-
const body = Buffer.concat(chunks);
|
|
1544
|
-
if (contentType.includes('application/json')) {
|
|
1545
|
-
resolveBuffer(JSON.parse(body.toString()));
|
|
1546
|
-
}
|
|
1547
|
-
else {
|
|
1548
|
-
resolveBuffer(body.toString());
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
catch (error) {
|
|
1552
|
-
rejectBuffer(error);
|
|
1553
|
-
}
|
|
1554
|
-
});
|
|
1555
|
-
req.on('error', rejectBuffer);
|
|
1556
|
-
});
|
|
1557
|
-
},
|
|
1558
|
-
};
|
|
1559
|
-
// Auto-detect and return appropriate parser
|
|
1560
|
-
if (contentType.includes('application/json')) {
|
|
1561
|
-
resolve({ type: 'json', parser: streamParser.json });
|
|
1562
|
-
}
|
|
1563
|
-
else if (contentType.includes('application/x-www-form-urlencoded')) {
|
|
1564
|
-
resolve({ type: 'form', parser: streamParser.form });
|
|
1565
|
-
}
|
|
1566
|
-
else {
|
|
1567
|
-
resolve({ type: 'stream', parser: streamParser.stream });
|
|
1568
|
-
}
|
|
1569
|
-
});
|
|
1570
|
-
}
|
|
1571
|
-
/**
|
|
1572
|
-
* Streaming JSON parser for large payloads
|
|
1573
|
-
*/
|
|
1574
|
-
async streamJsonParse(req, maxSize) {
|
|
1575
|
-
return new Promise((resolve, reject) => {
|
|
1576
|
-
let jsonString = '';
|
|
1577
|
-
let totalLength = 0;
|
|
1578
|
-
req.on('data', (chunk) => {
|
|
1579
|
-
totalLength += chunk.length;
|
|
1580
|
-
if (totalLength > maxSize) {
|
|
1581
|
-
reject(new Error('Request body too large'));
|
|
1582
|
-
return;
|
|
1583
|
-
}
|
|
1584
|
-
jsonString += chunk.toString();
|
|
1585
|
-
});
|
|
1586
|
-
req.on('end', () => {
|
|
1587
|
-
try {
|
|
1588
|
-
// For very large JSON, consider streaming JSON parsing in the future
|
|
1589
|
-
resolve(JSON.parse(jsonString));
|
|
1590
|
-
}
|
|
1591
|
-
catch (error) {
|
|
1592
|
-
reject(error);
|
|
1593
|
-
}
|
|
1594
|
-
});
|
|
1595
|
-
req.on('error', reject);
|
|
1596
|
-
});
|
|
1597
|
-
}
|
|
1598
|
-
/**
|
|
1599
|
-
* Streaming form data parser
|
|
1600
|
-
*/
|
|
1601
|
-
async streamFormParse(req, maxSize) {
|
|
1602
|
-
return new Promise((resolve, reject) => {
|
|
1603
|
-
let formData = '';
|
|
1604
|
-
let totalLength = 0;
|
|
1605
|
-
req.on('data', (chunk) => {
|
|
1606
|
-
totalLength += chunk.length;
|
|
1607
|
-
if (totalLength > maxSize) {
|
|
1608
|
-
reject(new Error('Request body too large'));
|
|
1609
|
-
return;
|
|
1610
|
-
}
|
|
1611
|
-
formData += chunk.toString();
|
|
1612
|
-
});
|
|
1613
|
-
req.on('end', () => {
|
|
1614
|
-
try {
|
|
1615
|
-
resolve(this.parseUrlEncoded(formData));
|
|
1616
|
-
}
|
|
1617
|
-
catch (error) {
|
|
1533
|
+
// A malformed body is a client error (400), not a server error (500).
|
|
1534
|
+
// Tag it so the request-error path answers 400, matching the engine
|
|
1535
|
+
// and uWS transports.
|
|
1536
|
+
if (error instanceof Error && error.statusCode === undefined) {
|
|
1537
|
+
error.statusCode = 400;
|
|
1538
|
+
}
|
|
1618
1539
|
reject(error);
|
|
1619
1540
|
}
|
|
1620
1541
|
});
|
|
@@ -1622,76 +1543,9 @@ export class MoroHttpServer {
|
|
|
1622
1543
|
});
|
|
1623
1544
|
}
|
|
1624
1545
|
parseMultipart(buffer, contentType) {
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
}
|
|
1629
|
-
// Work with Buffer directly - don't convert to string (corrupts binary data)
|
|
1630
|
-
const boundaryBuffer = Buffer.from(`--${boundary}`);
|
|
1631
|
-
const parts = this.splitBuffer(buffer, boundaryBuffer);
|
|
1632
|
-
const fields = {};
|
|
1633
|
-
const files = {};
|
|
1634
|
-
// Skip first (empty) and last (closing boundary) parts
|
|
1635
|
-
const partsLen = parts.length - 1;
|
|
1636
|
-
for (let i = 1; i < partsLen; i++) {
|
|
1637
|
-
const part = parts[i];
|
|
1638
|
-
// Find the double CRLF that separates headers from content
|
|
1639
|
-
const headerEndPos = this.findBufferSequence(part, Buffer.from('\r\n\r\n'));
|
|
1640
|
-
if (headerEndPos === -1)
|
|
1641
|
-
continue;
|
|
1642
|
-
// Headers are always text - safe to convert to string
|
|
1643
|
-
const headers = part.slice(0, headerEndPos).toString('utf8');
|
|
1644
|
-
// Content stays as Buffer to preserve binary data
|
|
1645
|
-
const content = part.slice(headerEndPos + 4); // Skip the \r\n\r\n
|
|
1646
|
-
const nameMatch = headers.match(/name="([^"]+)"/);
|
|
1647
|
-
const filenameMatch = headers.match(/filename="([^"]+)"/);
|
|
1648
|
-
const contentTypeMatch = headers.match(/Content-Type: ([^\r\n]+)/);
|
|
1649
|
-
if (nameMatch) {
|
|
1650
|
-
const name = nameMatch[1];
|
|
1651
|
-
if (filenameMatch) {
|
|
1652
|
-
// This is a file - keep as Buffer to preserve binary data
|
|
1653
|
-
const filename = filenameMatch[1];
|
|
1654
|
-
const mimeType = contentTypeMatch ? contentTypeMatch[1] : 'application/octet-stream';
|
|
1655
|
-
// Remove trailing \r\n (2 bytes) from the end
|
|
1656
|
-
const fileData = content.slice(0, content.length - 2);
|
|
1657
|
-
files[name] = {
|
|
1658
|
-
filename,
|
|
1659
|
-
mimetype: mimeType,
|
|
1660
|
-
data: fileData, // Already a Buffer - preserves binary integrity
|
|
1661
|
-
size: fileData.length,
|
|
1662
|
-
};
|
|
1663
|
-
}
|
|
1664
|
-
else {
|
|
1665
|
-
// This is a regular field - convert to string
|
|
1666
|
-
const fieldContent = content.slice(0, content.length - 2); // Remove trailing \r\n
|
|
1667
|
-
fields[name] = fieldContent.toString('utf8');
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
return { fields, files };
|
|
1672
|
-
}
|
|
1673
|
-
/**
|
|
1674
|
-
* Split a Buffer by a delimiter Buffer
|
|
1675
|
-
* Used for multipart boundary splitting without corrupting binary data
|
|
1676
|
-
*/
|
|
1677
|
-
splitBuffer(buffer, delimiter) {
|
|
1678
|
-
const parts = [];
|
|
1679
|
-
let start = 0;
|
|
1680
|
-
let pos = 0;
|
|
1681
|
-
while ((pos = buffer.indexOf(delimiter, start)) !== -1) {
|
|
1682
|
-
parts.push(buffer.slice(start, pos));
|
|
1683
|
-
start = pos + delimiter.length;
|
|
1684
|
-
}
|
|
1685
|
-
// Add the remaining part
|
|
1686
|
-
parts.push(buffer.slice(start));
|
|
1687
|
-
return parts;
|
|
1688
|
-
}
|
|
1689
|
-
/**
|
|
1690
|
-
* Find the position of a sequence within a Buffer
|
|
1691
|
-
* Returns -1 if not found
|
|
1692
|
-
*/
|
|
1693
|
-
findBufferSequence(buffer, sequence) {
|
|
1694
|
-
return buffer.indexOf(sequence);
|
|
1546
|
+
// Shared implementation - the native engine server parses uploads with
|
|
1547
|
+
// the exact same code so both transports agree on body/files shape
|
|
1548
|
+
return parseMultipartBuffer(buffer, contentType, this.multipartLimits);
|
|
1695
1549
|
}
|
|
1696
1550
|
parseUrlEncoded(body) {
|
|
1697
1551
|
const params = new URLSearchParams(body);
|
|
@@ -1755,6 +1609,8 @@ export class MoroHttpServer {
|
|
|
1755
1609
|
// Only test routes with matching method and segment count
|
|
1756
1610
|
for (let i = 0; i < candidateLen; i++) {
|
|
1757
1611
|
const candidateRoute = candidateRoutes[i];
|
|
1612
|
+
if (candidateRoute === undefined)
|
|
1613
|
+
continue;
|
|
1758
1614
|
if (candidateRoute.method === method && candidateRoute.pattern.test(normalizedPath)) {
|
|
1759
1615
|
route = candidateRoute;
|
|
1760
1616
|
break;
|
|
@@ -1864,7 +1720,11 @@ export class MoroHttpServer {
|
|
|
1864
1720
|
callback = host;
|
|
1865
1721
|
host = undefined;
|
|
1866
1722
|
}
|
|
1867
|
-
|
|
1723
|
+
const backlog = this.listenBacklog;
|
|
1724
|
+
if (host && backlog) {
|
|
1725
|
+
this.server.listen(port, host, backlog, callback);
|
|
1726
|
+
}
|
|
1727
|
+
else if (host) {
|
|
1868
1728
|
this.server.listen(port, host, callback);
|
|
1869
1729
|
}
|
|
1870
1730
|
else {
|