Skip to content

Commit e087179

Browse files
authored
fix: stream repo images directly to support files over 1MB (#43)
1 parent 143dd80 commit e087179

1 file changed

Lines changed: 22 additions & 15 deletions

File tree

  • apps/web/src/app/api/github-image

apps/web/src/app/api/github-image/route.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NextRequest, NextResponse } from "next/server";
2-
import { getOctokit } from "@/lib/github";
2+
import { getGitHubToken } from "@/lib/github";
33

44
const MIME_TYPES: Record<string, string> = {
55
png: "image/png",
@@ -18,37 +18,44 @@ export async function GET(request: NextRequest) {
1818
const owner = searchParams.get("owner");
1919
const repo = searchParams.get("repo");
2020
const path = searchParams.get("path");
21-
const ref = searchParams.get("ref") || undefined;
21+
const ref = searchParams.get("ref");
2222

23-
if (!owner || !repo || !path) {
23+
if (!owner || !repo || !path || !ref) {
2424
return NextResponse.json(
25-
{ error: "Missing required parameters: owner, repo, path" },
25+
{ error: "Missing required parameters: owner, repo, path, ref" },
2626
{ status: 400 },
2727
);
2828
}
2929

30-
const octokit = await getOctokit();
31-
if (!octokit) {
30+
const token = await getGitHubToken();
31+
if (!token) {
3232
return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
3333
}
3434

3535
try {
36-
const { data } = await octokit.repos.getContent({
37-
owner,
38-
repo,
39-
path,
40-
...(ref ? { ref } : {}),
36+
/**
37+
* Bypass Octokit:
38+
* base64 content only for ≤1MB, raw format corrupts binary
39+
* @see https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#get-repository-content
40+
* */
41+
const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/${path}`;
42+
const upstream = await fetch(rawUrl, {
43+
headers: {
44+
Authorization: `Bearer ${token}`,
45+
},
4146
});
4247

43-
if (Array.isArray(data) || !("content" in data) || !data.content) {
48+
if (!upstream.ok) {
4449
return NextResponse.json({ error: "Image not found" }, { status: 404 });
4550
}
4651

47-
const buffer = Buffer.from(data.content, "base64");
4852
const ext = path.split(".").pop()?.toLowerCase() || "";
49-
const contentType = MIME_TYPES[ext] || "application/octet-stream";
53+
const contentType =
54+
MIME_TYPES[ext] ||
55+
upstream.headers.get("content-type") ||
56+
"application/octet-stream";
5057

51-
return new NextResponse(buffer, {
58+
return new NextResponse(upstream.body, {
5259
headers: {
5360
"Content-Type": contentType,
5461
"Cache-Control":

0 commit comments

Comments
 (0)