@rapidrest/service-core 1.0.0-rc.21 → 1.0.0-rc.23
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/dist/lib/ApiErrors.js +2 -0
- package/dist/lib/ApiErrors.js.map +1 -1
- package/dist/lib/OpenApiSpec.js.map +1 -1
- package/dist/lib/Server.js +25 -15
- package/dist/lib/Server.js.map +1 -1
- package/dist/lib/auth/AuthMiddleware.js +2 -1
- package/dist/lib/auth/AuthMiddleware.js.map +1 -1
- package/dist/lib/auth/JWTStrategy.js +21 -1
- package/dist/lib/auth/JWTStrategy.js.map +1 -1
- package/dist/lib/database/ConnectionManager.js +7 -1
- package/dist/lib/database/ConnectionManager.js.map +1 -1
- package/dist/lib/database/MongoSchemaSync.js.map +1 -1
- package/dist/lib/decorators/ModelDecorators.js +17 -0
- package/dist/lib/decorators/ModelDecorators.js.map +1 -1
- package/dist/lib/http/IWebSocketShim.js +2 -0
- package/dist/lib/http/IWebSocketShim.js.map +1 -0
- package/dist/lib/http/MiddlewareChain.js +129 -0
- package/dist/lib/http/MiddlewareChain.js.map +1 -0
- package/dist/lib/http/RuntimeDetect.js +8 -0
- package/dist/lib/http/RuntimeDetect.js.map +1 -0
- package/dist/lib/http/bun/BunAdapters.js +270 -0
- package/dist/lib/http/bun/BunAdapters.js.map +1 -0
- package/dist/lib/http/bun/BunRouter.js +377 -0
- package/dist/lib/http/bun/BunRouter.js.map +1 -0
- package/dist/lib/http/bun/BunWebSocket.js +48 -0
- package/dist/lib/http/bun/BunWebSocket.js.map +1 -0
- package/dist/lib/http/index.js +13 -3
- package/dist/lib/http/index.js.map +1 -1
- package/dist/lib/http/{Adapters.js → uWS/Adapters.js} +65 -27
- package/dist/lib/http/uWS/Adapters.js.map +1 -0
- package/dist/lib/http/{Router.js → uWS/Router.js} +24 -133
- package/dist/lib/http/uWS/Router.js.map +1 -0
- package/dist/lib/http/uWS/WebSocket.js.map +1 -0
- package/dist/lib/models/ModelUtils.js +104 -9
- package/dist/lib/models/ModelUtils.js.map +1 -1
- package/dist/lib/models/RepoUtils.js +89 -6
- package/dist/lib/models/RepoUtils.js.map +1 -1
- package/dist/lib/routes/BaseAdminRoute.js +7 -5
- package/dist/lib/routes/BaseAdminRoute.js.map +1 -1
- package/dist/lib/routes/BaseMetricsRoute.js.map +1 -1
- package/dist/lib/routes/BasePushRoute.js +32 -5
- package/dist/lib/routes/BasePushRoute.js.map +1 -1
- package/dist/lib/routes/CRUDRoute.js.map +1 -1
- package/dist/lib/routes/ModelRoute.js.map +1 -1
- package/dist/lib/routes/RouteUtils.js +6 -2
- package/dist/lib/routes/RouteUtils.js.map +1 -1
- package/dist/lib/security/ACLUtils.js +10 -5
- package/dist/lib/security/ACLUtils.js.map +1 -1
- package/dist/lib/security/AccessControlListMongo.js +29 -29
- package/dist/lib/security/AccessControlListSQL.js +29 -29
- package/dist/lib/security/BaseACLRoute.js.map +1 -1
- package/dist/lib/test/requestws.js +28 -3
- package/dist/lib/test/requestws.js.map +1 -1
- package/dist/types/ApiErrors.d.ts +2 -0
- package/dist/types/OpenApiSpec.d.ts +1 -1
- package/dist/types/Server.d.ts +4 -4
- package/dist/types/auth/AuthMiddleware.d.ts +2 -2
- package/dist/types/auth/AuthStrategy.d.ts +2 -2
- package/dist/types/auth/BasicStrategy.d.ts +3 -3
- package/dist/types/auth/JWTStrategy.d.ts +3 -2
- package/dist/types/decorators/ModelDecorators.d.ts +8 -1
- package/dist/types/decorators/RouteDecorators.d.ts +1 -1
- package/dist/types/http/IWebSocketShim.d.ts +11 -0
- package/dist/types/http/MiddlewareChain.d.ts +40 -0
- package/dist/types/http/RuntimeDetect.d.ts +2 -0
- package/dist/types/http/bun/BunAdapters.d.ts +128 -0
- package/dist/types/http/bun/BunRouter.d.ts +79 -0
- package/dist/types/http/bun/BunWebSocket.d.ts +35 -0
- package/dist/types/http/index.d.ts +12 -6
- package/dist/types/http/types.d.ts +21 -0
- package/dist/types/http/{Adapters.d.ts → uWS/Adapters.d.ts} +24 -2
- package/dist/types/http/{Router.d.ts → uWS/Router.d.ts} +8 -32
- package/dist/types/http/{WebSocket.d.ts → uWS/WebSocket.d.ts} +6 -5
- package/dist/types/models/ModelUtils.d.ts +30 -0
- package/dist/types/models/RepoUtils.d.ts +2 -2
- package/dist/types/routes/BaseAdminRoute.d.ts +3 -3
- package/dist/types/routes/BaseMetricsRoute.d.ts +1 -1
- package/dist/types/routes/BasePushRoute.d.ts +4 -0
- package/dist/types/routes/BaseStaticRoute.d.ts +1 -1
- package/dist/types/routes/CRUDRoute.d.ts +2 -2
- package/dist/types/routes/ModelRoute.d.ts +2 -2
- package/dist/types/security/ACLUtils.d.ts +6 -3
- package/dist/types/security/AccessControlListMongo.d.ts +1 -1
- package/dist/types/security/AccessControlListSQL.d.ts +1 -1
- package/dist/types/security/BaseACLRoute.d.ts +3 -3
- package/package.json +138 -132
- package/dist/lib/http/Adapters.js.map +0 -1
- package/dist/lib/http/Router.js.map +0 -1
- package/dist/lib/http/WebSocket.js.map +0 -1
- /package/dist/lib/http/{WebSocket.js → uWS/WebSocket.js} +0 -0
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { DEFAULT_MAX_BODY_SIZE } from "../uWS/Adapters.js";
|
|
2
|
+
import { BunRequest, BunResponse, readBunBody } from "./BunAdapters.js";
|
|
3
|
+
import { BunWebSocketShim } from "./BunWebSocket.js";
|
|
4
|
+
import { makeWsStubResponse, runChain } from "../MiddlewareChain.js";
|
|
5
|
+
import { ApiError } from "@rapidrest/core";
|
|
6
|
+
import { ApiErrorMessages, ApiErrors } from "../../ApiErrors.js";
|
|
7
|
+
/** Strips a single trailing slash from a pathname, except for the root `"/"` itself. */
|
|
8
|
+
function normalizePath(pathname) {
|
|
9
|
+
if (pathname.length > 1 && pathname.endsWith("/")) {
|
|
10
|
+
return pathname.slice(0, -1);
|
|
11
|
+
}
|
|
12
|
+
return pathname;
|
|
13
|
+
}
|
|
14
|
+
/** Splits a normalized pathname into non-empty segments (e.g. `/users/:uid` -> `["users", ":uid"]`). */
|
|
15
|
+
function splitPath(pathname) {
|
|
16
|
+
return pathname.split("/").filter((s) => s.length > 0);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Scores how well a route's segments match a request's segments: 2 points per exact static
|
|
20
|
+
* segment match, 1 point per `:param` segment match, or `null` if the segment counts differ or a
|
|
21
|
+
* static segment doesn't match. Higher scores are more specific (static beats `:param`).
|
|
22
|
+
*/
|
|
23
|
+
function matchSegments(routeSegments, reqSegments) {
|
|
24
|
+
if (routeSegments.length !== reqSegments.length)
|
|
25
|
+
return null;
|
|
26
|
+
let score = 0;
|
|
27
|
+
for (let i = 0; i < routeSegments.length; i++) {
|
|
28
|
+
const seg = routeSegments[i];
|
|
29
|
+
if (seg.startsWith(":")) {
|
|
30
|
+
score += 1;
|
|
31
|
+
}
|
|
32
|
+
else if (seg === reqSegments[i]) {
|
|
33
|
+
score += 2;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return score;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Extracts `:param` values from a matched request path given the route's segment pattern.
|
|
43
|
+
* Deliberately does NOT percent-decode — matches uWS's `getParameter()`, which returns the raw
|
|
44
|
+
* segment as-is, so `:param` values are identical across both adapters for the same request.
|
|
45
|
+
*/
|
|
46
|
+
function extractParams(routeSegments, reqSegments) {
|
|
47
|
+
const params = {};
|
|
48
|
+
for (let i = 0; i < routeSegments.length; i++) {
|
|
49
|
+
const seg = routeSegments[i];
|
|
50
|
+
if (seg.startsWith(":")) {
|
|
51
|
+
params[seg.slice(1)] = reqSegments[i] ?? "";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return params;
|
|
55
|
+
}
|
|
56
|
+
/** Maps the framework's `ssl` config block (file paths) to Bun's `tls` option (file contents). */
|
|
57
|
+
function mapSslConfigToBunTls(sslConfig) {
|
|
58
|
+
return {
|
|
59
|
+
key: Bun.file(sslConfig.key),
|
|
60
|
+
cert: Bun.file(sslConfig.cert),
|
|
61
|
+
ca: sslConfig.ca ? Bun.file(sslConfig.ca) : undefined,
|
|
62
|
+
passphrase: sslConfig.passphrase,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Bun-native HTTP/WebSocket router built on `Bun.serve()`. Exposes the same public surface as the
|
|
67
|
+
* uWS-backed `HttpRouter` (`use/get/post/put/delete/patch/head/options/ws/listen/close/isListening/
|
|
68
|
+
* listenPort`) so `RouteUtils.registerRoute()` and `Server.ts` work against either implementation
|
|
69
|
+
* unchanged.
|
|
70
|
+
*
|
|
71
|
+
* Unlike uWS, `Bun.serve()` has no built-in dynamic router, so this class maintains its own route
|
|
72
|
+
* table matched inside a single `fetch()` callback, with static-segment > `:param` > `/*` wildcard
|
|
73
|
+
* precedence — replicating uWS's specificity-based matching.
|
|
74
|
+
*/
|
|
75
|
+
export class BunRouter {
|
|
76
|
+
constructor(maxBodySize = DEFAULT_MAX_BODY_SIZE, sslConfig) {
|
|
77
|
+
this.routesByMethod = new Map();
|
|
78
|
+
this.wsRoutes = [];
|
|
79
|
+
this.globalMiddleware = [];
|
|
80
|
+
this.preRouteCount = -1;
|
|
81
|
+
this.rootWildcardVerbs = new Set();
|
|
82
|
+
/** The port the server is currently listening on (set after a successful `listen()` call). */
|
|
83
|
+
this.listenPort = 0;
|
|
84
|
+
// -------------------------------------------------------------------------
|
|
85
|
+
// Request dispatch
|
|
86
|
+
// -------------------------------------------------------------------------
|
|
87
|
+
this.fetchHandler = async (rawReq, server) => {
|
|
88
|
+
const url = new URL(rawReq.url);
|
|
89
|
+
const reqHasTrailingSlash = url.pathname.length > 1 && url.pathname.endsWith("/");
|
|
90
|
+
const normalizedPath = normalizePath(url.pathname);
|
|
91
|
+
const reqSegments = splitPath(normalizedPath);
|
|
92
|
+
if (rawReq.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
93
|
+
const wsMatch = this.matchWsRoute(reqSegments);
|
|
94
|
+
if (wsMatch) {
|
|
95
|
+
const req = new BunRequest(rawReq, server);
|
|
96
|
+
req.params = extractParams(wsMatch.segments, reqSegments);
|
|
97
|
+
if (wsMatch.upgradeAuth) {
|
|
98
|
+
const authResult = wsMatch.upgradeAuth(req);
|
|
99
|
+
if (authResult.reject) {
|
|
100
|
+
return new Response(JSON.stringify({ status: 401, message: "Unauthorized" }), {
|
|
101
|
+
status: 401,
|
|
102
|
+
headers: { "content-type": "application/json" },
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (authResult.user) {
|
|
106
|
+
req.user = authResult.user;
|
|
107
|
+
req.auth = authResult;
|
|
108
|
+
req.authPayload = authResult.authPayload;
|
|
109
|
+
req.authToken = authResult.authToken;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const socketData = { req, handlers: wsMatch.handlers };
|
|
113
|
+
const upgraded = server.upgrade(rawReq, { data: socketData });
|
|
114
|
+
if (upgraded)
|
|
115
|
+
return undefined;
|
|
116
|
+
return new Response("WebSocket upgrade failed", { status: 400 });
|
|
117
|
+
}
|
|
118
|
+
// No matching ws route — fall through to normal HTTP handling (ends in 404 below).
|
|
119
|
+
}
|
|
120
|
+
const method = rawReq.method.toUpperCase();
|
|
121
|
+
const route = this.matchRoute(method, reqSegments, reqHasTrailingSlash);
|
|
122
|
+
if (!route) {
|
|
123
|
+
return new Response(JSON.stringify({ code: ApiErrors.NOT_FOUND, status: 404, message: ApiErrorMessages.NOT_FOUND }), { status: 404, headers: { "content-type": "application/json" } });
|
|
124
|
+
}
|
|
125
|
+
const req = new BunRequest(rawReq, server);
|
|
126
|
+
// For wildcard-suffixed routes, `route.segments` is only the prefix — slice reqSegments to
|
|
127
|
+
// match so extractParams doesn't walk past it. For exact-length routes this is a no-op
|
|
128
|
+
// (route.segments.length === reqSegments.length is guaranteed by matchSegments).
|
|
129
|
+
req.params = extractParams(route.segments, reqSegments.slice(0, route.segments.length));
|
|
130
|
+
const res = new BunResponse(rawReq);
|
|
131
|
+
res.isHead = route.isHead;
|
|
132
|
+
const bodyResult = await readBunBody(req, rawReq, this.maxBodySize);
|
|
133
|
+
if (!bodyResult.ok)
|
|
134
|
+
return bodyResult.response;
|
|
135
|
+
const allHandlers = [
|
|
136
|
+
...this.globalMiddleware.slice(0, route.preLength),
|
|
137
|
+
...route.handlers,
|
|
138
|
+
...this.globalMiddleware.slice(route.preLength),
|
|
139
|
+
];
|
|
140
|
+
runChain(allHandlers, req, res)
|
|
141
|
+
.then(() => {
|
|
142
|
+
if (!res.writableEnded)
|
|
143
|
+
res.status(204).end();
|
|
144
|
+
})
|
|
145
|
+
.catch((err) => {
|
|
146
|
+
res.abortStream(err);
|
|
147
|
+
});
|
|
148
|
+
return res.responseReady;
|
|
149
|
+
};
|
|
150
|
+
this.websocketConfig = {
|
|
151
|
+
open: async (ws) => {
|
|
152
|
+
const data = ws.data;
|
|
153
|
+
const shim = new BunWebSocketShim(ws);
|
|
154
|
+
data.shim = shim;
|
|
155
|
+
const req = data.req;
|
|
156
|
+
req.websocket = shim;
|
|
157
|
+
req.wsHandled = false;
|
|
158
|
+
const stubRes = makeWsStubResponse();
|
|
159
|
+
await runChain(data.handlers, req, stubRes);
|
|
160
|
+
// Guard against the client disconnecting while runChain was awaiting (e.g. authWebSocket
|
|
161
|
+
// waiting for a LOGIN frame) — mirrors the uWS router's readyState !== 3 / try-catch guard.
|
|
162
|
+
if (!req.wsHandled && shim.readyState !== 3) {
|
|
163
|
+
try {
|
|
164
|
+
ws.close();
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Client already disconnected — nothing to do
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
message: (ws, message) => {
|
|
172
|
+
const data = ws.data;
|
|
173
|
+
const isBinary = typeof message !== "string";
|
|
174
|
+
data.shim?.emit("message", isBinary ? Buffer.from(message) : message, isBinary);
|
|
175
|
+
},
|
|
176
|
+
close: (ws, code, reason) => {
|
|
177
|
+
const data = ws.data;
|
|
178
|
+
if (data.shim)
|
|
179
|
+
data.shim.readyState = 3; // CLOSED
|
|
180
|
+
data.shim?.emit("close", code, reason);
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
this.maxBodySize = maxBodySize;
|
|
184
|
+
this.sslConfig = sslConfig;
|
|
185
|
+
}
|
|
186
|
+
/** Returns `true` if the server is currently listening. */
|
|
187
|
+
get isListening() {
|
|
188
|
+
return this._bunServer !== undefined;
|
|
189
|
+
}
|
|
190
|
+
/** Register global middleware that runs before every route handler. */
|
|
191
|
+
use(...handlers) {
|
|
192
|
+
this.globalMiddleware.push(...handlers);
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Freezes the pre-route middleware count the first time a route is registered.
|
|
197
|
+
* All global middleware registered BEFORE this call is "pre-route" middleware;
|
|
198
|
+
* everything added after is "post-route" (error handlers, metrics, etc.).
|
|
199
|
+
*/
|
|
200
|
+
capturePreRouteCount() {
|
|
201
|
+
if (this.preRouteCount === -1) {
|
|
202
|
+
this.preRouteCount = this.globalMiddleware.length;
|
|
203
|
+
}
|
|
204
|
+
return this.preRouteCount;
|
|
205
|
+
}
|
|
206
|
+
pushRoute(method, route) {
|
|
207
|
+
const list = this.routesByMethod.get(method) ?? [];
|
|
208
|
+
list.push(route);
|
|
209
|
+
this.routesByMethod.set(method, list);
|
|
210
|
+
}
|
|
211
|
+
register(method, routePath, handlers, isHead = false) {
|
|
212
|
+
const pre = this.capturePreRouteCount();
|
|
213
|
+
const normalized = normalizePath(routePath);
|
|
214
|
+
const isRootWildcard = normalized === "/*";
|
|
215
|
+
if (isRootWildcard)
|
|
216
|
+
this.rootWildcardVerbs.add(method.toLowerCase());
|
|
217
|
+
const hasWildcardSuffix = isRootWildcard || normalized.endsWith("/*");
|
|
218
|
+
// Strip the trailing "/*" (2 chars) to get the prefix; "/*" itself strips to "" -> segments [].
|
|
219
|
+
const segments = hasWildcardSuffix ? splitPath(normalized.slice(0, -2)) : splitPath(normalized);
|
|
220
|
+
this.pushRoute(method, { segments, hasWildcardSuffix, isRootWildcard, handlers, preLength: pre, isHead });
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
// -------------------------------------------------------------------------
|
|
224
|
+
// HTTP verb methods
|
|
225
|
+
// -------------------------------------------------------------------------
|
|
226
|
+
get(routePath, ...handlers) {
|
|
227
|
+
return this.register("GET", routePath, handlers);
|
|
228
|
+
}
|
|
229
|
+
post(routePath, ...handlers) {
|
|
230
|
+
return this.register("POST", routePath, handlers);
|
|
231
|
+
}
|
|
232
|
+
put(routePath, ...handlers) {
|
|
233
|
+
return this.register("PUT", routePath, handlers);
|
|
234
|
+
}
|
|
235
|
+
delete(routePath, ...handlers) {
|
|
236
|
+
return this.register("DELETE", routePath, handlers);
|
|
237
|
+
}
|
|
238
|
+
patch(routePath, ...handlers) {
|
|
239
|
+
return this.register("PATCH", routePath, handlers);
|
|
240
|
+
}
|
|
241
|
+
head(routePath, ...handlers) {
|
|
242
|
+
return this.register("HEAD", routePath, handlers, true);
|
|
243
|
+
}
|
|
244
|
+
options(routePath, ...handlers) {
|
|
245
|
+
return this.register("OPTIONS", routePath, handlers);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Registers a WebSocket route. Handlers follow the same `(req, res, next)` pattern as HTTP
|
|
249
|
+
* routes; they receive `req.websocket` containing the Bun WebSocket shim.
|
|
250
|
+
*
|
|
251
|
+
* `upgradeAuth` is an optional pre-upgrade auth function, run synchronously inside `fetch()`
|
|
252
|
+
* before the handshake. If it returns `{ reject: true }`, an HTTP 401 is sent and the upgrade
|
|
253
|
+
* is aborted. If it returns `{ user, ... }`, those credentials are attached to the request so
|
|
254
|
+
* downstream middleware sees an authenticated user. If it returns `{}`, auth falls through to
|
|
255
|
+
* the post-upgrade message-based LOGIN flow.
|
|
256
|
+
*/
|
|
257
|
+
ws(routePath, handlers, _wsOptions, upgradeAuth) {
|
|
258
|
+
const normalized = normalizePath(routePath);
|
|
259
|
+
this.wsRoutes.push({ segments: splitPath(normalized), handlers, upgradeAuth });
|
|
260
|
+
return this;
|
|
261
|
+
}
|
|
262
|
+
// -------------------------------------------------------------------------
|
|
263
|
+
// Route matching
|
|
264
|
+
// -------------------------------------------------------------------------
|
|
265
|
+
/**
|
|
266
|
+
* Matches a request against the route table. Exact-length static/param routes always outrank
|
|
267
|
+
* wildcard-suffixed routes, matching uWS's `best ?? wildcard` fallback behavior. Among wildcard
|
|
268
|
+
* candidates, the one with the longest (most specific) matching prefix wins — e.g. `/static/*`
|
|
269
|
+
* beats a bare `/*` for requests under `/static`.
|
|
270
|
+
*
|
|
271
|
+
* `reqHasTrailingSlash` is required to replicate uWS's own wildcard boundary rule, verified
|
|
272
|
+
* empirically against real uWS: a `<prefix>/*` route matches `<prefix>/` and anything nested
|
|
273
|
+
* under it, but NOT the bare `<prefix>` with no trailing slash — a distinction that's lost if
|
|
274
|
+
* matching were done on segment arrays alone, since `/static` and `/static/` produce the same
|
|
275
|
+
* segment list once empty segments are filtered out.
|
|
276
|
+
*/
|
|
277
|
+
matchRoute(method, reqSegments, reqHasTrailingSlash) {
|
|
278
|
+
const candidates = this.routesByMethod.get(method);
|
|
279
|
+
if (!candidates)
|
|
280
|
+
return null;
|
|
281
|
+
let best = null;
|
|
282
|
+
let bestScore = -1;
|
|
283
|
+
let bestWildcard = null;
|
|
284
|
+
let bestWildcardSpecificity = -1;
|
|
285
|
+
for (const route of candidates) {
|
|
286
|
+
if (route.hasWildcardSuffix) {
|
|
287
|
+
const prefixLen = route.segments.length;
|
|
288
|
+
const hasContentAfterPrefix = reqSegments.length > prefixLen || (reqSegments.length === prefixLen && reqHasTrailingSlash);
|
|
289
|
+
if (!hasContentAfterPrefix)
|
|
290
|
+
continue;
|
|
291
|
+
const score = matchSegments(route.segments, reqSegments.slice(0, prefixLen));
|
|
292
|
+
if (score === null)
|
|
293
|
+
continue;
|
|
294
|
+
if (prefixLen > bestWildcardSpecificity) {
|
|
295
|
+
bestWildcardSpecificity = prefixLen;
|
|
296
|
+
bestWildcard = route;
|
|
297
|
+
}
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
const score = matchSegments(route.segments, reqSegments);
|
|
301
|
+
if (score !== null && score > bestScore) {
|
|
302
|
+
bestScore = score;
|
|
303
|
+
best = route;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return best ?? bestWildcard;
|
|
307
|
+
}
|
|
308
|
+
matchWsRoute(reqSegments) {
|
|
309
|
+
let best = null;
|
|
310
|
+
let bestScore = -1;
|
|
311
|
+
for (const route of this.wsRoutes) {
|
|
312
|
+
const score = matchSegments(route.segments, reqSegments);
|
|
313
|
+
if (score !== null && score > bestScore) {
|
|
314
|
+
bestScore = score;
|
|
315
|
+
best = route;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return best;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Starts listening on the given host and port.
|
|
322
|
+
* Resolves when the server is ready; rejects if the port cannot be bound.
|
|
323
|
+
*/
|
|
324
|
+
listen(host, port) {
|
|
325
|
+
// Register a catch-all OPTIONS handler so CORS global middleware runs for all preflight
|
|
326
|
+
// requests. preLength=0 places all globalMiddleware as "post-route" so it all executes
|
|
327
|
+
// sequentially; the CORS middleware terminates the chain early for OPTIONS (sends 204
|
|
328
|
+
// without calling next). Mirrors Router.ts::listen()'s uWS behavior exactly.
|
|
329
|
+
this.pushRoute("OPTIONS", {
|
|
330
|
+
segments: [],
|
|
331
|
+
hasWildcardSuffix: true,
|
|
332
|
+
isRootWildcard: true,
|
|
333
|
+
handlers: [],
|
|
334
|
+
preLength: 0,
|
|
335
|
+
isHead: false,
|
|
336
|
+
});
|
|
337
|
+
// Register a JSON 404 fallback for any request that doesn't match a registered route,
|
|
338
|
+
// respecting an app-defined literal `/*` route (e.g. a `BaseStaticRoute` mounted at the site
|
|
339
|
+
// root) via `rootWildcardVerbs`, exactly as the uWS router does.
|
|
340
|
+
const notFoundHandler = (_req, _res, next) => {
|
|
341
|
+
next(new ApiError(ApiErrors.NOT_FOUND, 404, ApiErrorMessages.NOT_FOUND));
|
|
342
|
+
};
|
|
343
|
+
const verbs = [
|
|
344
|
+
"get", "post", "put", "delete", "patch", "head",
|
|
345
|
+
];
|
|
346
|
+
for (const verb of verbs) {
|
|
347
|
+
if (!this.rootWildcardVerbs.has(verb)) {
|
|
348
|
+
this[verb]("/*", notFoundHandler);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const tls = this.sslConfig ? mapSslConfigToBunTls(this.sslConfig) : undefined;
|
|
352
|
+
return new Promise((resolve, reject) => {
|
|
353
|
+
try {
|
|
354
|
+
this._bunServer = Bun.serve({
|
|
355
|
+
hostname: host,
|
|
356
|
+
port,
|
|
357
|
+
fetch: this.fetchHandler,
|
|
358
|
+
websocket: this.websocketConfig,
|
|
359
|
+
tls,
|
|
360
|
+
});
|
|
361
|
+
this.listenPort = this._bunServer.port ?? port;
|
|
362
|
+
resolve();
|
|
363
|
+
}
|
|
364
|
+
catch (err) {
|
|
365
|
+
reject(err instanceof Error ? err : new Error(`Failed to listen on ${host}:${port}`));
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
/** Stops the server, closing the listen socket. */
|
|
370
|
+
close() {
|
|
371
|
+
if (this._bunServer) {
|
|
372
|
+
void this._bunServer.stop();
|
|
373
|
+
this._bunServer = undefined;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
//# sourceMappingURL=BunRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BunRouter.js","sourceRoot":"","sources":["../../../../src/http/bun/BunRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2020-2026 Jean-Philippe Steinmetz. All rights reserved.
|
|
3
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
4
|
+
import { EventEmitter } from "events";
|
|
5
|
+
/**
|
|
6
|
+
* Wraps a Bun `ServerWebSocket` handle and exposes an EventEmitter-based API compatible with
|
|
7
|
+
* `IWebSocketShim`, mirroring `UWSWebSocketShim`'s behavior for the uWS-backed router so that
|
|
8
|
+
* route handlers (e.g. `BaseAdminRoute`) and `AuthMiddleware.authWebSocket()` work unchanged
|
|
9
|
+
* regardless of which runtime is active.
|
|
10
|
+
*/
|
|
11
|
+
export class BunWebSocketShim extends EventEmitter {
|
|
12
|
+
constructor(ws) {
|
|
13
|
+
super();
|
|
14
|
+
this.readyState = 1; // OPEN
|
|
15
|
+
this._ws = ws;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Sends data over the WebSocket connection.
|
|
19
|
+
* @param data The data to send.
|
|
20
|
+
* @param cb Optional callback invoked on completion or error.
|
|
21
|
+
*/
|
|
22
|
+
send(data, cb) {
|
|
23
|
+
try {
|
|
24
|
+
const result = this._ws.send(typeof data === "string" ? data : Buffer.from(data));
|
|
25
|
+
// Bun's ws.send returns bytes sent on success, 0 when the message was dropped due to
|
|
26
|
+
// backpressure, or a negative number when it was queued to be sent once backpressure
|
|
27
|
+
// clears (not itself a failure) — only treat 0 as an actual send failure.
|
|
28
|
+
if (cb)
|
|
29
|
+
cb(result === 0 ? new Error("Bun backpressure: send dropped") : undefined);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (cb)
|
|
33
|
+
cb(err);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Closes the WebSocket connection with an optional code and reason.
|
|
38
|
+
*/
|
|
39
|
+
close(code, reason) {
|
|
40
|
+
try {
|
|
41
|
+
this._ws.close(code, reason);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Socket may already be closed
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=BunWebSocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BunWebSocket.js","sourceRoot":"","sources":["../../../../src/http/bun/BunWebSocket.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,wEAAwE;AACxE,+EAA+E;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAgBtC;;;;;GAKG;AACH,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IAI9C,YAAY,EAAuB;QAC/B,KAAK,EAAE,CAAC;QAHL,eAAU,GAAW,CAAC,CAAC,CAAC,OAAO;QAIlC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACI,IAAI,CAAC,IAAS,EAAE,EAA0B;QAC7C,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAClF,qFAAqF;YACrF,qFAAqF;YACrF,0EAA0E;YAC1E,IAAI,EAAE;gBAAE,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACvF,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,IAAI,EAAE;gBAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,IAAa,EAAE,MAAe;QACvC,IAAI,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACL,+BAA+B;QACnC,CAAC;IACL,CAAC;CACJ"}
|
package/dist/lib/http/index.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
|
|
1
|
+
export { isBunRuntime } from "./RuntimeDetect.js";
|
|
2
|
+
export { extractParamNames, makeWsStubResponse, runChain } from "./MiddlewareChain.js";
|
|
3
|
+
// uWS-backed adapter. `HttpRouter` is exported as a type only — the class itself value-imports
|
|
4
|
+
// `uWebSockets.js` at module load, which does not work under Bun. Consumers that only annotate with
|
|
5
|
+
// the type stay safe on every runtime; constructing one is done internally by Server.ts via a
|
|
6
|
+
// dynamic import gated on `isBunRuntime()`.
|
|
7
|
+
export { UWSRequest, UWSResponse, readBody } from "./uWS/Adapters.js";
|
|
8
|
+
export { UWSWebSocketShim, createWebSocketStream } from "./uWS/WebSocket.js";
|
|
9
|
+
// Bun-backed adapter. Safe to value-export unconditionally on every runtime — these modules never
|
|
10
|
+
// touch the `Bun` global outside of method bodies invoked at runtime.
|
|
11
|
+
export { BunRequest, BunResponse, readBunBody } from "./bun/BunAdapters.js";
|
|
12
|
+
export { BunRouter } from "./bun/BunRouter.js";
|
|
13
|
+
export { BunWebSocketShim } from "./bun/BunWebSocket.js";
|
|
4
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/http/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/http/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAGvF,+FAA+F;AAC/F,oGAAoG;AACpG,8FAA8F;AAC9F,4CAA4C;AAC5C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGtE,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE7E,kGAAkG;AAClG,sEAAsE;AACtE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ApiErrorMessages, ApiErrors } from "../../ApiErrors.js";
|
|
1
2
|
/** Parses a `cookie` header string into a key/value map. */
|
|
2
|
-
function parseCookies(cookieHeader) {
|
|
3
|
+
export function parseCookies(cookieHeader) {
|
|
3
4
|
const result = {};
|
|
4
5
|
if (!cookieHeader)
|
|
5
6
|
return result;
|
|
@@ -14,7 +15,7 @@ function parseCookies(cookieHeader) {
|
|
|
14
15
|
return result;
|
|
15
16
|
}
|
|
16
17
|
/** Parses a URL query string (without leading `?`) into a key/value map. */
|
|
17
|
-
function parseQueryString(qs) {
|
|
18
|
+
export function parseQueryString(qs) {
|
|
18
19
|
const result = {};
|
|
19
20
|
if (!qs)
|
|
20
21
|
return result;
|
|
@@ -51,6 +52,32 @@ function parseQueryString(qs) {
|
|
|
51
52
|
}
|
|
52
53
|
return result;
|
|
53
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Parses a raw request body Buffer according to its content-type header. Shared by both the
|
|
57
|
+
* uWS-backed and Bun-backed HTTP adapters so body-parsing rules stay in one place:
|
|
58
|
+
* `application/json` is parsed (falling back to the raw string on parse failure),
|
|
59
|
+
* `application/x-www-form-urlencoded` is parsed into a plain object, and anything else is
|
|
60
|
+
* returned as the raw Buffer. Returns `undefined` for an empty body.
|
|
61
|
+
*/
|
|
62
|
+
export function parseBodyByContentType(raw, contentType) {
|
|
63
|
+
if (raw.length === 0)
|
|
64
|
+
return undefined;
|
|
65
|
+
const ct = contentType.toLowerCase();
|
|
66
|
+
if (ct.includes("application/json")) {
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(raw.toString("utf8"));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return raw.toString("utf8");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (ct.includes("application/x-www-form-urlencoded")) {
|
|
75
|
+
return Object.fromEntries(new URLSearchParams(raw.toString("utf8")).entries());
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
return raw;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
54
81
|
/**
|
|
55
82
|
* Adapts a uWS `HttpRequest` to the framework-agnostic `HttpRequest` interface.
|
|
56
83
|
*
|
|
@@ -228,47 +255,58 @@ export class UWSResponse {
|
|
|
228
255
|
return `${code} ${messages[code] || "Unknown"}`;
|
|
229
256
|
}
|
|
230
257
|
}
|
|
258
|
+
/** Default maximum accepted request body size (10 MiB) when no explicit limit is configured. */
|
|
259
|
+
export const DEFAULT_MAX_BODY_SIZE = 10 * 1024 * 1024;
|
|
231
260
|
/**
|
|
232
261
|
* Reads the full request body from a uWS response object as a Buffer.
|
|
233
262
|
* Body parsing (JSON / URL-encoded) is applied based on content-type and the result
|
|
234
263
|
* is cached on `req.body` / `req.rawBody`.
|
|
264
|
+
*
|
|
265
|
+
* If the accumulated body exceeds `maxBodySize`, a `413 Payload Too Large` response is written
|
|
266
|
+
* directly and the connection is ended — the caller must check the resolved value and skip running
|
|
267
|
+
* any further middleware/routing for this request when it's `false`, since a response has already
|
|
268
|
+
* been sent.
|
|
269
|
+
*
|
|
270
|
+
* @returns `true` if the body was read normally (or there was none to read), `false` if the request
|
|
271
|
+
* was rejected for exceeding `maxBodySize`.
|
|
235
272
|
*/
|
|
236
|
-
export function readBody(uwsRes, req) {
|
|
237
|
-
return new Promise((resolve
|
|
273
|
+
export function readBody(uwsRes, req, maxBodySize = DEFAULT_MAX_BODY_SIZE) {
|
|
274
|
+
return new Promise((resolve) => {
|
|
238
275
|
if (req.body !== undefined) {
|
|
239
|
-
resolve();
|
|
276
|
+
resolve(true);
|
|
240
277
|
return;
|
|
241
278
|
}
|
|
242
279
|
let hasChunks = false;
|
|
280
|
+
let totalLength = 0;
|
|
281
|
+
let rejected = false;
|
|
243
282
|
const chunks = [];
|
|
244
283
|
const parseBody = (raw) => {
|
|
245
284
|
req.rawBody = raw;
|
|
246
|
-
|
|
247
|
-
const contentType = String(req.headers["content-type"] || "").toLowerCase();
|
|
248
|
-
if (contentType.includes("application/json")) {
|
|
249
|
-
try {
|
|
250
|
-
req.body = JSON.parse(raw.toString("utf8"));
|
|
251
|
-
}
|
|
252
|
-
catch {
|
|
253
|
-
req.body = raw.toString("utf8");
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
else if (contentType.includes("application/x-www-form-urlencoded")) {
|
|
257
|
-
req.body = Object.fromEntries(new URLSearchParams(raw.toString("utf8")).entries());
|
|
258
|
-
}
|
|
259
|
-
else {
|
|
260
|
-
req.body = raw;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
req.body = undefined;
|
|
265
|
-
}
|
|
285
|
+
req.body = parseBodyByContentType(raw, String(req.headers["content-type"] || ""));
|
|
266
286
|
};
|
|
267
287
|
uwsRes.onData((chunk, isLast) => {
|
|
288
|
+
// The response has already been ended below; ignore any further chunks uWS may deliver.
|
|
289
|
+
if (rejected)
|
|
290
|
+
return;
|
|
291
|
+
totalLength += chunk.byteLength;
|
|
292
|
+
if (totalLength > maxBodySize) {
|
|
293
|
+
rejected = true;
|
|
294
|
+
uwsRes.cork(() => {
|
|
295
|
+
uwsRes.writeStatus("413 Payload Too Large");
|
|
296
|
+
uwsRes.writeHeader("content-type", "application/json");
|
|
297
|
+
uwsRes.end(JSON.stringify({
|
|
298
|
+
code: ApiErrors.PAYLOAD_TOO_LARGE,
|
|
299
|
+
status: 413,
|
|
300
|
+
message: ApiErrorMessages.PAYLOAD_TOO_LARGE,
|
|
301
|
+
}));
|
|
302
|
+
});
|
|
303
|
+
resolve(false);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
268
306
|
if (isLast && !hasChunks) {
|
|
269
307
|
// Fast path: single-chunk body — skip the chunks array and Buffer.concat entirely.
|
|
270
308
|
parseBody(Buffer.from(chunk));
|
|
271
|
-
resolve();
|
|
309
|
+
resolve(true);
|
|
272
310
|
return;
|
|
273
311
|
}
|
|
274
312
|
// Multi-chunk path: copy each chunk (ArrayBuffer is only valid during this callback).
|
|
@@ -276,7 +314,7 @@ export function readBody(uwsRes, req) {
|
|
|
276
314
|
chunks.push(Buffer.from(chunk));
|
|
277
315
|
if (isLast) {
|
|
278
316
|
parseBody(Buffer.concat(chunks));
|
|
279
|
-
resolve();
|
|
317
|
+
resolve(true);
|
|
280
318
|
}
|
|
281
319
|
});
|
|
282
320
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Adapters.js","sourceRoot":"","sources":["../../../../src/http/uWS/Adapters.ts"],"names":[],"mappings":"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"}
|