Skip to content
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

bugfix: socket + post with data #35

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
22 changes: 15 additions & 7 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,23 @@ function vitePlugin(options) {
async configureServer(server) {
const nextSymbol = Symbol('next');

/** @type {import('fastify').FastifyInstance} */
let fastify;

/** @type {import('fastify').FastifyServerFactory} */
const serverFactory = (handler, opts) => {
server.middlewares.use((req, res, next) => {
req[nextSymbol] = next;
handler(req, res);
if (fastify.hasRoute({ method: req.method, url: req.url })) {
req[nextSymbol] = next;
handler(req, res);
} else {
next();
}
});
return /** @type {import('http').Server} */(server.httpServer ?? new http.Server());
}

const fastify = Fastify({
fastify = Fastify({
logger: options?.logger ?? true,
serverFactory
});
Expand All @@ -63,16 +70,17 @@ function vitePlugin(options) {
}
setupRoutes(fastify);
}

// Final catch-all route forwards back to the Vite server
fastify.all('/*', function (request) {

// The vite socket can get to here...
// Relevant also when registered @fastify/websocket
fastify.get("/", function (request) {
/** @type {import('connect').NextFunction} */
const next = request.raw[nextSymbol];
if (typeof next === "function") {
next();
}
});

await fastify.ready();
},
transform(code, id) {
Expand Down
63 changes: 61 additions & 2 deletions lib/server.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IncomingMessage } from "node:http";
import { NodeApp } from "astro/app/node";
import Fastify from "fastify";
import fastifyStatic from "@fastify/static";
Expand Down Expand Up @@ -58,9 +59,13 @@ export function start(manifest, options) {
* @param {import('fastify').FastifyReply} reply
*/
const rootHandler = async (request, reply) => {
const routeData = app.match(request.raw, { matchNotFound: true });
let rawRequest = request.raw;
if (IncomingMessage.isDisturbed(rawRequest)) {
rawRequest = revertToRequest(request);
}
const routeData = app.match(rawRequest, { matchNotFound: true });
if (routeData) {
const response = await app.render(request.raw, { routeData });
const response = await app.render(rawRequest, { routeData });

await writeWebResponse(app, reply.raw, response);
} else {
Expand Down Expand Up @@ -151,6 +156,60 @@ async function writeWebResponse(app, res, webResponse) {
res.end();
}

/**
* @param {import('fastify').FastifyRequest} request
*/
function revertToRequest(request) {
const url = createURL(request);
const newRequest = new Request(url, {
method: request.method,
headers: request.headers,
body: getBody(request),
});
return newRequest;
}

/**
* @param {import('fastify').FastifyRequest} request
*/
function getBody(request) {
const contentType = request.headers["content-type"];
switch (contentType) {
case "application/x-www-form-urlencoded": {
return Object.keys(request.body).reduce((urlEncode, key) => {
urlEncode.append(key, request.body[key]);
return urlEncode;
}, new URLSearchParams());
}
default:
return request.body;
}
}

/**
* @param {import('fastify').FastifyRequest} request
*/
function createURL(request) {
const url = new URL(
`${request.url}`,
`${request.protocol}://${request.hostname}`,
);
if (typeof query === "string") {
url.search = query;
} else if (typeof query === "object") {
Object.entries(query).forEach(([key, val]) => {
if (typeof val === "string") {
url.searchParams.append(key, val);
} else {
val.forEach((innerVal) => {
url.searchParams.append(key, innerVal);
});
}
});
}
return url;
}

export function createExports(manifest, options) {
return {
start() {
Expand Down
35 changes: 34 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.