Kaynağa Gözat

fix: 修复新闻图片中包含 localhost 时 Next.js 生产环境拦截导致图片加载失败(400)的问题

nahida 1 ay önce
ebeveyn
işleme
c6950f005e

+ 2 - 2
.env.production

@@ -1,5 +1,5 @@
-NEXT_PUBLIC_API_BASE=http://47.107.107.47:8040
-NEXT_PUBLIC_BASE_URL=http://47.107.107.47:8040
+NEXT_PUBLIC_API_BASE=http://localhost:8040
+NEXT_PUBLIC_BASE_URL=http://localhost:8040
 NEXT_PUBLIC_REMOTE_BASE_URL=http://47.107.107.47:8040
 NEXT_PUBLIC_BASE_WS_URL = 'ws://47.107.107.47:8081/ws'
 NEXT_PUBLIC_CLIENT_URL=http://47.107.107.47:8040

+ 8 - 0
src/app/layout.tsx

@@ -11,6 +11,14 @@ export const metadata: Metadata = {
     description: "中科盛阳信息技术有限公司官网",
     icons: {
         icon: '/favicon.ico'
+    },
+    verification: {
+        other:{
+            'baidu-site-verification':'codeva-DTglvfgi4u',
+            '360-site-verification':'43c1e7a15c236d09d09d671a44703338',
+            'sogou_site_verification':'TUZViBCvJs',
+            'msvalidate.01':'0327E84E98BAE20AB7172C5B9DE4AC1E'
+        }
     }
 };
 

+ 19 - 2
src/app/news/page.tsx

@@ -47,7 +47,24 @@ export default async function NewsPage({
   searchParams: Promise<{ page?: string }>
 }) {
 
-  const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
+  const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || '';
+  const REMOTE_BASE_URL = process.env.NEXT_PUBLIC_REMOTE_BASE_URL || 'http://47.107.107.47:8040';
+  
+  // 处理特别新闻图片 URL
+  let specialNewsUrl = specialNews?.newsUrl || '';
+  if (specialNewsUrl) {
+    if (specialNewsUrl.startsWith('http')) {
+      if (specialNewsUrl.includes('localhost')) {
+        try {
+          const urlObj = new URL(specialNewsUrl);
+          specialNewsUrl = `${REMOTE_BASE_URL}${urlObj.pathname}${urlObj.search}`;
+        } catch (e) {}
+      }
+    } else {
+      specialNewsUrl = `${REMOTE_BASE_URL.replace(/\/$/, '')}/${specialNewsUrl.replace(/^\//, '')}`;
+    }
+  }
+
   // 等待 searchParams 解析
   const params = await searchParams
   const pageNum = Number.parseInt(params.page || "1", 10)
@@ -79,7 +96,7 @@ export default async function NewsPage({
       {/*                /!* 模拟图片色块 *!/*/}
       {/*                <div*/}
       {/*                    className="w-full sm:w-1/3 bg-gray-300 rounded-lg sm:h-auto flex items-center justify-center">*/}
-      {/*                    <Image src={specialNews?.newsUrl ? BASE_URL + specialNews?.newsUrl : ""}*/}
+      {/*                    <Image src={specialNewsUrl}*/}
       {/*                           alt={"特别新闻图片"}*/}
       {/*                           width={300} height={300}/>*/}
       {/*                </div>*/}

+ 20 - 3
src/components/news/NewsList.tsx

@@ -37,9 +37,26 @@ const CATEGORY_MAP = Object.freeze({
 const NewsItem: React.FC<NewsItemProps> = ({news: article}) => {
   // 环境变量默认值兜底,避免undefined
   const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL || '';
-
-  // 图片地址处理抽离,提升可读性
-  const coverImageUrl = article.newsUrl ? `${BASE_URL}${article.newsUrl}` : '';
+  const REMOTE_BASE_URL = process.env.NEXT_PUBLIC_REMOTE_BASE_URL || 'http://47.107.107.47:8040';
+
+  // 图片地址处理抽离,提升可读性,并且修复可能出现的本地绝对路径和重复拼接问题
+  let coverImageUrl = article.newsUrl || '';
+  if (coverImageUrl) {
+    if (coverImageUrl.startsWith('http')) {
+      // 如果后端返回了包含 localhost 的绝对路径,替换为实际的外网 IP,因为 Next.js 生产环境默认拦截 localhost 图片防止 SSRF
+      if (coverImageUrl.includes('localhost')) {
+        try {
+          const urlObj = new URL(coverImageUrl);
+          coverImageUrl = `${REMOTE_BASE_URL}${urlObj.pathname}${urlObj.search}`;
+        } catch (e) {
+          // 容错处理
+        }
+      }
+    } else {
+      // 相对路径,使用 REMOTE_BASE_URL 确保能够在外网访问
+      coverImageUrl = `${REMOTE_BASE_URL.replace(/\/$/, '')}/${coverImageUrl.replace(/^\//, '')}`;
+    }
+  }
 
   return (
       <Link