-
-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
step 1 for middleware architecture #545
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
9507909
rename src/lib/middleware to src/lib/old-wrappers
dai-shi 1c2de97
wip: middleware interface and runner
dai-shi 23bda53
remove unused
dai-shi 5e24880
Merge branch 'main' into middleware-api-1
dai-shi 7a998bc
fallback middleware
dai-shi 520b997
Merge branch 'main' into middleware-api-1
dai-shi 38f40a0
add ssr middleware
dai-shi 609fff2
Merge branch 'main' into middleware-api-1
dai-shi 253d16a
refactor
dai-shi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
export { honoMiddleware as unstable_honoMiddleware } from './lib/middleware/hono-dev.js'; | ||
export { connectMiddleware as unstable_connectMiddleware } from './lib/middleware/connect-dev.js'; | ||
export { honoMiddleware as unstable_honoMiddleware } from './lib/old-wrappers/hono-dev.js'; | ||
export { connectMiddleware as unstable_connectMiddleware } from './lib/old-wrappers/connect-dev.js'; | ||
|
||
export { createHandler as unstable_createHandler } from './lib/handlers/handler-dev.js'; | ||
export { build } from './lib/builder/build.js'; | ||
export { build as unstable_build } from './lib/builder/build.js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import type { MiddlewareHandler } from 'hono'; | ||
|
||
import type { HandlerContext, MiddlewareOptions } from '../middleware/types.js'; | ||
|
||
const createEmptyReadableStream = () => | ||
new ReadableStream({ | ||
start(controller) { | ||
controller.close(); | ||
}, | ||
}); | ||
|
||
export const runner = (options: MiddlewareOptions): MiddlewareHandler => { | ||
const middlewareList = [ | ||
import('waku/middleware').then((mod) => mod.ssr), | ||
import('waku/middleware').then((mod) => mod.rsc), | ||
// import('waku/middleware').then((mod) => mod.fallback), | ||
]; | ||
const handlersPromise = Promise.all( | ||
middlewareList.map(async (middleware) => (await middleware)(options)), | ||
); | ||
return async (c, next) => { | ||
const ctx: HandlerContext = { | ||
req: { | ||
body: c.req.raw.body || createEmptyReadableStream(), | ||
url: new URL(c.req.url), | ||
method: c.req.method, | ||
headers: Object.fromEntries( | ||
Array.from(c.req.raw.headers.entries()).map(([k, v]) => [k, v]), | ||
), | ||
}, | ||
res: {}, | ||
context: {}, | ||
}; | ||
const handlers = await handlersPromise; | ||
const run = async (index: number) => { | ||
if (index >= handlers.length) { | ||
return next(); | ||
} | ||
let alreadyCalled = false; | ||
await handlers[index]!(ctx, async () => { | ||
if (!alreadyCalled) { | ||
alreadyCalled = true; | ||
await run(index + 1); | ||
} | ||
}); | ||
}; | ||
await run(0); | ||
if ('status' in ctx.res) { | ||
c.status(ctx.res.status as any); | ||
} | ||
if ('headers' in ctx.res) { | ||
for (const [k, v] of Object.entries(ctx.res.headers)) { | ||
c.header(k, v); | ||
} | ||
} | ||
if ('body' in ctx.res) { | ||
return c.body(ctx.res.body); | ||
} | ||
return c.body(null); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { stringToStream } from '../utils/stream.js'; | ||
import type { Middleware } from './types.js'; | ||
|
||
export const fallback: Middleware = (options) => { | ||
if (options.cmd === 'dev') { | ||
// pass through in dev command | ||
return async (_ctx, next) => next(); | ||
} | ||
|
||
const entriesPromise = options.loadEntries(); | ||
|
||
return async (ctx, _next) => { | ||
const entries = await entriesPromise; | ||
ctx.res.body = stringToStream(entries.publicIndexHtml); | ||
ctx.res.headers = { | ||
...ctx.res.headers, | ||
'content-type': 'text/html; charset=utf-8', | ||
}; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { resolveConfig } from '../config.js'; | ||
import { decodeInput, hasStatusCode } from '../renderers/utils.js'; | ||
import { renderRsc } from '../renderers/rsc-renderer.js'; | ||
import type { Middleware } from './types.js'; | ||
|
||
export const rsc: Middleware = (options) => { | ||
if (options.cmd === 'dev') { | ||
throw new Error('not implemented yet'); | ||
} | ||
|
||
(globalThis as any).__WAKU_PRIVATE_ENV__ = options.env || {}; | ||
const configPromise = resolveConfig(options.config || {}); | ||
const entriesPromise = options.loadEntries(); | ||
|
||
return async (ctx, next) => { | ||
const [config, entries] = await Promise.all([ | ||
configPromise, | ||
entriesPromise, | ||
]); | ||
const basePrefix = config.basePath + config.rscPath + '/'; | ||
if (ctx.req.url.pathname.startsWith(basePrefix)) { | ||
const { method, headers } = ctx.req; | ||
if (method !== 'GET' && method !== 'POST') { | ||
throw new Error(`Unsupported method '${method}'`); | ||
} | ||
try { | ||
const input = decodeInput( | ||
ctx.req.url.pathname.slice(basePrefix.length), | ||
); | ||
const readable = await renderRsc({ | ||
config, | ||
input, | ||
searchParams: ctx.req.url.searchParams, | ||
method, | ||
context: ctx.context, | ||
body: ctx.req.body, | ||
contentType: headers['content-type'] || '', | ||
isDev: false, | ||
entries, | ||
}); | ||
ctx.res.body = readable; | ||
return; | ||
} catch (err) { | ||
if (hasStatusCode(err)) { | ||
ctx.res.status = err.statusCode; | ||
} else { | ||
console.info('Cannot process RSC', err); | ||
ctx.res.status = 500; | ||
} | ||
return; | ||
} | ||
} | ||
await next(); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { resolveConfig } from '../config.js'; | ||
import { getPathMapping } from '../utils/path.js'; | ||
import { renderHtml } from '../renderers/html-renderer.js'; | ||
import { hasStatusCode } from '../renderers/utils.js'; | ||
import { renderRsc, getSsrConfig } from '../renderers/rsc-renderer.js'; | ||
import type { Middleware } from './types.js'; | ||
|
||
export const CLIENT_PREFIX = 'client/'; | ||
|
||
export const ssr: Middleware = (options) => { | ||
if (options.cmd === 'dev') { | ||
throw new Error('not implemented yet'); | ||
} | ||
|
||
(globalThis as any).__WAKU_PRIVATE_ENV__ = options.env || {}; | ||
const configPromise = resolveConfig(options.config || {}); | ||
const entriesPromise = options.loadEntries(); | ||
|
||
return async (ctx, next) => { | ||
const [config, entries] = await Promise.all([ | ||
configPromise, | ||
entriesPromise, | ||
]); | ||
try { | ||
const { dynamicHtmlPaths } = entries; | ||
const htmlHead = dynamicHtmlPaths.find(([pathSpec]) => | ||
getPathMapping(pathSpec, ctx.req.url.pathname), | ||
)?.[1]; | ||
if (htmlHead) { | ||
const readable = await renderHtml({ | ||
config, | ||
pathname: ctx.req.url.pathname, | ||
searchParams: ctx.req.url.searchParams, | ||
htmlHead, | ||
// TODO refactor: avoid this and try using next() instead | ||
renderRscForHtml: (input, searchParams) => | ||
renderRsc({ | ||
entries, | ||
config, | ||
input, | ||
searchParams, | ||
method: 'GET', | ||
context: ctx.context, | ||
isDev: false, | ||
}), | ||
getSsrConfigForHtml: (pathname, searchParams) => | ||
getSsrConfig({ | ||
config, | ||
pathname, | ||
searchParams, | ||
isDev: false, | ||
entries, | ||
}), | ||
loadClientModule: (key) => entries.loadModule(CLIENT_PREFIX + key), | ||
isDev: false, | ||
loadModule: entries.loadModule, | ||
}); | ||
if (readable) { | ||
ctx.res.headers = { | ||
...ctx.res.headers, | ||
'content-type': 'text/html; charset=utf-8', | ||
}; | ||
ctx.res.body = readable; | ||
return; | ||
} | ||
} | ||
} catch (err) { | ||
if (hasStatusCode(err)) { | ||
ctx.res.status = err.statusCode; | ||
} else { | ||
console.info('Cannot process SSR', err); | ||
ctx.res.status = 500; | ||
} | ||
return; | ||
} | ||
await next(); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import type { Config } from '../../config.js'; | ||
import type { EntriesPrd } from '../../server.js'; | ||
|
||
export type HandlerReq = { | ||
readonly body: ReadableStream; | ||
readonly url: URL; | ||
readonly method: string; | ||
readonly headers: Record<string, string>; | ||
}; | ||
|
||
export type HandlerRes = { | ||
body?: ReadableStream; | ||
headers?: Record<string, string>; | ||
status?: number; | ||
}; | ||
|
||
export type RscContext = Record<string, unknown>; | ||
|
||
export type HandlerContext = { | ||
readonly req: HandlerReq; | ||
readonly res: HandlerRes; | ||
readonly context: RscContext; | ||
}; | ||
|
||
export type Handler = ( | ||
ctx: HandlerContext, | ||
next: () => Promise<void>, | ||
) => Promise<void>; | ||
|
||
export type MiddlewareOptions = { | ||
config?: Config; | ||
env?: Record<string, string>; | ||
} & ({ cmd: 'dev' } | { cmd: 'start'; loadEntries: () => Promise<EntriesPrd> }); | ||
|
||
export type Middleware = (options: MiddlewareOptions) => Handler; |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It only works behind this flag.