@alignable/bifrost-fastify 0.0.23 → 0.0.25

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/index.d.ts CHANGED
@@ -2,11 +2,20 @@ import { FastifyPluginAsync, FastifyReply, RawServerBase } from 'fastify';
2
2
  import { FastifyRequest } from 'fastify/types/request';
3
3
  import { IncomingMessage, IncomingHttpHeaders as IncomingHttpHeaders$1 } from 'http';
4
4
  import { Http2ServerRequest, IncomingHttpHeaders } from 'http2';
5
+ import { renderPage } from 'vite-plugin-ssr/server';
5
6
  import { AugmentMe } from '@alignable/bifrost';
6
7
 
8
+ type RenderedPageContext = Awaited<ReturnType<typeof renderPage<{
9
+ redirectTo?: string;
10
+ isClientSideNavigation?: boolean;
11
+ _pageId?: string;
12
+ }, {
13
+ urlOriginal: string;
14
+ }>>>;
7
15
  interface ViteProxyPluginOptions {
8
16
  upstream: URL;
9
17
  host: URL;
18
+ onError?: (error: any, pageContext: RenderedPageContext) => void;
10
19
  buildPageContextInit?: (req: FastifyRequest) => Promise<AugmentMe.PageContextInit>;
11
20
  getLayout: (reply: FastifyReply<RawServerBase>) => {
12
21
  layout: string;
package/dist/index.js CHANGED
@@ -11,19 +11,29 @@ function streamToString(stream) {
11
11
  stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
12
12
  });
13
13
  }
14
- async function replyWithPage(reply, pageContext) {
15
- const { httpResponse } = pageContext;
16
- if (pageContext.redirectTo && !pageContext.isClientSideNavigation) {
17
- return reply.redirect(307, pageContext.redirectTo);
18
- }
19
- if (!httpResponse) {
20
- return reply.code(404).type("text/html").send("Not Found");
21
- }
22
- const { body, statusCode, headers } = httpResponse;
23
- return reply.status(statusCode).headers(Object.fromEntries(headers)).send(body);
24
- }
25
14
  var proxyPageId = "/proxy/pages";
