Skip to content

Commit b96093c

Browse files
committed
feat: 밈 미들웨어 추가 및 메타 태그 동적 수정
- 새로운 미들웨어를 추가하여 밈 ID에 따라 API에서 데이터를 가져오고, HTML의 OG 및 Twitter 메타 태그를 동적으로 수정 - package.json에 '@vercel/og' 및 '@types/node' 패키지 추가 - pnpm-lock.yaml에서 '@types/node' 버전 업데이트 및 '@vercel/edge' 패키지 추가 - vercel.json에서 리다이렉트 규칙 수정
1 parent 8c489e8 commit b96093c

File tree

4 files changed

+104
-19
lines changed

4 files changed

+104
-19
lines changed

apps/web/middleware.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
export const config = {
2+
matcher: '/meme/:path*',
3+
};
4+
5+
export default async function middleware(request: Request) {
6+
const url = new URL(request.url);
7+
const memeId = url.pathname.split('/').pop();
8+
9+
try {
10+
// API에서 밈 데이터를 가져옵니다
11+
const response = await fetch(
12+
`https://api.meme-wiki.net/api/memes/${memeId}`,
13+
{
14+
headers: {
15+
Accept: 'application/json',
16+
},
17+
},
18+
);
19+
20+
if (!response.ok) {
21+
return Response.redirect(url.origin, 302);
22+
}
23+
24+
const data = await response.json();
25+
26+
// 원본 HTML을 가져옵니다
27+
const res = await fetch(new URL('/', request.url));
28+
const html = await res.text();
29+
30+
// OG 태그를 동적으로 교체합니다
31+
const modifiedHtml = html
32+
.replace(
33+
/<meta\s+property="og:title"\s+content="[^"]*"[^>]*>/,
34+
`<meta property="og:title" content="${data.success.title} - Meme Wiki" />`,
35+
)
36+
.replace(
37+
/<meta\s+property="og:description"\s+content="[^"]*"[^>]*>/,
38+
`<meta property="og:description" content="${data.success.usageContext}" />`,
39+
)
40+
.replace(
41+
/<meta\s+property="og:image"\s+content="[^"]*"[^>]*>/,
42+
`<meta property="og:image" content="${data.success.imgUrl}" />`,
43+
)
44+
.replace(
45+
/<meta\s+property="og:url"\s+content="[^"]*"[^>]*>/,
46+
`<meta property="og:url" content="https://meme-wiki.net/meme/${memeId}" />`,
47+
)
48+
.replace(
49+
/<meta\s+property="twitter:title"\s+content="[^"]*"[^>]*>/,
50+
`<meta property="twitter:title" content="${data.success.title} - Meme Wiki" />`,
51+
)
52+
.replace(
53+
/<meta\s+property="twitter:description"\s+content="[^"]*"[^>]*>/,
54+
`<meta property="twitter:description" content="${data.success.usageContext}" />`,
55+
)
56+
.replace(
57+
/<meta\s+property="twitter:image"\s+content="[^"]*"[^>]*>/,
58+
`<meta property="twitter:image" content="${data.success.imgUrl}" />`,
59+
);
60+
61+
return new Response(modifiedHtml, {
62+
headers: {
63+
'content-type': 'text/html;charset=UTF-8',
64+
'x-middleware-cache': 'no-cache',
65+
'cache-control': 'no-cache, no-store, must-revalidate',
66+
pragma: 'no-cache',
67+
expires: '0',
68+
},
69+
});
70+
} catch (error) {
71+
// 에러 발생 시 기본 페이지로 리다이렉트
72+
return Response.redirect(url.origin, 302);
73+
}
74+
}

apps/web/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
"@types/react": "^18.2.0",
3232
"@types/react-dom": "^18.2.0",
3333
"@vitejs/plugin-react": "^3.1.0",
34+
"@vercel/og": "^0.6.2",
35+
"@types/node": "^20.0.0",
3436
"eslint": "^8.57.0",
3537
"typescript": "5.5.4",
3638
"vite": "^5.1.4",

apps/web/vercel.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"rewrites": [
33
{
4-
"source": "/(.*)",
4+
"source": "/((?!api/.*).*)",
55
"destination": "/index.html"
66
}
77
]

pnpm-lock.yaml

Lines changed: 27 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)