Skip to content

Instantly share code, notes, and snippets.

@robksawyer
Last active June 2, 2024 06:07
Show Gist options
  • Select an option

  • Save robksawyer/c082fc6e73cc20431431f57e49f28741 to your computer and use it in GitHub Desktop.

Select an option

Save robksawyer/c082fc6e73cc20431431f57e49f28741 to your computer and use it in GitHub Desktop.
Shopify's authentication and utility libraries are designed to work with native Node.js IncomingMessage and ServerResponse objects. Since Next.js uses its own request and response objects, these conversions are necessary to bridge the gap. By implementing these conversion functions, you can ensure that your Next.js application seamlessly integra…
import { IncomingMessage } from "http";
import { NextRequest } from "next/server";
import { Socket } from "net";
export async function convertNextRequestToIncomingMessage(
request: NextRequest
): Promise<IncomingMessage> {
if (!request || typeof request !== "object") {
throw new Error("Invalid request object");
}
const incomingMessage = new IncomingMessage(new Socket());
try {
incomingMessage.headers = Object.fromEntries(request.headers.entries());
incomingMessage.method = request.method;
incomingMessage.url = request.url;
const bodyChunks: Uint8Array[] = [];
if (request.body) {
const reader = request.body.getReader();
let result = await reader.read();
while (!result.done) {
bodyChunks.push(result.value);
result = await reader.read();
}
}
const bodyBuffer = Buffer.concat(bodyChunks);
if (bodyBuffer.length > 0) {
incomingMessage.push(bodyBuffer);
}
incomingMessage.push(null);
// Mimic NextApiRequest properties
(incomingMessage as any).query = Object.fromEntries(
new URL(request.url).searchParams.entries()
);
(incomingMessage as any).cookies = Object.fromEntries(
request.headers
.get("cookie")
?.split("; ")
.map((cookie) => cookie.split("=")) || []
);
(incomingMessage as any).body =
bodyBuffer.length > 0 ? JSON.parse(bodyBuffer.toString()) : null;
} catch (error) {
console.error("Error converting NextRequest to IncomingMessage:", error);
throw error;
}
return incomingMessage;
}
import { ServerResponse } from "http";
import { NextResponse } from "next/server";
export function convertNextResponseToServerResponse(
nextResponse: NextResponse
): ServerResponse {
if (!nextResponse || typeof nextResponse !== "object") {
throw new Error("Invalid nextResponse object");
}
const serverResponse = new ServerResponse({} as any);
try {
serverResponse.statusCode = nextResponse.status;
serverResponse.statusMessage = nextResponse.statusText;
for (const [key, value] of nextResponse.headers.entries()) {
serverResponse.setHeader(key, value);
}
// Implement write method
serverResponse.write = (
chunk: any,
encodingOrCallback?: any,
callback?: any
): boolean => {
if (typeof encodingOrCallback === "function") {
encodingOrCallback(null);
} else if (typeof callback === "function") {
callback(null);
}
return true; // Ensure boolean is returned
};
// Implement end method
serverResponse.end = (
chunk: any,
encodingOrCallback?: any,
callback?: any
): ServerResponse => {
if (typeof encodingOrCallback === "function") {
encodingOrCallback(null);
} else if (typeof callback === "function") {
callback(null);
}
return serverResponse; // Ensure ServerResponse is returned
};
} catch (error) {
console.error("Error converting NextResponse to ServerResponse:", error);
throw error;
}
return serverResponse;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment