Last active
November 4, 2022 22:37
-
-
Save cramforce/12e58aea2920ae80159f42be451e8027 to your computer and use it in GitHub Desktop.
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
import { NextResponse } from "next/server"; | |
import type { NextRequest } from "next/server"; | |
const SCRIPT_TAG = '<script async src="/feedback-bootstrap.js"></script>'; | |
export async function middleware(request: NextRequest) { | |
// Skip requests not looking for html. | |
const accept = request.headers.get("accept") || ""; | |
if (!accept) { | |
console.log("Request headers", request.headers); | |
} | |
if (!accept || !accept.startsWith("text/html")) { | |
return NextResponse.next(); | |
} | |
const middlewareResponse = NextResponse.next(); | |
// Skip redirects, etc. | |
if (middlewareResponse.status > 200) { | |
return middlewareResponse; | |
} | |
// We want to change the response, and that means we have to fetch it ourselves. | |
const originResponse = await fetch(request); | |
// Response doesn't look like HTML, skip! | |
const contentType = originResponse.headers.get("content-type"); | |
if (!contentType) { | |
console.log("Origin response headers", originResponse.headers); | |
} | |
if (!contentType || !contentType.startsWith("text/html")) { | |
return originResponse; | |
} | |
let rewritten; | |
if (originResponse.body.getReader) { | |
console.log("Using the streaming API"); | |
const reader = originResponse.body.getReader(); | |
rewritten = new ReadableStream({ | |
start(controller) { | |
function push() { | |
return reader.read().then(({ done, value }) => { | |
if (done) { | |
// Append the script tag. | |
controller.enqueue(new TextEncoder().encode(SCRIPT_TAG)); | |
controller.close(); | |
return; | |
} | |
controller.enqueue(value); | |
push(); | |
}); | |
} | |
push(); | |
}, | |
}); | |
} else { | |
// It appears that originResponse.body.getReader is null and so we cannot stream the | |
// addition. | |
const text = await originResponse.text(); | |
// Dumping it to the end is simple and works. | |
rewritten = text + SCRIPT_TAG; | |
} | |
return new Response(rewritten, { | |
headers: new Headers(originResponse.headers), | |
status: originResponse.status, | |
statusText: originResponse.statusText, | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
But
NextResponse.next()
doesn't actually run anything else. It's just a static object (so that check will always be false):It's used to check the response at the end of the middleware call to know what to do next. I think it's mostly meant to be used if you want to let the request fall through, but attach some extra headers.
Yeah, it's a middleware issue, we have a workaround
cleanResponseBody
method in Live to get the correct ReadableStream (currently it returns a Node.js stream)--
The rest looks good. Only worry here is if the user has an existing top-level middleware, I don't know how this will play out (how do we merge them)
This is pretty much exactly the way I implemented it locally as well, only difference was the streaming