Comparing version 0.2.4 to 0.3.0
@@ -7,2 +7,3 @@ /// <reference types="node" /> | ||
import { Router } from './router.js'; | ||
export * from './middleware/index.js'; | ||
export declare const NEXT = "next"; | ||
@@ -9,0 +10,0 @@ export declare const NEXT_ROUTE = "route"; |
@@ -6,2 +6,3 @@ import { createSecureServer, createServer, } from 'node:http2'; | ||
import { Router, routerPrototype } from './router.js'; | ||
export * from './middleware/index.js'; | ||
export const NEXT = 'next'; | ||
@@ -44,3 +45,3 @@ export const NEXT_ROUTE = 'route'; | ||
try { | ||
const result = await app.handleRequest(req.path, req, res); | ||
const result = await app.handleRequest(req.path, '/', req, res); | ||
if (result == 'next' && !res.responseSent) { | ||
@@ -47,0 +48,0 @@ res.status(404); |
@@ -19,3 +19,3 @@ import { randomUUID } from 'node:crypto'; | ||
return async (req, res) => { | ||
if (req.headers['content-type'].includes('multipart/form-data')) { | ||
if (req.headers['content-type']?.includes('multipart/form-data')) { | ||
let data = ''; | ||
@@ -22,0 +22,0 @@ const files = {}; |
export function deserializeJsonPayload(options) { | ||
const parse = options?.parse ?? JSON.parse; | ||
return async (req, res) => { | ||
if (req.headers['content-type'].includes('json')) { | ||
if (req.headers['content-type']?.includes('json')) { | ||
let data = ''; | ||
@@ -6,0 +6,0 @@ for await (const chunk of req.rawRequest) { |
@@ -65,3 +65,2 @@ import { randomUUID } from 'node:crypto'; | ||
this._status = statusCode; | ||
return this; | ||
}, | ||
@@ -89,3 +88,2 @@ asEventSource(value) { | ||
this._eventSource = value; | ||
return this; | ||
}, | ||
@@ -144,3 +142,2 @@ write(data) { | ||
'data: ' + preparedData + '\n\n'); | ||
return this; | ||
}, | ||
@@ -147,0 +144,0 @@ json(data) { |
@@ -8,3 +8,3 @@ import { type PathString, type PathMatcher } from './path-matching.js'; | ||
interface __InternalRouter extends Router { | ||
handleRequest(remainingPath: PathString, req: Request, res: Response, err?: unknown): Promise<void | 'next'>; | ||
handleRequest(remainingPath: PathString, matchedPath: string, req: Request, res: Response, err?: unknown, queryAssigned?: boolean): Promise<void | 'next'>; | ||
__getMatchingRoute(state: __RouterState): Generator<__InternalRoute>; | ||
@@ -32,5 +32,6 @@ routes: __InternalRoute[]; | ||
interface __InternalRoute extends Route { | ||
handleRequest(remainingPath: string, req: Request, res: Response, err?: unknown): Promise<void | 'next'>; | ||
handleRequest(remainingPath: string, matchedPath: string, req: Request, res: Response, err?: unknown, queryAssigned?: boolean): Promise<void | 'next'>; | ||
__getMatchingHandlers(this: __InternalRoute, state: __RouteHandlerState): Generator<(RequestHandler | ErrorHandler | __InternalRouter)[]>; | ||
handlers: [method: HandlerHttpMethods, ...handlers: (RequestHandler | ErrorHandler | Router)[]][]; | ||
__addHandler(this: __InternalRoute, method: HandlerHttpMethods | null, ...handlers: (RequestHandler | ErrorHandler | Router)[]): this; | ||
pathMatcher: PathMatcher; | ||
@@ -41,5 +42,7 @@ } | ||
error?: unknown; | ||
matchedPath?: PathString; | ||
path: PathString; | ||
req: Request; | ||
end?: boolean; | ||
queryAssigned?: boolean; | ||
} | ||
@@ -49,3 +52,6 @@ interface __RouteHandlerState { | ||
req: Request; | ||
path: string; | ||
matchedPath?: string; | ||
end?: boolean; | ||
queryAssigned?: boolean; | ||
} | ||
@@ -95,3 +101,3 @@ interface Route { | ||
*/ | ||
handleRequest(this: __InternalRouter, path: PathString, req: Request, res: Response): Promise<void | 'next'>; | ||
handleRequest(this: __InternalRouter, path: PathString, matchedPath: PathString, req: Request, res: Response, err?: unknown, queryAssigned?: boolean): Promise<void | 'next'>; | ||
__getMatchingRoute: (state: __RouterState) => Generator<__InternalRoute>; | ||
@@ -98,0 +104,0 @@ __addRoute(this: __InternalRouter, method: HandlerHttpMethods | null, path: PathMatcher, ...handlers: (RequestHandler | ErrorHandler | Router)[]): Fluvial.__InternalRoute; |
@@ -68,14 +68,15 @@ import { getRouteParams, getQueryParams, } from './path-matching.js'; | ||
*/ | ||
async handleRequest(path, req, res) { | ||
async handleRequest(path, matchedPath, req, res, err, queryAssigned = false) { | ||
// by default, if there doesn't happen to be any handlers that work with this request, it should direct it to the next handler found | ||
let latestResult = 'next'; | ||
const routerState = { | ||
error: null, | ||
error: err ?? null, | ||
path, | ||
req, | ||
matchedPath, | ||
queryAssigned, | ||
}; | ||
for (const route of this.__getMatchingRoute(routerState)) { | ||
try { | ||
const remainingPath = removeMatchedPathPortion(path, route.pathMatcher); | ||
latestResult = await route.handleRequest(remainingPath, req, res, routerState.error); | ||
latestResult = await route.handleRequest(path, matchedPath, req, res, routerState.error, routerState.queryAssigned); | ||
if (routerState.error) { | ||
@@ -107,7 +108,10 @@ // consider the error handled and resolve as if not errored | ||
const params = getRouteParams(state.path, route.pathMatcher); | ||
if (!state.queryAssigned) { | ||
// TODO: put this at the beginning of the request cycle; the assignment here is not great... | ||
const query = getQueryParams(state.path); | ||
Object.assign(state.req.query, query); | ||
state.queryAssigned = true; | ||
} | ||
if (params) { | ||
// TODO: put this at the beginning of the request cycle; doing it each time doesn't make sense... | ||
const query = getQueryParams(state.path); | ||
Object.assign(state.req.params, params); | ||
Object.assign(state.req.query, query); | ||
yield route; | ||
@@ -135,3 +139,3 @@ } | ||
*/ | ||
async handleRequest(remainingPath, req, res, err) { | ||
async handleRequest(path, matchedPath, req, res, err, queryAssigned = false) { | ||
// by default, if there doesn't happen to be any handlers that work with this request, it should direct it to the next handler found | ||
@@ -142,2 +146,5 @@ let latestResult = 'next'; | ||
req, | ||
path, | ||
matchedPath, | ||
queryAssigned, | ||
}; | ||
@@ -159,3 +166,8 @@ for (const handlers of this.__getMatchingHandlers(handlerState)) { | ||
else { | ||
latestResult = await handler.handleRequest(remainingPath, req, res, handlerState.error); | ||
// removing the matched portion here instead of the router because otherwise future route handlers fail to have the necessary information | ||
const remainingPath = removeMatchedPathPortion(path, this.pathMatcher) || '/'; | ||
const previousPath = remainingPath == path ? | ||
matchedPath : | ||
(matchedPath == '/' ? '' : matchedPath) + path.slice(0, path.indexOf(remainingPath)); | ||
latestResult = await handler.handleRequest(remainingPath, previousPath, req, res, handlerState.error, handlerState.queryAssigned); | ||
} | ||
@@ -205,2 +217,42 @@ if (latestResult != 'next') { | ||
}, | ||
get(...handlers) { | ||
this.__addHandler('GET', ...handlers); | ||
return this; | ||
}, | ||
post(...handlers) { | ||
this.__addHandler('POST', ...handlers); | ||
return this; | ||
}, | ||
put(...handlers) { | ||
this.__addHandler('PUT', ...handlers); | ||
return this; | ||
}, | ||
patch(...handlers) { | ||
this.__addHandler('PATCH', ...handlers); | ||
return this; | ||
}, | ||
delete(...handlers) { | ||
this.__addHandler('DELETE', ...handlers); | ||
return this; | ||
}, | ||
options(...handlers) { | ||
this.__addHandler('OPTIONS', ...handlers); | ||
return this; | ||
}, | ||
head(...handlers) { | ||
this.__addHandler('HEAD', ...handlers); | ||
return this; | ||
}, | ||
all(...handlers) { | ||
this.__addHandler('ALL', ...handlers); | ||
return this; | ||
}, | ||
catch(...handlers) { | ||
this.__addHandler('ERROR', ...handlers); | ||
return this; | ||
}, | ||
__addHandler(method, ...handlers) { | ||
this.handlers.push([method, ...handlers]); | ||
return this; | ||
}, | ||
}; | ||
@@ -228,3 +280,3 @@ function removeMatchedPathPortion(currentPath, matcher) { | ||
const matcherPortion = matcherPortions[i]; | ||
if (matcherPortion.startsWith(':')) { | ||
if (pathPortion && matcherPortion.startsWith(':')) { | ||
const unprefixedPortion = matcherPortion.slice(1); | ||
@@ -231,0 +283,0 @@ pathLength += 1 + params[unprefixedPortion].length; |
{ | ||
"name": "fluvial", | ||
"version": "0.2.4", | ||
"version": "0.3.0", | ||
"description": "Fluvial: A light http/2 server framework, similar to Express", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
109431
1359