26
- var viteProxyPlugin = async (fastify, { upstream, host, buildPageContextInit, rewriteRequestHeaders, getLayout }) => {
15
+ var viteProxyPlugin = async (fastify, {
16
+ upstream,
17
+ host,
18
+ onError,
19
+ buildPageContextInit,
20
+ rewriteRequestHeaders,
21
+ getLayout
22
+ }) => {
23
+ async function replyWithPage(reply, pageContext) {
24
+ const { httpResponse } = pageContext;
25
+ if (onError && httpResponse?.statusCode === 500 && pageContext.errorWhileRendering) {
26
+ onError(pageContext.errorWhileRendering, pageContext);
27
+ }
28
+ if (pageContext.redirectTo && !pageContext.isClientSideNavigation) {
29
+ return reply.redirect(307, pageContext.redirectTo);
30
+ }
31
+ if (!httpResponse) {
32
+ return reply.code(404).type("text/html").send("Not Found");
33
+ }
34
+ const { body, statusCode, headers } = httpResponse;
35
+ return reply.status(statusCode).headers(Object.fromEntries(headers)).send(body);
36
+ }
27
37
  await fastify.register(accepts);
28
38
  await fastify.register(proxy, {
29
39
  upstream: upstream.href,
@@ -44,12 +54,18 @@ var viteProxyPlugin = async (fastify, { upstream, host, buildPageContextInit, re
44
54
  return replyWithPage(reply, pageContext);
45
55
  } else {
46
56
  req.log.info(`bifrost: proxy route matched, proxying to backend`);
57
+ const isPageContext = req.raw.url.includes(
58
+ "/index.pageContext.json"
59
+ );
47
60
  req._proxy = {
48
- isPageContext: req.raw.url.includes("/index.pageContext.json"),
61
+ isPageContext,
49
62
  originalUrl: req.raw.url
50
63
  };
51
64
  req.raw._proxy = true;
52
- req.raw.url = req.raw.url.replace("/index.pageContext.json", "");
65
+ if (isPageContext) {
66
+ req.raw.headers["accept"] = "text/html";
67
+ req.raw.url = req.raw.url.replace("/index.pageContext.json", "");
68
+ }
53
69
  }
54
70
  }
55
71
  },
@@ -97,15 +113,12 @@ var viteProxyPlugin = async (fastify, { upstream, host, buildPageContextInit, re
97
113
  }
98
114
  }
99
115
  const { layout, layoutProps } = getLayout(reply);
100
- if (!layout) {
116
+ if (!isPageContext && !layout) {
101
117
  return reply.send(res);
102
118
  }
103
119
  const html = await streamToString(res);
104
120
  const pageContextInit = {
105
121
  urlOriginal: req.url,
106
- // Nest into fromProxy to avoid triggering pageContextInitHasClientData which forces restorationVisit to refetch pageContext
107
- // Ideally we would just set restorationVisit onBeforeRender to no-op
108
- // https://github.com/brillout/vite-plugin-ssr/discussions/1075#discussioncomment-6758711
109
122
  fromProxy: {
110
123
  layout,
111
124
  layoutProps,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["// Note that this file isn't processed by Vite, see https://github.com/brillout/vite-plugin-ssr/issues/562\nimport { FastifyReply, RawServerBase, FastifyPluginAsync } from \"fastify\";\nimport { FastifyRequest, RequestGenericInterface } from \"fastify/types/request\";\nimport proxy from \"@fastify/http-proxy\";\nimport accepts from \"@fastify/accepts\";\nimport forwarded from \"@fastify/forwarded\";\nimport { Writable } from \"stream\";\nimport { IncomingHttpHeaders, IncomingMessage } from \"http\";\nimport {\n Http2ServerRequest,\n IncomingHttpHeaders as Http2IncomingHttpHeaders,\n} from \"http2\";\nimport { renderPage } from \"vite-plugin-ssr/server\";\nimport { AugmentMe } from \"@alignable/bifrost\";\n\ntype RequestExtendedWithProxy = FastifyRequest<\n RequestGenericInterface,\n RawServerBase\n> & { _proxy?: { isPageContext: boolean; originalUrl?: string } };\n\nfunction streamToString(stream: Writable): Promise<string> {\n const chunks: Buffer[] = [];\n return new Promise((resolve, reject) => {\n stream.on(\"data\", (chunk) => chunks.push(Buffer.from(chunk)));\n stream.on(\"error\", (err) => reject(err));\n stream.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\n });\n}\n\nasync function replyWithPage(\n reply: FastifyReply<RawServerBase>,\n pageContext: Awaited<\n ReturnType<\n typeof renderPage<\n { redirectTo?: string; isClientSideNavigation?: boolean },\n { urlOriginal: string }\n >\n >\n >\n): Promise<FastifyReply> {\n const { httpResponse } = pageContext;\n\n if (pageContext.redirectTo && !pageContext.isClientSideNavigation) {\n return reply.redirect(307, pageContext.redirectTo);\n }\n\n if (!httpResponse) {\n return reply.code(404).type(\"text/html\").send(\"Not Found\");\n }\n\n const { body, statusCode, headers } = httpResponse;\n return reply\n .status(statusCode)\n .headers(Object.fromEntries(headers))\n .send(body);\n}\n\nconst proxyPageId = \"/proxy/pages\";\n\ninterface ViteProxyPluginOptions {\n upstream: URL;\n host: URL;\n buildPageContextInit?: (\n req: FastifyRequest\n ) => Promise<AugmentMe.PageContextInit>;\n getLayout: (reply: FastifyReply<RawServerBase>) => {\n layout: string;\n layoutProps: AugmentMe.LayoutProps;\n };\n /// Use to signal to legacy backend to return special results (eg. remove navbar etc)\n rewriteRequestHeaders?: (\n req: Http2ServerRequest | IncomingMessage,\n headers: Http2IncomingHttpHeaders | IncomingHttpHeaders\n ) => Http2IncomingHttpHeaders | IncomingHttpHeaders;\n}\n/**\n * Fastify plugin that wraps @fasitfy/http-proxy to proxy Rails/Turbolinks server into a Vite-Plugin-SSR site.\n */\nexport const viteProxyPlugin: FastifyPluginAsync<\n ViteProxyPluginOptions\n> = async (\n fastify,\n { upstream, host, buildPageContextInit, rewriteRequestHeaders, getLayout }\n) => {\n await fastify.register(accepts);\n await fastify.register(proxy, {\n upstream: upstream.href,\n async preHandler(req, reply) {\n if (req.method === \"GET\" && req.accepts().type([\"html\"]) === \"html\") {\n const pageContextInit = {\n urlOriginal: req.url,\n ...(buildPageContextInit ? await buildPageContextInit(req) : {}),\n };\n\n const pageContext = await renderPage<\n { _pageId: string },\n typeof pageContextInit\n >(pageContextInit);\n\n const proxy = pageContext._pageId === proxyPageId;\n const noRouteMatched =\n (pageContext as any).is404 && !pageContext.errorWhileRendering; // we hit no page, but NOT because of an error\n\n if (noRouteMatched) {\n req.log.info(\"bifrost: no route match, naked proxy to backend\");\n // Naked proxy\n return;\n } else if (!proxy) {\n req.log.info(`bifrost: rendering page ${pageContext._pageId}`);\n return replyWithPage(reply, pageContext);\n } else {\n req.log.info(`bifrost: proxy route matched, proxying to backend`);\n // pageContext.json is added on client navigations to indicate we are returning just json for the client router\n // we have to remove it before proxying though.\n (req as RequestExtendedWithProxy)._proxy = {\n isPageContext: req.raw.url!.includes(\"/index.pageContext.json\"),\n originalUrl: req.raw.url,\n };\n (req.raw as any)._proxy = true;\n req.raw.url = req.raw.url!.replace(\"/index.pageContext.json\", \"\");\n }\n }\n },\n replyOptions: {\n rewriteRequestHeaders(request, headers) {\n const fwd = forwarded(request as IncomingMessage).reverse();\n // fwd.push(request.ip); TODO: not sure if this is needed\n headers[\"X-Forwarded-For\"] = fwd.join(\", \");\n headers[\"X-Forwarded-Host\"] = host.host;\n headers[\"X-Forwarded-Protocol\"] = host.protocol;\n\n if ((request as any)._proxy) {\n // Proxying and wrapping\n\n // Delete cache headers\n delete headers[\"if-modified-since\"];\n delete headers[\"if-none-match\"];\n delete headers[\"if-unmodified-since\"];\n delete headers[\"if-none-match\"];\n delete headers[\"if-range\"];\n if (rewriteRequestHeaders) {\n return rewriteRequestHeaders(request, headers);\n }\n }\n return headers;\n },\n async onResponse(req, reply: FastifyReply<RawServerBase>, res) {\n const { isPageContext = false, originalUrl = undefined } =\n (req as RequestExtendedWithProxy)._proxy || {};\n if (isPageContext && originalUrl) {\n // restore url rewrite\n req.raw.url = originalUrl;\n }\n\n if ([301, 302, 303, 307, 308].includes(reply.statusCode)) {\n const location = reply.getHeader(\"location\") as string;\n if (location) {\n const url = new URL(location);\n if (url.host === upstream.host) {\n // rewrite redirect on upstream's host to the proxy host\n url.host = host.host;\n }\n reply.header(\"location\", url);\n if (isPageContext) {\n return reply\n .status(200)\n .type(\"application/json\")\n .send(\n JSON.stringify({\n _pageId: proxyPageId,\n redirectTo: url,\n })\n );\n } else {\n return reply.send(res);\n }\n }\n }\n\n const { layout, layoutProps } = getLayout(reply);\n if (!layout) {\n return reply.send(res);\n }\n\n const html = await streamToString(res);\n\n const pageContextInit = {\n urlOriginal: req.url,\n // Nest into fromProxy to avoid triggering pageContextInitHasClientData which forces restorationVisit to refetch pageContext\n // Ideally we would just set restorationVisit onBeforeRender to no-op\n // https://github.com/brillout/vite-plugin-ssr/discussions/1075#discussioncomment-6758711\n fromProxy: {\n layout,\n layoutProps,\n html,\n },\n };\n const pageContext = await renderPage(pageContextInit);\n return replyWithPage(reply, pageContext);\n },\n },\n });\n};\n"],"mappings":"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","names":["proxy"]}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["// Note that this file isn't processed by Vite, see https://github.com/brillout/vite-plugin-ssr/issues/562\nimport { FastifyReply, RawServerBase, FastifyPluginAsync } from \"fastify\";\nimport { FastifyRequest, RequestGenericInterface } from \"fastify/types/request\";\nimport proxy from \"@fastify/http-proxy\";\nimport accepts from \"@fastify/accepts\";\nimport forwarded from \"@fastify/forwarded\";\nimport { Writable } from \"stream\";\nimport { IncomingHttpHeaders, IncomingMessage } from \"http\";\nimport {\n Http2ServerRequest,\n IncomingHttpHeaders as Http2IncomingHttpHeaders,\n} from \"http2\";\nimport { renderPage } from \"vite-plugin-ssr/server\";\nimport { AugmentMe } from \"@alignable/bifrost\";\n\ntype RenderedPageContext = Awaited<\n ReturnType<\n typeof renderPage<\n {\n redirectTo?: string;\n isClientSideNavigation?: boolean;\n _pageId?: string;\n },\n { urlOriginal: string }\n >\n >\n>;\n\ntype RequestExtendedWithProxy = FastifyRequest<\n RequestGenericInterface,\n RawServerBase\n> & { _proxy?: { isPageContext: boolean; originalUrl?: string } };\n\nfunction streamToString(stream: Writable): Promise<string> {\n const chunks: Buffer[] = [];\n return new Promise((resolve, reject) => {\n stream.on(\"data\", (chunk) => chunks.push(Buffer.from(chunk)));\n stream.on(\"error\", (err) => reject(err));\n stream.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf8\")));\n });\n}\n\nconst proxyPageId = \"/proxy/pages\";\n\ninterface ViteProxyPluginOptions {\n upstream: URL;\n host: URL;\n onError?: (error: any, pageContext: RenderedPageContext) => void;\n buildPageContextInit?: (\n req: FastifyRequest\n ) => Promise<AugmentMe.PageContextInit>;\n getLayout: (reply: FastifyReply<RawServerBase>) => {\n layout: string;\n layoutProps: AugmentMe.LayoutProps;\n };\n /// Use to signal to legacy backend to return special results (eg. remove navbar etc)\n rewriteRequestHeaders?: (\n req: Http2ServerRequest | IncomingMessage,\n headers: Http2IncomingHttpHeaders | IncomingHttpHeaders\n ) => Http2IncomingHttpHeaders | IncomingHttpHeaders;\n}\n/**\n * Fastify plugin that wraps @fasitfy/http-proxy to proxy Rails/Turbolinks server into a Vite-Plugin-SSR site.\n */\nexport const viteProxyPlugin: FastifyPluginAsync<\n ViteProxyPluginOptions\n> = async (\n fastify,\n {\n upstream,\n host,\n onError,\n buildPageContextInit,\n rewriteRequestHeaders,\n getLayout,\n }\n) => {\n async function replyWithPage(\n reply: FastifyReply<RawServerBase>,\n pageContext: RenderedPageContext\n ): Promise<FastifyReply> {\n const { httpResponse } = pageContext;\n\n if (\n onError &&\n httpResponse?.statusCode === 500 &&\n pageContext.errorWhileRendering\n ) {\n onError(pageContext.errorWhileRendering, pageContext);\n }\n\n if (pageContext.redirectTo && !pageContext.isClientSideNavigation) {\n return reply.redirect(307, pageContext.redirectTo);\n }\n\n if (!httpResponse) {\n return reply.code(404).type(\"text/html\").send(\"Not Found\");\n }\n\n const { body, statusCode, headers } = httpResponse;\n return reply\n .status(statusCode)\n .headers(Object.fromEntries(headers))\n .send(body);\n }\n await fastify.register(accepts);\n await fastify.register(proxy, {\n upstream: upstream.href,\n async preHandler(req, reply) {\n if (req.method === \"GET\" && req.accepts().type([\"html\"]) === \"html\") {\n const pageContextInit = {\n urlOriginal: req.url,\n ...(buildPageContextInit ? await buildPageContextInit(req) : {}),\n };\n\n const pageContext = await renderPage<\n { _pageId: string },\n typeof pageContextInit\n >(pageContextInit);\n\n const proxy = pageContext._pageId === proxyPageId;\n const noRouteMatched =\n (pageContext as any).is404 && !pageContext.errorWhileRendering; // we hit no page, but NOT because of an error\n\n if (noRouteMatched) {\n req.log.info(\"bifrost: no route match, naked proxy to backend\");\n // Naked proxy\n return;\n } else if (!proxy) {\n req.log.info(`bifrost: rendering page ${pageContext._pageId}`);\n return replyWithPage(reply, pageContext);\n } else {\n req.log.info(`bifrost: proxy route matched, proxying to backend`);\n // pageContext.json is added on client navigations to indicate we are returning just json for the client router\n // we have to remove it before proxying though.\n const isPageContext = req.raw.url!.includes(\n \"/index.pageContext.json\"\n );\n (req as RequestExtendedWithProxy)._proxy = {\n isPageContext,\n originalUrl: req.raw.url,\n };\n (req.raw as any)._proxy = true;\n if (isPageContext) {\n // page context expects json - we need html from legacy server\n req.raw.headers[\"accept\"] = \"text/html\";\n req.raw.url = req.raw.url!.replace(\"/index.pageContext.json\", \"\");\n }\n }\n }\n },\n replyOptions: {\n rewriteRequestHeaders(request, headers) {\n const fwd = forwarded(request as IncomingMessage).reverse();\n // fwd.push(request.ip); TODO: not sure if this is needed\n headers[\"X-Forwarded-For\"] = fwd.join(\", \");\n headers[\"X-Forwarded-Host\"] = host.host;\n headers[\"X-Forwarded-Protocol\"] = host.protocol;\n\n if ((request as any)._proxy) {\n // Proxying and wrapping\n\n // Delete cache headers\n delete headers[\"if-modified-since\"];\n delete headers[\"if-none-match\"];\n delete headers[\"if-unmodified-since\"];\n delete headers[\"if-none-match\"];\n delete headers[\"if-range\"];\n if (rewriteRequestHeaders) {\n return rewriteRequestHeaders(request, headers);\n }\n }\n return headers;\n },\n async onResponse(req, reply: FastifyReply<RawServerBase>, res) {\n const { isPageContext = false, originalUrl = undefined } =\n (req as RequestExtendedWithProxy)._proxy || {};\n if (isPageContext && originalUrl) {\n // restore url rewrite\n req.raw.url = originalUrl;\n }\n\n if ([301, 302, 303, 307, 308].includes(reply.statusCode)) {\n const location = reply.getHeader(\"location\") as string;\n if (location) {\n const url = new URL(location);\n if (url.host === upstream.host) {\n // rewrite redirect on upstream's host to the proxy host\n url.host = host.host;\n }\n reply.header(\"location\", url);\n if (isPageContext) {\n return reply\n .status(200)\n .type(\"application/json\")\n .send(\n JSON.stringify({\n _pageId: proxyPageId,\n redirectTo: url,\n })\n );\n } else {\n return reply.send(res);\n }\n }\n }\n\n const { layout, layoutProps } = getLayout(reply);\n if (!isPageContext && !layout) {\n return reply.send(res);\n }\n\n const html = await streamToString(res);\n\n const pageContextInit = {\n urlOriginal: req.url,\n fromProxy: {\n layout,\n layoutProps,\n html,\n },\n };\n const pageContext = await renderPage(pageContextInit);\n return replyWithPage(reply, pageContext);\n },\n },\n });\n};\n"],"mappings":"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","names":["proxy"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@alignable/bifrost-fastify",
3
3
  "repository": "https://github.com/Alignable/bifrost.git",
4
- "version": "0.0.23",
4
+ "version": "0.0.25",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -18,9 +18,9 @@
18
18
  "vite": "^4.0.3"
19
19
  },
20
20
  "peerDependencies": {
21
- "@alignable/bifrost": "0.0.23",
21
+ "@alignable/bifrost": "0.0.25",
22
22
  "fastify": "^4.9.2",
23
- "vite-plugin-ssr": "0.4.135"
23
+ "vite-plugin-ssr": "0.4.138"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/connect": "^3.4.35",