api替换

This commit is contained in:
谢宇宁
2026-11-07 11:14:16 +07:00
parent 0676511eee
commit 38e7edc756
171 changed files with 75869 additions and 1586 deletions
+2 -2
View File
@@ -7,7 +7,7 @@
# 本地代理调试(推荐):BASE 留空 + 设置代理目标
NEXT_PUBLIC_API_BASE_URL=
API_PROXY_TARGET=https://sgdj-h5.80sygtm.com
API_PROXY_TARGET=https://webhgbapi.mfcg.me
# HTTPS_PROXY=http://127.0.0.1:7890
# HTTP_PROXY=http://127.0.0.1:7890
@@ -15,6 +15,6 @@ API_PROXY_TARGET=https://sgdj-h5.80sygtm.com
NEXT_PUBLIC_TRACKER_APP_ID=JHA-1049
NEXT_PUBLIC_GTAG_ID=
# 站点正式域名(sitemap / OG / canonical 强制用此值,勿填反代内部域)
# NEXT_PUBLIC_SITE_URL=https://shuguodj.com
# NEXT_PUBLIC_SITE_URL=https://huangguoduanju.im
# NEXT_PUBLIC_TRACKER_ENCRYPTED_CONFIG=
# NEXT_PUBLIC_YANDEX_METRIKA_ID=
+19 -4
View File
@@ -41,6 +41,21 @@
"static/chunks/turbopack-_1aaoqtn6vriom._.js",
"static/chunks/_219uq1sj0q91c._.js"
],
"/drama/[id]/page": [
"static/chunks/[turbopack]_browser_dev_hmr-client_hmr-client_ts_13pqcwtuzrbk0._.js",
"static/chunks/node_modules_next_dist_compiled_next-devtools_index_090k2jmam7qwg.js",
"static/chunks/1daa_next_dist_compiled_react-dom_cjs_react-dom-client_development_0mp0cp_t-ezj9.js",
"static/chunks/1q96_modules_next_dist_compiled_react-dom_cjs_react-dom_development_1sqry0_53krp4.js",
"static/chunks/node_modules_next_dist_compiled_react-dom_0grqycjrj6mju._.js",
"static/chunks/node_modules_next_dist_compiled_react-server-dom-turbopack_164kp-67asdr9._.js",
"static/chunks/node_modules_next_dist_compiled_1amofcmz--cdp._.js",
"static/chunks/node_modules_next_dist_client_14zvornz047l2._.js",
"static/chunks/node_modules_next_dist_1bjkg68unqmjx._.js",
"static/chunks/node_modules_@swc_helpers_cjs_0oghen6kqggry._.js",
"static/chunks/_1anvha4rlo79g._.js",
"static/chunks/turbopack-_1aaoqtn6vriom._.js",
"static/chunks/_0pmqou_4mtbjb._.js"
],
"/play/[id]/[episode]/page": [
"static/chunks/[turbopack]_browser_dev_hmr-client_hmr-client_ts_13pqcwtuzrbk0._.js",
"static/chunks/node_modules_next_dist_compiled_next-devtools_index_090k2jmam7qwg.js",
@@ -56,7 +71,7 @@
"static/chunks/turbopack-_1aaoqtn6vriom._.js",
"static/chunks/_0slr_qtlqsjni._.js"
],
"/nav/page": [
"/search/[[...parts]]/page": [
"static/chunks/[turbopack]_browser_dev_hmr-client_hmr-client_ts_13pqcwtuzrbk0._.js",
"static/chunks/node_modules_next_dist_compiled_next-devtools_index_090k2jmam7qwg.js",
"static/chunks/1daa_next_dist_compiled_react-dom_cjs_react-dom-client_development_0mp0cp_t-ezj9.js",
@@ -69,9 +84,9 @@
"static/chunks/node_modules_@swc_helpers_cjs_0oghen6kqggry._.js",
"static/chunks/_1anvha4rlo79g._.js",
"static/chunks/turbopack-_1aaoqtn6vriom._.js",
"static/chunks/_0w2jlohhfhuy8._.js"
"static/chunks/_0byvfhmmc25t4._.js"
],
"/_not-found/page": [
"/home-road/page": [
"static/chunks/[turbopack]_browser_dev_hmr-client_hmr-client_ts_13pqcwtuzrbk0._.js",
"static/chunks/node_modules_next_dist_compiled_next-devtools_index_090k2jmam7qwg.js",
"static/chunks/1daa_next_dist_compiled_react-dom_cjs_react-dom-client_development_0mp0cp_t-ezj9.js",
@@ -84,7 +99,7 @@
"static/chunks/node_modules_@swc_helpers_cjs_0oghen6kqggry._.js",
"static/chunks/_1anvha4rlo79g._.js",
"static/chunks/turbopack-_1aaoqtn6vriom._.js",
"static/chunks/_18x7jxupx5rou._.js"
"static/chunks/_0sf-lmfgdqib-._.js"
]
},
"pagesChunkGroupBootstrapParams": {},
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"kind":"FETCH","data":{"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"Content-Disposition,Refresh-Authorization","connection":"keep-alive","content-encoding":"gzip","content-type":"application/json; charset=utf-8","date":"Sat, 07 Nov 2026 04:13:32 GMT","server":"nginx/1.24.0 (Ubuntu)","transfer-encoding":"chunked"},"body":"eyJjb2RlIjoyMDAsImRhdGEiOnsiZm9vdGVySW5mbyI6eyJicmFuZCI6eyJ0aXRsZSI6IueGn+aenOefreWJpyIsImNvbnRlbnQiOiLnhp/mnpznn63liafkvZzkuLrpooblhYjnmoRBSeaIkOS6uuefreWJp+S4jueyvuWTgeefreinhumikee7vOWQiOW5s+WPsO+8jOaxh+mbhuWFqOe9keWOn+WIm+mrmOiDvUlQ5LiO5Y+N6L2s54i95Ymn44CC56uZ5YaF54us5a6254Ot5pKt44CK6aOO5Y2O56We5aWz5b2V44CL44CK55C85piO56We5aWz5b2V44CL44CK5q+N5LiK5pS755Wl44CL44CK5LuZ5a2Q55qE5L+u6KGM44CL44CK5p6B5ZOB5a625LiB44CL562J5aSa6aKY5p2Q5Yqb5L2c77yM5ra155uW5LuZ5L6g5aWH5bm744CB6YO95biC5Lmx5Lym44CB6IGM5Zy65LiO56m/6LaK44CC5YWo56uZ55S76LSo6LaF5riF5peg5Yig5YeP44CB5q+P5pel5pu05paw5pyA5paw6ZuG77yM5pSv5oyB572R6aG15Y2z54K55Y2z5pKt5LiO5a6Y5pa5QVBQ5o6M5LiK6KeC5b2x77yM5byA5ZCv5p6B6Ie05rKJ5rW455qE6KeG5ZCs55ub5a6044CCIn0sIm5hdkxpc3QiOlt7ImlkIjoxMjcwNywibmFtZSI6IuW6lemDqOWvvOiIqiIsImljb24iOiIiLCJ0cmFuc2xhdGlvbkxpc3QiOlt7ImlkIjoxMjY3MSwibmFtZSI6IuWFs+S6juaIkeS7rCIsImlzRnJpZW5kQWRzIjpmYWxzZSwidXJsVmFsdWUiOiIvcmljaHRleHQv5YWz5LqO5oiR5LusIn0seyJpZCI6MTI2NzMsIm5hbWUiOiLpmpDnp4HmlL/nrZYiLCJpc0ZyaWVuZEFkcyI6ZmFsc2UsInVybFZhbHVlIjoiL3JpY2h0ZXh0L+makOengeaUv+etliJ9LHsiaWQiOjEyNjc0LCJuYW1lIjoi572R56uZ55aR6ZeuIiwiaXNGcmllbmRBZHMiOmZhbHNlLCJ1cmxWYWx1ZSI6Ii9yaWNodGV4dC/nvZHnq5nnlpHpl64ifSx7ImlkIjoxMjY3NSwibmFtZSI6IuaEj+ingeWPjemmiCIsImlzRnJpZW5kQWRzIjpmYWxzZSwidXJsVmFsdWUiOiIvZmVlZGJhY2sifSx7ImlkIjoxMjY3NiwibmFtZSI6IjIyNTciLCJpc0ZyaWVuZEFkcyI6ZmFsc2UsInVybFZhbHVlIjoiL3JpY2hldGV4dC8yMjU3In0seyJpZCI6MTI2NzcsIm5hbWUiOiJETUNBIiwiaXNGcmllbmRBZHMiOmZhbHNlLCJ1cmxWYWx1ZSI6Ii9yaWNoZXRleHQvRE1DQSJ9XSwidXJsVmFsdWUiOiIiLCJjYXRlZ29yeVR5cGUiOjMsInNlb0luZm8iOnsidGl0bGUiOiIiLCJrZXl3b3JsZCI6W10sImRlc2NyaXB0aW9uIjoiIn19XSwiY29udGFjdExpc3QiOlt7Im5hbWUiOiJFLW1haWwiLCJ2YWx1ZSI6Imh0dHBzOi8vY2hlbmdyZW52aWRlb0Bwcm90b24ubWUifSx7Im5hbWUiOiLllYbliqHlkIjkvZzvvJrnq4vljbPogZTns7siLCJ2YWx1ZSI6IiJ9LHsibmFtZSI6IuWumOaWuee+pO+8mueri+WNs+WKoOWFpSIsInZhbHVlIjoiaHR0cHM6Ly90Lm1lL1NodUd1b0FJMDEifV19fSwiaGFzaCI6ZmFsc2UsIm1zZyI6InN1Y2Nlc3MiLCJ0aW1lIjoiMjAyNi0xMS0wN1QwNDoxMzozMi44OTJaIiwidGlwIjoi5oiQ5YqfIn0=","status":200,"url":"https://webhgbapi.mfcg.me/api/app/config/footer/info"},"revalidate":60,"tags":["footer-info"]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"kind":"FETCH","data":{"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"Content-Disposition,Refresh-Authorization","connection":"keep-alive","content-encoding":"gzip","content-type":"application/json; charset=utf-8","date":"Sat, 07 Nov 2026 04:13:14 GMT","server":"nginx/1.24.0 (Ubuntu)","transfer-encoding":"chunked"},"body":"eyJjb2RlIjoyMDAsImRhdGEiOnsiZm9vdGVySW5mbyI6eyJicmFuZCI6eyJ0aXRsZSI6IueGn+aenOefreWJpyIsImNvbnRlbnQiOiLnhp/mnpznn63liafkvZzkuLrpooblhYjnmoRBSeaIkOS6uuefreWJp+S4jueyvuWTgeefreinhumikee7vOWQiOW5s+WPsO+8jOaxh+mbhuWFqOe9keWOn+WIm+mrmOiDvUlQ5LiO5Y+N6L2s54i95Ymn44CC56uZ5YaF54us5a6254Ot5pKt44CK6aOO5Y2O56We5aWz5b2V44CL44CK55C85piO56We5aWz5b2V44CL44CK5q+N5LiK5pS755Wl44CL44CK5LuZ5a2Q55qE5L+u6KGM44CL44CK5p6B5ZOB5a625LiB44CL562J5aSa6aKY5p2Q5Yqb5L2c77yM5ra155uW5LuZ5L6g5aWH5bm744CB6YO95biC5Lmx5Lym44CB6IGM5Zy65LiO56m/6LaK44CC5YWo56uZ55S76LSo6LaF5riF5peg5Yig5YeP44CB5q+P5pel5pu05paw5pyA5paw6ZuG77yM5pSv5oyB572R6aG15Y2z54K55Y2z5pKt5LiO5a6Y5pa5QVBQ5o6M5LiK6KeC5b2x77yM5byA5ZCv5p6B6Ie05rKJ5rW455qE6KeG5ZCs55ub5a6044CCIn0sIm5hdkxpc3QiOlt7ImlkIjoxMjcwNywibmFtZSI6IuW6lemDqOWvvOiIqiIsImljb24iOiIiLCJ0cmFuc2xhdGlvbkxpc3QiOlt7ImlkIjoxMjY3MSwibmFtZSI6IuWFs+S6juaIkeS7rCIsImlzRnJpZW5kQWRzIjpmYWxzZSwidXJsVmFsdWUiOiIvcmljaHRleHQv5YWz5LqO5oiR5LusIn0seyJpZCI6MTI2NzMsIm5hbWUiOiLpmpDnp4HmlL/nrZYiLCJpc0ZyaWVuZEFkcyI6ZmFsc2UsInVybFZhbHVlIjoiL3JpY2h0ZXh0L+makOengeaUv+etliJ9LHsiaWQiOjEyNjc0LCJuYW1lIjoi572R56uZ55aR6ZeuIiwiaXNGcmllbmRBZHMiOmZhbHNlLCJ1cmxWYWx1ZSI6Ii9yaWNodGV4dC/nvZHnq5nnlpHpl64ifSx7ImlkIjoxMjY3NSwibmFtZSI6IuaEj+ingeWPjemmiCIsImlzRnJpZW5kQWRzIjpmYWxzZSwidXJsVmFsdWUiOiIvZmVlZGJhY2sifSx7ImlkIjoxMjY3NiwibmFtZSI6IjIyNTciLCJpc0ZyaWVuZEFkcyI6ZmFsc2UsInVybFZhbHVlIjoiL3JpY2hldGV4dC8yMjU3In0seyJpZCI6MTI2NzcsIm5hbWUiOiJETUNBIiwiaXNGcmllbmRBZHMiOmZhbHNlLCJ1cmxWYWx1ZSI6Ii9yaWNoZXRleHQvRE1DQSJ9XSwidXJsVmFsdWUiOiIiLCJjYXRlZ29yeVR5cGUiOjMsInNlb0luZm8iOnsidGl0bGUiOiIiLCJrZXl3b3JsZCI6W10sImRlc2NyaXB0aW9uIjoiIn19XSwiY29udGFjdExpc3QiOlt7Im5hbWUiOiJFLW1haWwiLCJ2YWx1ZSI6Imh0dHBzOi8vY2hlbmdyZW52aWRlb0Bwcm90b24ubWUifSx7Im5hbWUiOiLllYbliqHlkIjkvZzvvJrnq4vljbPogZTns7siLCJ2YWx1ZSI6IiJ9LHsibmFtZSI6IuWumOaWuee+pO+8mueri+WNs+WKoOWFpSIsInZhbHVlIjoiaHR0cHM6Ly90Lm1lL1NodUd1b0FJMDEifV19fSwiaGFzaCI6ZmFsc2UsIm1zZyI6InN1Y2Nlc3MiLCJ0aW1lIjoiMjAyNi0xMS0wN1QwNDoxMzoxNC42OTRaIiwidGlwIjoi5oiQ5YqfIn0=","status":200,"url":"https://webhgbapi.mfcg.me/api/app/config/footer/info"},"revalidate":60,"tags":["footer-info"]}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
{"max_sequence_number":189,"commit_time":"2026-11-05T17:06:11.956948Z"}
{"max_sequence_number":227,"commit_time":"2026-11-07T04:13:42.436926Z"}
+57
View File
@@ -376,3 +376,60 @@ FAM | META SEQ | SST SEQ | RANGE
1 | 00000188 | 00000143 00000144 00000149 00000161 00000169 00000181 OBSOLETE SST
| | 00000143 00000144 00000149 00000161 00000169 00000181 SST DELETED
| | 00000145 00000154 00000166 00000174 00000185 META DELETED
Time 2026-11-07T04:09:23.562661Z
Commit 00000197 25607 keys in 22ms 772µs
FAM | META SEQ | SST SEQ | RANGE
0 | 00000194 | 00000193 SST | O | c44bdff4074eecdb-c44bdff4074eecdb (0 MiB, fresh, 38 bytes, 1 entries, 0 tombstones)
3 | 00000195 | 00000191 SST | [==================================================================================================] | 00074e2d5e1aef87-fffc639dc1876c17 (0 MiB, fresh, 26529 bytes, 2201 entries, 0 tombstones)
2 | 00000196 | 00000190 SST | [==================================================================================================] | 0006918236657861-fff3c034418ba0e5 (3 MiB, fresh, 3335775 bytes, 4580 entries, 0 tombstones)
1 | 00000197 | 00000192 SST | [==================================================================================================] | 0003356ded434e7f-fffd6fbd2229df8a (6 MiB, fresh, 6415690 bytes, 18825 entries, 0 tombstones)
Time 2026-11-07T04:11:54.939554Z
Commit 00000205 53030 keys in 25ms 871µs
FAM | META SEQ | SST SEQ | RANGE
0 | 00000202 | 00000201 SST | O | c44bdff4074eecdb-c44bdff4074eecdb (0 MiB, fresh, 38 bytes, 1 entries, 0 tombstones)
3 | 00000203 | 00000198 SST | [==================================================================================================] | 004687eb627740df-ffd92fcebb948480 (0 MiB, fresh, 27873 bytes, 2313 entries, 0 tombstones)
2 | 00000204 | 00000199 SST | [==================================================================================================] | 00013daa2e97875e-fffe1000326d5b11 (5 MiB, fresh, 6153672 bytes, 15292 entries, 0 tombstones)
1 | 00000205 | 00000200 SST | [==================================================================================================] | 00013daa2e97875e-fffe1000326d5b11 (7 MiB, fresh, 7875402 bytes, 35424 entries, 0 tombstones)
2 | 00000209 | Compaction:
2 | 00000209 | MERGE (33172 keys):
2 | 00000209 | 00000155 INPUT | [==================================================================================================] | 00013daa2e97875e-fffccbe9625d2d11
2 | 00000209 | 00000158 INPUT | [==================================================================================================] | 00013daa2e97875e-fffccbe9625d2d11
2 | 00000209 | 00000160 INPUT | [==================================================================================================] | 0008ca2a8bf0c07d-fff3c034418ba0e5
2 | 00000209 | 00000168 INPUT | [==================================================================================================] | 0006918236657861-ffa66562c90d408a
2 | 00000209 | 00000180 INPUT | [==================================================================================================] | 0006918236657861-ffebd49f0ef4bfdb
2 | 00000209 | 00000190 INPUT | [==================================================================================================] | 0006918236657861-fff3c034418ba0e5
2 | 00000209 | 00000199 INPUT | [==================================================================================================] | 00013daa2e97875e-fffe1000326d5b11
2 | 00000209 | 00000206 OUTPUT | [==================================================================================================] | 00013daa2e97875e-fffe1000326d5b11 (compacted)
1 | 00000210 | Compaction:
1 | 00000210 | MERGE (381465 keys):
1 | 00000210 | 00000186 INPUT | [==================================================================================================] | 00001b5ec0be92f9-ffffa6219f6e8533
1 | 00000210 | 00000187 INPUT | [==================================================================================================] | 0003356ded434e7f-fffdbf7d578e72a9
1 | 00000210 | 00000192 INPUT | [==================================================================================================] | 0003356ded434e7f-fffd6fbd2229df8a
1 | 00000210 | 00000200 INPUT | [==================================================================================================] | 00013daa2e97875e-fffe1000326d5b11
1 | 00000210 | 00000207 OUTPUT | [==================================================================================================] | 00001b5ec0be92f9-ffffa6219f6e8533 (cold bottom)
1 | 00000210 | 00000208 OUTPUT | [==================================================================================================] | 00013daa2e97875e-fffddf739e16297d (hot bottom)
Time 2026-11-07T04:11:55.243174Z
Commit 00000211 414637 keys in 22ms 156µs
FAM | META SEQ | SST SEQ | RANGE
2 | 00000209 | 00000206 SST | [==================================================================================================] | 00013daa2e97875e-fffe1000326d5b11 (33 MiB, compacted, 34778157 bytes, 33172 entries, 0 tombstones)
2 | 00000209 | 00000155 00000158 00000160 00000168 00000180 00000190 00000199 OBSOLETE SST
1 | 00000210 | 00000207 SST | [==================================================================================================] | 00001b5ec0be92f9-ffffa6219f6e8533 (16 MiB, cold bottom, 17041762 bytes, 315138 entries, 0 tombstones)
1 | 00000210 | 00000208 SST | [==================================================================================================] | 00013daa2e97875e-fffddf739e16297d (10 MiB, hot bottom, 10949030 bytes, 66327 entries, 0 tombstones)
1 | 00000210 | 00000186 00000187 00000192 00000200 OBSOLETE SST
| | 00000155 00000158 00000160 00000168 00000180 00000186 00000187 00000190 00000192 00000199 00000200 SST DELETED
| | 00000188 00000197 00000205 META DELETED
| | 00000156 00000165 00000173 00000184 00000196 00000204 META DELETED
Time 2026-11-07T04:13:16.262145Z
Commit 00000219 15491 keys in 27ms 815µs
FAM | META SEQ | SST SEQ | RANGE
0 | 00000216 | 00000215 SST | O | c44bdff4074eecdb-c44bdff4074eecdb (0 MiB, fresh, 38 bytes, 1 entries, 0 tombstones)
3 | 00000217 | 00000212 SST | [==================================================================================================] | 0044374e39240467-ffaf63c9f0fbf2ed (0 MiB, fresh, 6321 bytes, 524 entries, 0 tombstones)
2 | 00000218 | 00000213 SST | [==================================================================================================] | 000d0c97c75ad9ad-fff3c034418ba0e5 (2 MiB, fresh, 2947771 bytes, 4256 entries, 0 tombstones)
1 | 00000219 | 00000214 SST | [==================================================================================================] | 0003356ded434e7f-fff8d995d4bba353 (4 MiB, fresh, 4581354 bytes, 10710 entries, 0 tombstones)
Time 2026-11-07T04:13:42.405517Z
Commit 00000227 14386 keys in 37ms 370µs
FAM | META SEQ | SST SEQ | RANGE
0 | 00000224 | 00000223 SST | O | c44bdff4074eecdb-c44bdff4074eecdb (0 MiB, fresh, 38 bytes, 1 entries, 0 tombstones)
3 | 00000225 | 00000220 SST | [==================================================================================================] | 00a5f2839d52062a-ff31b2ec1283c990 (0 MiB, fresh, 5901 bytes, 489 entries, 0 tombstones)
1 | 00000226 | 00000222 SST | [==================================================================================================] | 0004dceb9b3a19a9-fff8d995d4bba353 (3 MiB, fresh, 3538081 bytes, 9830 entries, 0 tombstones)
2 | 00000227 | 00000221 SST | [==================================================================================================] | 0004dceb9b3a19a9-fff3c034418ba0e5 (1 MiB, fresh, 1937235 bytes, 4066 entries, 0 tombstones)
+1
View File
@@ -0,0 +1 @@
{"pid":58626,"port":26149,"hostname":"localhost","appUrl":"http://localhost:26149","startedAt":1794024464267}
+1 -1
View File
@@ -1 +1 @@
{"version":3,"caseSensitive":false,"basePath":"","rewrites":{"beforeFiles":[],"afterFiles":[],"fallback":[{"source":"/api/:path*","destination":"https://sgdj-h5.80sygtm.com/api/:path*","regex":"^\\/api(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?(?:\\/)?$","check":true}]},"redirects":[{"source":"/:path+/","destination":"/:path+","permanent":true,"internal":true,"priority":true,"regex":"^(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))\\/$"}],"headers":[],"onMatchHeaders":[]}
{"version":3,"caseSensitive":false,"basePath":"","rewrites":{"beforeFiles":[],"afterFiles":[],"fallback":[{"source":"/api/:path*","destination":"https://webhgbapi.mfcg.me/api/:path*","regex":"^\\/api(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))?(?:\\/)?$","check":true}]},"redirects":[{"source":"/:path+/","destination":"/:path+","permanent":true,"internal":true,"priority":true,"regex":"^(?:\\/((?:[^\\/]+?)(?:\\/(?:[^\\/]+?))*))\\/$"}],"headers":[],"onMatchHeaders":[]}
+6 -3
View File
@@ -1,8 +1,11 @@
{
"/_not-found/page": "app/_not-found/page.js",
"/api/[...path]/route": "app/api/[...path]/route.js",
"/nav/page": "app/nav/page.js",
"/drama/[id]/page": "app/drama/[id]/page.js",
"/enkey/route": "app/enkey/route.js",
"/h5/chapter-detail/route": "app/h5/chapter-detail/route.js",
"/h5/m3u8/[...path]/route": "app/h5/m3u8/[...path]/route.js",
"/home-road/page": "app/home-road/page.js",
"/page": "app/page.js",
"/play/[id]/[episode]/page": "app/play/[id]/[episode]/page.js",
"/robots.txt/route": "app/robots.txt/route.js"
"/search/[[...parts]]/page": "app/search/[[...parts]]/page.js"
}
+2 -2
View File
@@ -1,5 +1,5 @@
var R=require("../../../chunks/ssr/[turbopack]_runtime.js")("server/app/drama/[id]/page.js")
R.c("server/chunks/ssr/[root-of-the-server]__1_rmksccog9y3._.js")
R.c("server/chunks/ssr/[root-of-the-server]__0_19tjch_mrfx._.js")
R.c("server/chunks/ssr/node_modules_next_dist_06htj7u026hps._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_server_0i519_x_u947b._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_shared_lib_110_pvnwn9uqh._.js")
@@ -8,7 +8,7 @@ R.c("server/chunks/ssr/node_modules_next_dist_esm_0_65u7e78e6h9._.js")
R.c("server/chunks/ssr/node_modules_next_dist_compiled_00yj_1pr91zo-._.js")
R.c("server/chunks/ssr/node_modules_next_dist_server_route-modules_app-page_0qo_rmcihhsx5._.js")
R.c("server/chunks/ssr/[externals]__1cacbhfx2nbuk._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1w0ppiu6oha67._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1r_ycdo5ggf5t._.js")
R.c("server/chunks/ssr/node_modules_0n2q5m2nq0yi9._.js")
R.c("server/chunks/ssr/src_0hsbhz7n16r_g._.js")
R.c("server/chunks/ssr/src_app_not-found_tsx_1863-sqmkh7ny._.js")
File diff suppressed because one or more lines are too long
+6
View File
@@ -0,0 +1,6 @@
var R=require("../../chunks/[turbopack]_runtime.js")("server/app/enkey/route.js")
R.c("server/chunks/node_modules_next_dist_1gu--yty9067e._.js")
R.c("server/chunks/[root-of-the-server]__1y_dny-cu_otu._.js")
R.c("server/chunks/_next-internal_server_app_enkey_route_actions_0jqwrpk0x1_pi.js")
R.m("[project]/node_modules/next/dist/esm/build/templates/app-route.js { INNER_APP_ROUTE => \"[project]/src/app/enkey/route.ts [app-route] (ecmascript)\" } [app-route] (ecmascript)")
module.exports=R.m("[project]/node_modules/next/dist/esm/build/templates/app-route.js { INNER_APP_ROUTE => \"[project]/src/app/enkey/route.ts [app-route] (ecmascript)\" } [app-route] (ecmascript)").exports
@@ -0,0 +1,5 @@
{
"version": 3,
"sources": [],
"sections": []
}
@@ -0,0 +1,3 @@
{
"/enkey/route": "app/enkey/route.js"
}
@@ -0,0 +1,12 @@
{
"devFiles": [],
"ampDevFiles": [],
"polyfillFiles": [],
"lowPriorityFiles": [],
"rootMainFiles": [],
"pages": {},
"ampFirstPages": [],
"rootMainFilesTree": {},
"pagesChunkGroupBootstrapParams": {},
"chunkLoadingGlobal": "TURBOPACK"
}
@@ -0,0 +1,4 @@
{
"node": {},
"edge": {}
}
@@ -0,0 +1,3 @@
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {};
globalThis.__RSC_MANIFEST["/enkey/route"] = {"moduleLoading":{"prefix":""},"clientModules":{},"ssrModuleMapping":{},"edgeSSRModuleMapping":{},"rscModuleMapping":{},"edgeRscModuleMapping":{},"entryCSSFiles":{},"entryJSFiles":{}};
@@ -0,0 +1,6 @@
var R=require("../../../chunks/[turbopack]_runtime.js")("server/app/h5/chapter-detail/route.js")
R.c("server/chunks/node_modules_next_0fizghk6jc8ls._.js")
R.c("server/chunks/[root-of-the-server]__0a8xmgadn_opt._.js")
R.c("server/chunks/_next-internal_server_app_h5_chapter-detail_route_actions_1xc2wcl27dmcm.js")
R.m("[project]/node_modules/next/dist/esm/build/templates/app-route.js { INNER_APP_ROUTE => \"[project]/src/app/h5/chapter-detail/route.ts [app-route] (ecmascript)\" } [app-route] (ecmascript)")
module.exports=R.m("[project]/node_modules/next/dist/esm/build/templates/app-route.js { INNER_APP_ROUTE => \"[project]/src/app/h5/chapter-detail/route.ts [app-route] (ecmascript)\" } [app-route] (ecmascript)").exports
@@ -0,0 +1,5 @@
{
"version": 3,
"sources": [],
"sections": []
}
@@ -0,0 +1,3 @@
{
"/h5/chapter-detail/route": "app/h5/chapter-detail/route.js"
}
@@ -0,0 +1,12 @@
{
"devFiles": [],
"ampDevFiles": [],
"polyfillFiles": [],
"lowPriorityFiles": [],
"rootMainFiles": [],
"pages": {},
"ampFirstPages": [],
"rootMainFilesTree": {},
"pagesChunkGroupBootstrapParams": {},
"chunkLoadingGlobal": "TURBOPACK"
}
@@ -0,0 +1,4 @@
{
"node": {},
"edge": {}
}
@@ -0,0 +1,3 @@
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {};
globalThis.__RSC_MANIFEST["/h5/chapter-detail/route"] = {"moduleLoading":{"prefix":""},"clientModules":{},"ssrModuleMapping":{},"edgeSSRModuleMapping":{},"rscModuleMapping":{},"edgeRscModuleMapping":{},"entryCSSFiles":{},"entryJSFiles":{}};
@@ -0,0 +1,6 @@
var R=require("../../../../chunks/[turbopack]_runtime.js")("server/app/h5/m3u8/[...path]/route.js")
R.c("server/chunks/node_modules_next_dist_1ogzfy-d5327p._.js")
R.c("server/chunks/[root-of-the-server]__1dpw5ck2p-gjg._.js")
R.c("server/chunks/_next-internal_server_app_h5_m3u8_[___path]_route_actions_1-5tcp3v1fddu.js")
R.m("[project]/node_modules/next/dist/esm/build/templates/app-route.js { INNER_APP_ROUTE => \"[project]/src/app/h5/m3u8/[...path]/route.ts [app-route] (ecmascript)\" } [app-route] (ecmascript)")
module.exports=R.m("[project]/node_modules/next/dist/esm/build/templates/app-route.js { INNER_APP_ROUTE => \"[project]/src/app/h5/m3u8/[...path]/route.ts [app-route] (ecmascript)\" } [app-route] (ecmascript)").exports
@@ -0,0 +1,5 @@
{
"version": 3,
"sources": [],
"sections": []
}
@@ -0,0 +1,3 @@
{
"/h5/m3u8/[...path]/route": "app/h5/m3u8/[...path]/route.js"
}
@@ -0,0 +1,12 @@
{
"devFiles": [],
"ampDevFiles": [],
"polyfillFiles": [],
"lowPriorityFiles": [],
"rootMainFiles": [],
"pages": {},
"ampFirstPages": [],
"rootMainFilesTree": {},
"pagesChunkGroupBootstrapParams": {},
"chunkLoadingGlobal": "TURBOPACK"
}
@@ -0,0 +1,4 @@
{
"node": {},
"edge": {}
}
@@ -0,0 +1,3 @@
globalThis.__RSC_MANIFEST = globalThis.__RSC_MANIFEST || {};
globalThis.__RSC_MANIFEST["/h5/m3u8/[...path]/route"] = {"moduleLoading":{"prefix":""},"clientModules":{},"ssrModuleMapping":{},"edgeSSRModuleMapping":{},"rscModuleMapping":{},"edgeRscModuleMapping":{},"entryCSSFiles":{},"entryJSFiles":{}};
+2 -2
View File
@@ -1,5 +1,5 @@
var R=require("../../chunks/ssr/[turbopack]_runtime.js")("server/app/home-road/page.js")
R.c("server/chunks/ssr/[root-of-the-server]__0ippu_ubd11jy._.js")
R.c("server/chunks/ssr/[root-of-the-server]__06u--2ju43-zu._.js")
R.c("server/chunks/ssr/node_modules_next_dist_1-4jhhtr3ossi._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_server_0i519_x_u947b._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_shared_lib_110_pvnwn9uqh._.js")
@@ -8,7 +8,7 @@ R.c("server/chunks/ssr/node_modules_next_dist_esm_0_65u7e78e6h9._.js")
R.c("server/chunks/ssr/node_modules_next_dist_compiled_00yj_1pr91zo-._.js")
R.c("server/chunks/ssr/node_modules_next_dist_server_route-modules_app-page_0qo_rmcihhsx5._.js")
R.c("server/chunks/ssr/[externals]__1cacbhfx2nbuk._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1w0ppiu6oha67._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1r_ycdo5ggf5t._.js")
R.c("server/chunks/ssr/node_modules_0n2q5m2nq0yi9._.js")
R.c("server/chunks/ssr/src_0hsbhz7n16r_g._.js")
R.c("server/chunks/ssr/src_app_not-found_tsx_1863-sqmkh7ny._.js")
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,5 +1,5 @@
var R=require("../chunks/ssr/[turbopack]_runtime.js")("server/app/page.js")
R.c("server/chunks/ssr/[root-of-the-server]__039oh1dcvo4v2._.js")
R.c("server/chunks/ssr/[root-of-the-server]__067m3twdyxcop._.js")
R.c("server/chunks/ssr/node_modules_next_dist_087ejwjk1qamh._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_server_0i519_x_u947b._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_shared_lib_110_pvnwn9uqh._.js")
@@ -8,7 +8,7 @@ R.c("server/chunks/ssr/node_modules_next_dist_esm_0_65u7e78e6h9._.js")
R.c("server/chunks/ssr/node_modules_next_dist_compiled_00yj_1pr91zo-._.js")
R.c("server/chunks/ssr/node_modules_next_dist_server_route-modules_app-page_0qo_rmcihhsx5._.js")
R.c("server/chunks/ssr/[externals]__1cacbhfx2nbuk._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1w0ppiu6oha67._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1r_ycdo5ggf5t._.js")
R.c("server/chunks/ssr/node_modules_0n2q5m2nq0yi9._.js")
R.c("server/chunks/ssr/src_0hsbhz7n16r_g._.js")
R.c("server/chunks/ssr/src_app_not-found_tsx_1863-sqmkh7ny._.js")
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
var R=require("../../../../chunks/ssr/[turbopack]_runtime.js")("server/app/play/[id]/[episode]/page.js")
R.c("server/chunks/ssr/[root-of-the-server]__0zbexg5uovxbr._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1trcdg5d06d62._.js")
R.c("server/chunks/ssr/node_modules_next_dist_091c9w7_pnh6a._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_server_0i519_x_u947b._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_shared_lib_110_pvnwn9uqh._.js")
@@ -8,7 +8,7 @@ R.c("server/chunks/ssr/node_modules_next_dist_esm_0_65u7e78e6h9._.js")
R.c("server/chunks/ssr/node_modules_next_dist_compiled_00yj_1pr91zo-._.js")
R.c("server/chunks/ssr/node_modules_next_dist_server_route-modules_app-page_0qo_rmcihhsx5._.js")
R.c("server/chunks/ssr/[externals]__1cacbhfx2nbuk._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1w0ppiu6oha67._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1r_ycdo5ggf5t._.js")
R.c("server/chunks/ssr/node_modules_0n2q5m2nq0yi9._.js")
R.c("server/chunks/ssr/src_0hsbhz7n16r_g._.js")
R.c("server/chunks/ssr/src_app_not-found_tsx_1863-sqmkh7ny._.js")
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
var R=require("../../../chunks/ssr/[turbopack]_runtime.js")("server/app/search/[[...parts]]/page.js")
R.c("server/chunks/ssr/[root-of-the-server]__1p78lu1ompxz4._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1ao6i5v9mu7h2._.js")
R.c("server/chunks/ssr/node_modules_next_dist_1041i6l4sgy8u._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_server_0i519_x_u947b._.js")
R.c("server/chunks/ssr/node_modules_next_dist_esm_shared_lib_110_pvnwn9uqh._.js")
@@ -8,7 +8,7 @@ R.c("server/chunks/ssr/node_modules_next_dist_esm_0_65u7e78e6h9._.js")
R.c("server/chunks/ssr/node_modules_next_dist_compiled_00yj_1pr91zo-._.js")
R.c("server/chunks/ssr/node_modules_next_dist_server_route-modules_app-page_0qo_rmcihhsx5._.js")
R.c("server/chunks/ssr/[externals]__1cacbhfx2nbuk._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1w0ppiu6oha67._.js")
R.c("server/chunks/ssr/[root-of-the-server]__1r_ycdo5ggf5t._.js")
R.c("server/chunks/ssr/node_modules_0n2q5m2nq0yi9._.js")
R.c("server/chunks/ssr/src_0hsbhz7n16r_g._.js")
R.c("server/chunks/ssr/src_app_not-found_tsx_1863-sqmkh7ny._.js")
File diff suppressed because one or more lines are too long
@@ -0,0 +1,570 @@
module.exports = [
(()=>{"use strict";return[
"[project]/src/app/h5/chapter-detail/route.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"GET",
()=>GET
]);
var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$server$2e$js__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/node_modules/next/server.js [app-route] (ecmascript)");
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/client-headers.ts [app-route] (ecmascript)");
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$server$2d$fetch$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/server-fetch.ts [app-route] (ecmascript)");
;
;
;
async function GET(request) {
await (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$server$2e$js__$5b$app$2d$route$5d$__$28$ecmascript$29$__["connection"])();
const incoming = new URL(request.url);
const chapterId = incoming.searchParams.get("chapterId")?.trim() || "";
if (!chapterId) {
return Response.json({
code: 1001,
data: null,
tip: "缺少剧集 chapterId",
msg: "",
hash: false
}, {
status: 200,
headers: {
"cache-control": "no-store"
}
});
}
const query = new URLSearchParams({
chapterId
});
const playletSlug = incoming.searchParams.get("playletSlug")?.trim();
const playletId = incoming.searchParams.get("playletId")?.trim();
if (playletSlug) query.set("playletSlug", playletSlug);
else if (playletId) query.set("playletId", playletId);
const path = `/api/app/playlet/chapter/detail?${query}`;
try {
const data = await fetchChapterForPlay(path, request);
return Response.json({
code: 200,
data,
tip: "成功",
msg: "",
hash: false
}, {
status: 200,
headers: {
"cache-control": "no-store"
}
});
} catch (error) {
const tip = error instanceof Error ? error.message : "剧集详情加载失败";
return Response.json({
code: 500,
data: null,
tip,
msg: "",
hash: false
}, {
status: 200,
headers: {
"cache-control": "no-store"
}
});
}
}
async function fetchChapterForPlay(pathWithQuery, request) {
const internal = process.env.API_INTERNAL_ORIGIN?.trim().replace(/\/$/, "");
const ticketXff = process.env.MEDIA_TICKET_FORWARDED_FOR?.trim();
// 测试/预发:直连本机 Go,并用出站公网 IP 作为 XFF,与 /enkey 同源。
if (internal && ticketXff) {
const headers = {
Accept: "application/json",
...(0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["clientHeaders"])(request.headers),
"X-Forwarded-For": ticketXff,
"X-Real-IP": ticketXff
};
const response = await fetch(`${internal}${pathWithQuery}`, {
headers,
cache: "no-store",
signal: AbortSignal.timeout(10_000)
});
const text = await response.text();
let payload = null;
try {
payload = text ? JSON.parse(text) : null;
} catch {
payload = null;
}
if (!payload || typeof payload.code !== "number") {
throw new Error(response.ok ? "接口响应格式异常" : `接口暂时不可用 (${response.status})`);
}
if (!response.ok || payload.code !== 200) {
throw new Error(payload.tip || payload.msg || "请求失败");
}
return payload.data;
}
return (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$server$2d$fetch$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["serverFetchJson"])(pathWithQuery, {
maxAttempts: 2,
timeoutMs: 10_000,
revalidate: 0
});
}
}),
"[project]/src/lib/api/client-headers.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"buildBrowserApiHeaders",
()=>buildBrowserApiHeaders,
"clientHeaders",
()=>clientHeaders,
"clientIp",
()=>clientIp
]);
const APP_VER = ("TURBOPACK compile-time value", "1.0.0")?.trim() || "1.0.0";
function clean(value) {
return value.replace(/[^\x20-\x7E]|[;=]/g, " ").trim();
}
/** 不依赖 node:net,避免被浏览器端打包。 */ function isIP(value) {
if (/^(?:\d{1,3}\.){3}\d{1,3}$/.test(value)) {
return value.split(".").every((part)=>{
const n = Number(part);
return String(n) === part && n >= 0 && n <= 255;
});
}
// 宽松校验 IPv6,够用来转发 X-Real-IP。
return value.includes(":") && /^[0-9a-fA-F:.]+$/.test(value);
}
function sysType(ua) {
const value = ua.toLowerCase();
if (value.includes("android")) return "h5_android";
if (value.includes("iphone") || value.includes("ipad") || value.includes("ipod")) return "h5_ios";
return "h5_pc";
}
function guessAndroidBrand(model, ua) {
const value = `${model} ${ua}`;
const brands = [
[
/Build\/HONOR|\bHONOR\b/i,
"Honor"
],
[
/Build\/HUAWEI|HUAWEI|HW-/i,
"Huawei"
],
[
/SM-|samsung|Galaxy/i,
"Samsung"
],
[
/Pixel/i,
"Google"
],
[
/Redmi|POCO|XiaoMi|\bMi\b/i,
"Xiaomi"
],
[
/OPPO|\bCPH\d{3,4}/i,
"OPPO"
],
[
/vivo|\bV\d{4}/i,
"vivo"
],
[
/OnePlus|ONEPLUS/i,
"OnePlus"
],
[
/realme|\bRMX\d{3,4}/i,
"realme"
]
];
return brands.find(([pattern])=>pattern.test(value))?.[1] || "";
}
function parseBrowser(ua) {
const edge = ua.match(/Edg\/([\d.]+)/i);
if (edge) return `Edge ${edge[1]}`;
const opera = ua.match(/(?:OPR|Opera)\/([\d.]+)/i);
if (opera) return `Opera ${opera[1]}`;
const chrome = ua.match(/Chrome\/([\d.]+)/i);
if (chrome && !/Edg\//i.test(ua)) return `Chrome ${chrome[1]}`;
const safari = ua.match(/Version\/([\d.]+).*Safari/i);
if (safari) return `Safari ${safari[1]}`;
const firefox = ua.match(/Firefox\/([\d.]+)/i);
if (firefox) return `Firefox ${firefox[1]}`;
const ie = ua.match(/(?:MSIE\s|Trident.*rv:)([\d.]+)/i);
if (ie) return `IE ${ie[1]}`;
return "";
}
/** 从浏览器 User-Agent 解析设备公共字段,口径对齐 jha-1040 useragent.ParseDeviceFromUA。 */ function parseDeviceFromUA(ua) {
const raw = ua.trim();
let deviceBrand = "";
let deviceModel = "";
let deviceType = "desktop";
let systemName = "Other";
let systemVersion = "";
if (/iPhone|iPad|iPod/i.test(raw)) {
systemName = "iOS";
deviceBrand = "Apple";
const ios = raw.match(/OS (\d+[_\d]*) like Mac OS X/i);
if (ios) systemVersion = ios[1].replace(/_/g, ".");
if (/iPad/i.test(raw)) {
deviceModel = "iPad";
deviceType = "tablet";
} else if (/iPod/i.test(raw)) {
deviceModel = "iPod";
deviceType = "mobile";
} else {
deviceModel = "iPhone";
deviceType = "mobile";
}
} else if (/Android/i.test(raw)) {
systemName = "Android";
const version = raw.match(/Android ([\d.]+)/i);
if (version) systemVersion = version[1];
const model = raw.match(/Android\s+[\d.]+;\s*([^;)]+?)(?:\s+Build\/|\))/i);
if (model?.[1]) deviceModel = model[1].trim();
deviceBrand = guessAndroidBrand(deviceModel, raw);
deviceType = /Mobile/i.test(raw) ? "mobile" : "tablet";
} else if (/Windows/i.test(raw)) {
systemName = "Windows";
const win = raw.match(/Windows NT ([\d.]+)/i);
if (win) systemVersion = win[1];
} else if (/Mac OS X|Macintosh/i.test(raw)) {
systemName = "macOS";
deviceBrand = "Apple";
deviceModel = "Mac";
const mac = raw.match(/Mac OS X ([\d_]+)/i);
if (mac) systemVersion = mac[1].replace(/_/g, ".");
} else if (/Linux/i.test(raw)) {
systemName = "Linux";
}
const devType = [
deviceBrand,
deviceModel,
deviceType
].map((part)=>part.trim()).filter(Boolean).join(" ");
return {
devType: devType || "desktop",
sysType: sysType(raw),
buildID: clean(parseBrowser(raw)) || "web",
deviceBrand,
deviceModel,
systemName,
systemVersion
};
}
function xUserAgent(ua, extra = {}) {
const info = parseDeviceFromUA(ua);
return [
extra.devID ? `DevID=${clean(extra.devID)}` : "",
`DevType=${clean(info.devType)}`,
`SysType=${info.sysType}`,
`Ver=${clean(APP_VER)}`,
`BuildID=${clean(info.buildID) || "web"}`,
`device_brand=${clean(info.deviceBrand)}`,
`device_model=${clean(info.deviceModel)}`,
`system_name=${clean(info.systemName)}`,
`system_version=${clean(info.systemVersion)}`,
`sid=${clean(extra.sid || "")}`
].filter((part)=>part !== "").join(";");
}
function sessionId(source) {
const cookies = new Map((source.get("cookie") || "").split(";").map((value)=>{
const index = value.indexOf("=");
if (index < 0) return [
"",
""
];
return [
value.slice(0, index).trim(),
value.slice(index + 1).trim()
];
}));
const sid = cookies.get("sid");
if (sid) return sid;
const token = cookies.get("_s_token_") || "";
if (token.startsWith("{")) {
try {
return String(JSON.parse(token).sid || "");
} catch {
/* ignore */ }
}
return token;
}
function buildBrowserApiHeaders(devID = "", sid = "") {
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
return {
"X-User-Agent": xUserAgent(ua, {
devID,
sid
})
};
}
function clientIp(source, fallback = "") {
const candidates = [
source.get("x-real-ip"),
source.get("x-forwarded-for")?.split(",")[0],
fallback
];
for (const value of candidates){
const ip = value?.trim() || "";
if (ip && isIP(ip)) return ip;
}
return "";
}
function clientHeaders(source, overrides = {}) {
const result = {};
const ua = (overrides.userAgent || source?.get("user-agent") || "").trim();
if (ua) result["User-Agent"] = ua;
const incomingXua = source?.get("x-user-agent")?.trim() || "";
if (incomingXua) {
result["X-User-Agent"] = incomingXua;
} else if (ua) {
result["X-User-Agent"] = xUserAgent(ua, {
sid: source ? sessionId(source) : ""
});
} else {
Object.assign(result, buildBrowserApiHeaders(overrides.devID || "web-ssr"));
}
const ip = overrides.clientIp || (source ? clientIp(source) : "");
if (ip) result["X-Real-IP"] = ip;
return result;
}
}),
"[project]/src/lib/api/config.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"API_BASE_URL",
()=>API_BASE_URL,
"getServerApiBaseUrl",
()=>getServerApiBaseUrl,
"pointsAtThisServer",
()=>pointsAtThisServer
]);
/**
* 浏览器接口根地址。
* 留空时走同域 `/api/*`,由服务端转到 API_PROXY_TARGET。
*/ const DEFAULT_UPSTREAM = "https://webhgbapi.mfcg.me";
const raw = ("TURBOPACK compile-time value", "");
const API_BASE_URL = (raw ?? "").replace(/\/$/, "");
function pointsAtThisServer(base) {
try {
const url = new URL(base);
const loopback = url.hostname === "127.0.0.1" || url.hostname === "localhost" || url.hostname === "::1";
if (!loopback) return false;
const port = url.port || (url.protocol === "https:" ? "443" : "80");
const listen = process.env.PORT?.trim();
return !listen || port === listen;
} catch {
return false;
}
}
function getServerApiBaseUrl() {
const proxy = process.env.API_PROXY_TARGET?.trim().replace(/\/$/, "");
const configured = proxy || raw?.trim().replace(/\/$/, "") || "";
if (configured && !pointsAtThisServer(configured)) return configured;
return DEFAULT_UPSTREAM;
}
}),
"[project]/src/lib/api/server-fetch.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"isRequestAborted",
()=>isRequestAborted,
"serverFetchJson",
()=>serverFetchJson
]);
var __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$dns__$5b$external$5d$__$28$node$3a$dns$2c$__cjs$29$__ = __turbopack_context__.i("[externals]/node:dns [external] (node:dns, cjs)");
var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$headers$2e$js__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/node_modules/next/headers.js [app-route] (ecmascript)");
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/client-headers.ts [app-route] (ecmascript)");
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$config$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/config.ts [app-route] (ecmascript)");
;
;
;
;
(0, __TURBOPACK__imported__module__$5b$externals$5d2f$node$3a$dns__$5b$external$5d$__$28$node$3a$dns$2c$__cjs$29$__["setDefaultResultOrder"])("ipv4first");
const MAX_ATTEMPTS = 3;
const RETRY_BASE_MS = 400;
function networkErrorCode(error) {
if (!(error instanceof Error)) return "";
const withCode = error;
if (withCode.code) return withCode.code;
if (withCode.cause?.code) return withCode.cause.code;
const nested = withCode.cause?.errors?.[0];
return nested?.code || "";
}
function isRequestAborted(error) {
if (!(error instanceof Error)) return false;
if (error.name === "TimeoutError") return false;
return error.name === "AbortError" || /this operation was aborted/i.test(error.message);
}
function isRetryableNetworkError(error) {
if (!(error instanceof Error)) return false;
if (isRequestAborted(error)) return false;
if (error.name === "TimeoutError" || error.name === "AbortError") return true;
const message = error.message.toLowerCase();
if (message.includes("fetch failed") || message.includes("network")) return true;
const code = networkErrorCode(error);
if (/ENETUNREACH|ECONNRESET|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|UND_ERR/i.test(code)) {
return true;
}
const cause = error.cause;
if (Array.isArray(cause?.errors)) return true;
return false;
}
function wait(ms) {
return new Promise((resolve)=>setTimeout(resolve, ms));
}
function networkMessage(error) {
const code = networkErrorCode(error);
const message = error instanceof Error ? error.message : "";
if (error instanceof Error && (error.name === "TimeoutError" || /aborted due to timeout/i.test(message))) {
return "接口暂时不可用(服务端网络超时)";
}
if (/ETIMEDOUT|ENETUNREACH|ECONNREFUSED|fetch failed/i.test(`${code} ${message}`)) {
return "接口暂时不可用(服务端网络超时)";
}
return message || "请求失败";
}
async function requestIdentityHeaders() {
try {
return (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["clientHeaders"])(await (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$headers$2e$js__$5b$app$2d$route$5d$__$28$ecmascript$29$__["headers"])());
} catch {
return (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["buildBrowserApiHeaders"])("web-ssr");
}
}
async function serverFetchJson(pathWithQuery, options) {
const base = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$config$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["getServerApiBaseUrl"])();
const url = `${base}${pathWithQuery}`;
const timeoutMs = options?.timeoutMs ?? 12_000;
const maxAttempts = options?.maxAttempts ?? MAX_ATTEMPTS;
const identity = await requestIdentityHeaders();
const nextInit = options?.revalidate !== undefined || options?.tags?.length ? {
...options.revalidate !== undefined ? {
revalidate: options.revalidate
} : {},
...options.tags?.length ? {
tags: options.tags
} : {}
} : undefined;
let lastError;
for(let attempt = 1; attempt <= maxAttempts; attempt++){
try {
const response = await fetch(url, {
headers: {
Accept: "application/json",
...identity,
...options?.headers
},
signal: AbortSignal.timeout(timeoutMs),
...nextInit ? {
next: nextInit
} : {}
});
const text = await response.text();
let payload = null;
try {
payload = text ? JSON.parse(text) : null;
} catch {
payload = null;
}
if (!payload || typeof payload.code !== "number") {
throw new Error(response.ok ? "接口响应格式异常" : `接口暂时不可用 (${response.status})`);
}
if (!response.ok || payload.code !== 200) {
throw new Error(payload.tip || payload.msg || "请求失败");
}
return payload.data;
} catch (error) {
lastError = error;
if (attempt >= maxAttempts || !isRetryableNetworkError(error)) break;
await wait(RETRY_BASE_MS * attempt);
}
}
throw new Error(networkMessage(lastError));
}
}),
]})(),
"[externals]/crypto [external] (crypto, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("crypto", () => require("crypto"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/@opentelemetry/api [external] (next/dist/compiled/@opentelemetry/api, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/@opentelemetry/api", () => require("next/dist/compiled/@opentelemetry/api"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/next-server/app-page-turbo.runtime.dev.js [external] (next/dist/compiled/next-server/app-page-turbo.runtime.dev.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/next-server/app-page-turbo.runtime.dev.js", () => require("next/dist/compiled/next-server/app-page-turbo.runtime.dev.js"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/next-server/app-route-turbo.runtime.dev.js [external] (next/dist/compiled/next-server/app-route-turbo.runtime.dev.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/next-server/app-route-turbo.runtime.dev.js", () => require("next/dist/compiled/next-server/app-route-turbo.runtime.dev.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/action-async-storage.external.js [external] (next/dist/server/app-render/action-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/action-async-storage.external.js", () => require("next/dist/server/app-render/action-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/after-task-async-storage.external.js [external] (next/dist/server/app-render/after-task-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/after-task-async-storage.external.js", () => require("next/dist/server/app-render/after-task-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/work-async-storage.external.js [external] (next/dist/server/app-render/work-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/work-async-storage.external.js", () => require("next/dist/server/app-render/work-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/work-unit-async-storage.external.js [external] (next/dist/server/app-render/work-unit-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/work-unit-async-storage.external.js", () => require("next/dist/server/app-render/work-unit-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/runtime-reacts.external.js [external] (next/dist/server/runtime-reacts.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/runtime-reacts.external.js", () => require("next/dist/server/runtime-reacts.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/shared/lib/no-fallback-error.external.js [external] (next/dist/shared/lib/no-fallback-error.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/shared/lib/no-fallback-error.external.js", () => require("next/dist/shared/lib/no-fallback-error.external.js"));
module.exports = mod;
}),
"[externals]/node:dns [external] (node:dns, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("node:dns", () => require("node:dns"));
module.exports = mod;
}),
"[externals]/node:stream [external] (node:stream, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("node:stream", () => require("node:stream"));
module.exports = mod;
}),
"[externals]/path [external] (path, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("path", () => require("path"));
module.exports = mod;
}),
];
//# sourceMappingURL=%5Broot-of-the-server%5D__0a8xmgadn_opt._.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,625 @@
module.exports = [
(()=>{"use strict";return[
"[project]/src/app/h5/m3u8/[...path]/route.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"GET",
()=>GET
]);
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$media$2f$proxy$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/media/proxy.ts [app-route] (ecmascript)");
;
function GET(request) {
return (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$media$2f$proxy$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["proxyHls"])(request);
}
}),
"[project]/src/lib/api/client-headers.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"buildBrowserApiHeaders",
()=>buildBrowserApiHeaders,
"clientHeaders",
()=>clientHeaders,
"clientIp",
()=>clientIp
]);
const APP_VER = ("TURBOPACK compile-time value", "1.0.0")?.trim() || "1.0.0";
function clean(value) {
return value.replace(/[^\x20-\x7E]|[;=]/g, " ").trim();
}
/** 不依赖 node:net,避免被浏览器端打包。 */ function isIP(value) {
if (/^(?:\d{1,3}\.){3}\d{1,3}$/.test(value)) {
return value.split(".").every((part)=>{
const n = Number(part);
return String(n) === part && n >= 0 && n <= 255;
});
}
// 宽松校验 IPv6,够用来转发 X-Real-IP。
return value.includes(":") && /^[0-9a-fA-F:.]+$/.test(value);
}
function sysType(ua) {
const value = ua.toLowerCase();
if (value.includes("android")) return "h5_android";
if (value.includes("iphone") || value.includes("ipad") || value.includes("ipod")) return "h5_ios";
return "h5_pc";
}
function guessAndroidBrand(model, ua) {
const value = `${model} ${ua}`;
const brands = [
[
/Build\/HONOR|\bHONOR\b/i,
"Honor"
],
[
/Build\/HUAWEI|HUAWEI|HW-/i,
"Huawei"
],
[
/SM-|samsung|Galaxy/i,
"Samsung"
],
[
/Pixel/i,
"Google"
],
[
/Redmi|POCO|XiaoMi|\bMi\b/i,
"Xiaomi"
],
[
/OPPO|\bCPH\d{3,4}/i,
"OPPO"
],
[
/vivo|\bV\d{4}/i,
"vivo"
],
[
/OnePlus|ONEPLUS/i,
"OnePlus"
],
[
/realme|\bRMX\d{3,4}/i,
"realme"
]
];
return brands.find(([pattern])=>pattern.test(value))?.[1] || "";
}
function parseBrowser(ua) {
const edge = ua.match(/Edg\/([\d.]+)/i);
if (edge) return `Edge ${edge[1]}`;
const opera = ua.match(/(?:OPR|Opera)\/([\d.]+)/i);
if (opera) return `Opera ${opera[1]}`;
const chrome = ua.match(/Chrome\/([\d.]+)/i);
if (chrome && !/Edg\//i.test(ua)) return `Chrome ${chrome[1]}`;
const safari = ua.match(/Version\/([\d.]+).*Safari/i);
if (safari) return `Safari ${safari[1]}`;
const firefox = ua.match(/Firefox\/([\d.]+)/i);
if (firefox) return `Firefox ${firefox[1]}`;
const ie = ua.match(/(?:MSIE\s|Trident.*rv:)([\d.]+)/i);
if (ie) return `IE ${ie[1]}`;
return "";
}
/** 从浏览器 User-Agent 解析设备公共字段,口径对齐 jha-1040 useragent.ParseDeviceFromUA。 */ function parseDeviceFromUA(ua) {
const raw = ua.trim();
let deviceBrand = "";
let deviceModel = "";
let deviceType = "desktop";
let systemName = "Other";
let systemVersion = "";
if (/iPhone|iPad|iPod/i.test(raw)) {
systemName = "iOS";
deviceBrand = "Apple";
const ios = raw.match(/OS (\d+[_\d]*) like Mac OS X/i);
if (ios) systemVersion = ios[1].replace(/_/g, ".");
if (/iPad/i.test(raw)) {
deviceModel = "iPad";
deviceType = "tablet";
} else if (/iPod/i.test(raw)) {
deviceModel = "iPod";
deviceType = "mobile";
} else {
deviceModel = "iPhone";
deviceType = "mobile";
}
} else if (/Android/i.test(raw)) {
systemName = "Android";
const version = raw.match(/Android ([\d.]+)/i);
if (version) systemVersion = version[1];
const model = raw.match(/Android\s+[\d.]+;\s*([^;)]+?)(?:\s+Build\/|\))/i);
if (model?.[1]) deviceModel = model[1].trim();
deviceBrand = guessAndroidBrand(deviceModel, raw);
deviceType = /Mobile/i.test(raw) ? "mobile" : "tablet";
} else if (/Windows/i.test(raw)) {
systemName = "Windows";
const win = raw.match(/Windows NT ([\d.]+)/i);
if (win) systemVersion = win[1];
} else if (/Mac OS X|Macintosh/i.test(raw)) {
systemName = "macOS";
deviceBrand = "Apple";
deviceModel = "Mac";
const mac = raw.match(/Mac OS X ([\d_]+)/i);
if (mac) systemVersion = mac[1].replace(/_/g, ".");
} else if (/Linux/i.test(raw)) {
systemName = "Linux";
}
const devType = [
deviceBrand,
deviceModel,
deviceType
].map((part)=>part.trim()).filter(Boolean).join(" ");
return {
devType: devType || "desktop",
sysType: sysType(raw),
buildID: clean(parseBrowser(raw)) || "web",
deviceBrand,
deviceModel,
systemName,
systemVersion
};
}
function xUserAgent(ua, extra = {}) {
const info = parseDeviceFromUA(ua);
return [
extra.devID ? `DevID=${clean(extra.devID)}` : "",
`DevType=${clean(info.devType)}`,
`SysType=${info.sysType}`,
`Ver=${clean(APP_VER)}`,
`BuildID=${clean(info.buildID) || "web"}`,
`device_brand=${clean(info.deviceBrand)}`,
`device_model=${clean(info.deviceModel)}`,
`system_name=${clean(info.systemName)}`,
`system_version=${clean(info.systemVersion)}`,
`sid=${clean(extra.sid || "")}`
].filter((part)=>part !== "").join(";");
}
function sessionId(source) {
const cookies = new Map((source.get("cookie") || "").split(";").map((value)=>{
const index = value.indexOf("=");
if (index < 0) return [
"",
""
];
return [
value.slice(0, index).trim(),
value.slice(index + 1).trim()
];
}));
const sid = cookies.get("sid");
if (sid) return sid;
const token = cookies.get("_s_token_") || "";
if (token.startsWith("{")) {
try {
return String(JSON.parse(token).sid || "");
} catch {
/* ignore */ }
}
return token;
}
function buildBrowserApiHeaders(devID = "", sid = "") {
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
return {
"X-User-Agent": xUserAgent(ua, {
devID,
sid
})
};
}
function clientIp(source, fallback = "") {
const candidates = [
source.get("x-real-ip"),
source.get("x-forwarded-for")?.split(",")[0],
fallback
];
for (const value of candidates){
const ip = value?.trim() || "";
if (ip && isIP(ip)) return ip;
}
return "";
}
function clientHeaders(source, overrides = {}) {
const result = {};
const ua = (overrides.userAgent || source?.get("user-agent") || "").trim();
if (ua) result["User-Agent"] = ua;
const incomingXua = source?.get("x-user-agent")?.trim() || "";
if (incomingXua) {
result["X-User-Agent"] = incomingXua;
} else if (ua) {
result["X-User-Agent"] = xUserAgent(ua, {
sid: source ? sessionId(source) : ""
});
} else {
Object.assign(result, buildBrowserApiHeaders(overrides.devID || "web-ssr"));
}
const ip = overrides.clientIp || (source ? clientIp(source) : "");
if (ip) result["X-Real-IP"] = ip;
return result;
}
}),
"[project]/src/lib/api/config.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"API_BASE_URL",
()=>API_BASE_URL,
"getServerApiBaseUrl",
()=>getServerApiBaseUrl,
"pointsAtThisServer",
()=>pointsAtThisServer
]);
/**
* 浏览器接口根地址。
* 留空时走同域 `/api/*`,由服务端转到 API_PROXY_TARGET。
*/ const DEFAULT_UPSTREAM = "https://webhgbapi.mfcg.me";
const raw = ("TURBOPACK compile-time value", "");
const API_BASE_URL = (raw ?? "").replace(/\/$/, "");
function pointsAtThisServer(base) {
try {
const url = new URL(base);
const loopback = url.hostname === "127.0.0.1" || url.hostname === "localhost" || url.hostname === "::1";
if (!loopback) return false;
const port = url.port || (url.protocol === "https:" ? "443" : "80");
const listen = process.env.PORT?.trim();
return !listen || port === listen;
} catch {
return false;
}
}
function getServerApiBaseUrl() {
const proxy = process.env.API_PROXY_TARGET?.trim().replace(/\/$/, "");
const configured = proxy || raw?.trim().replace(/\/$/, "") || "";
if (configured && !pointsAtThisServer(configured)) return configured;
return DEFAULT_UPSTREAM;
}
}),
"[project]/src/lib/media/proxy.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"proxyHls",
()=>proxyHls,
"proxyKey",
()=>proxyKey,
"stripEnkeySlash",
()=>stripEnkeySlash
]);
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/client-headers.ts [app-route] (ecmascript)");
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$config$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/config.ts [app-route] (ecmascript)");
;
;
const FORWARD_HEADERS = [
"range",
"if-range",
"accept",
"cookie"
];
/** 正式服 app;H5 自指时代理会 508,密钥/媒资回退到这里。 */ const DEFAULT_MEDIA_API = "http://139.162.49.252:21036";
/** config/info.mediaAppUsCdn;Go 未配 cdnDomain 时用它拉原始 m3u8 / 分片。 */ const DEFAULT_MEDIA_CDN = "https://dyum53hre43nj.cloudfront.net";
function stripEnkeySlash(playlist) {
return playlist.replace(/enkey\/\?/g, "enkey?");
}
function uniqBases(...values) {
const bases = [];
for (const value of values){
const base = value?.trim().replace(/\/$/, "") || "";
if (base && !bases.includes(base)) bases.push(base);
}
return bases;
}
/**
* 测试/预发常把 API_PROXY_TARGET 写成公开 H5 自身。
* 媒资若再 fetch 该域名会打回本进程,请求挂死(线上表现为 /h5/m3u8 一直转圈)。
*/ function isSelfHostedMediaOrigin(base) {
try {
const host = new URL(base).hostname.toLowerCase();
if (host === "127.0.0.1" || host === "localhost" || host === "::1") return true;
const site = ("TURBOPACK compile-time value", "http://localhost:26149")?.trim();
if (site) {
try {
if (new URL(site).hostname.toLowerCase() === host) return true;
} catch {
/* ignore */ }
}
// 未配 SITE_URL 时,仍避开本项目常见公开 H5 域名
if (host === "huangguoduanju.im" || host === "www.huangguoduanju.im") return true;
return false;
} catch {
return true;
}
}
/** 可安全直连的媒资 API(排除 H5 自指)。 */ function mediaApiOrigin() {
const dedicated = process.env.MEDIA_API_PROXY_TARGET?.trim().replace(/\/$/, "");
if (dedicated && !isSelfHostedMediaOrigin(dedicated)) return dedicated;
const fromApi = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$config$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["getServerApiBaseUrl"])();
if (fromApi && !isSelfHostedMediaOrigin(fromApi)) return fromApi;
return DEFAULT_MEDIA_API;
}
/** 播放列表上游:只走 app 媒资 API,失败再 CDN 改写(绝不打回本站 H5)。 */ function mediaPlaylistBases() {
return uniqBases(mediaApiOrigin());
}
/** 密钥上游:app 缺 m3u8.key 时可额外回退其它 H5(仍排除本站)。 */ function mediaKeyBases() {
const extras = (process.env.MEDIA_KEY_FALLBACK_ORIGINS || // app 缺 m3u8.key 时的临时回退;与 config/*.env 中 MEDIA_KEY_FALLBACK_ORIGINS 一致
"https://91dj-h5.80sygtm.com").split(",").map((value)=>value.trim().replace(/\/$/, "")).filter((value)=>value && !isSelfHostedMediaOrigin(value));
return uniqBases(mediaApiOrigin(), ...extras);
}
function mediaCdnOrigin() {
return (process.env.MEDIA_CDN_ORIGIN || DEFAULT_MEDIA_CDN).replace(/\/$/, "");
}
function upstreamUrl(base, pathname, search) {
const target = new URL(base);
target.pathname = pathname;
target.search = search;
return target;
}
function forwardHeaders(request) {
const headers = new Headers();
for (const name of FORWARD_HEADERS){
const value = request.headers.get(name);
if (value) headers.set(name, value);
}
for (const [name, value] of Object.entries((0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["clientHeaders"])(request.headers))){
headers.set(name, value);
}
if (!headers.has("accept")) headers.set("accept", "*/*");
return headers;
}
function noStore(response) {
const headers = new Headers({
"cache-control": "no-store"
});
for (const name of [
"content-type",
"content-length",
"content-range",
"accept-ranges"
]){
const value = response.headers.get(name);
if (value) headers.set(name, value);
}
return headers;
}
function isUnusableUpstream(status, body, contentType) {
if (status === 508) return true;
if (status >= 500) return true;
if (!body.startsWith("{")) return false;
if (!/json/i.test(contentType) && status === 200) return false;
try {
const payload = JSON.parse(body);
const code = payload.code ?? 0;
if (code && code !== 200) return true;
const msg = `${payload.data?.msg || ""} ${payload.msg || ""} ${payload.tip || ""}`;
return /cdnDomain|origDomain|文件服务器|代理回环/i.test(msg);
} catch {
return false;
}
}
function joinUrl(base, ...parts) {
const path = parts.map((part)=>part.replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
return `${base.replace(/\/$/, "")}/${path}`;
}
/** 上游 m3u8 不可用时:从媒资 CDN 拉原始列表,改写密钥与分片为同域可播地址。 */ async function transformPlaylistFromCdn(request) {
const incoming = new URL(request.url);
const rel = incoming.pathname.replace(/^\/h5\/m3u8\/?/i, "").replace(/^\/+/, "");
if (!rel) return new Response("缺少媒资路径", {
status: 400,
headers: {
"cache-control": "no-store"
}
});
const cdn = mediaCdnOrigin();
const rawUrl = joinUrl(cdn, rel.split("?")[0]);
try {
const response = await fetch(rawUrl, {
headers: {
accept: "*/*",
"user-agent": request.headers.get("user-agent") || "Mozilla/5.0"
},
cache: "no-store",
redirect: "follow",
signal: AbortSignal.timeout(20_000)
});
if (!response.ok) {
return new Response("视频资源请求失败", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
const raw = await response.text();
if (!raw.includes("#EXTM3U")) {
return new Response("视频资源格式错误", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
const keyUri = `/enkey${incoming.search || ""}`;
const dir = rel.includes("/") ? rel.slice(0, rel.lastIndexOf("/")) : "";
const lines = raw.split(/\r?\n/).map((line)=>{
const trimmed = line.trim();
if (!trimmed) return line;
if (trimmed.startsWith("#EXT-X-KEY:")) {
return `#EXT-X-KEY:METHOD=AES-128,URI="${keyUri}"`;
}
if (trimmed.startsWith("#")) return line;
if (/^https?:\/\//i.test(trimmed)) return line;
const segment = trimmed.split("?")[0].replace(/^\/+/, "");
return joinUrl(cdn, dir, segment);
});
return new Response(stripEnkeySlash(lines.join("\n")), {
status: 200,
headers: {
"cache-control": "no-store",
"content-type": "application/vnd.apple.mpegurl"
}
});
} catch {
return new Response("视频资源请求失败", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
}
async function proxyKey(request, pathname) {
const incoming = new URL(request.url);
const keyHeaders = new Headers({
accept: "*/*"
});
const ua = request.headers.get("user-agent");
if (ua) keyHeaders.set("user-agent", ua);
for (const [name, value] of Object.entries((0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["clientHeaders"])(request.headers))){
if (name === "User-Agent" || name === "X-User-Agent" || name === "X-Real-IP") {
keyHeaders.set(name, value);
}
}
for (const base of mediaKeyBases()){
// 直接打带尾斜杠路径,避免 301 在部分运行时丢 query
const pathWithSlash = pathname.endsWith("/") ? pathname : `${pathname}/`;
const candidates = [
pathWithSlash,
pathname
];
let gotKey = false;
for (const path of candidates){
const target = upstreamUrl(base, path, incoming.search);
try {
const response = await fetch(target.href, {
headers: keyHeaders,
cache: "no-store",
redirect: "follow",
signal: AbortSignal.timeout(15_000)
});
const type = response.headers.get("content-type") || "";
const buffer = await response.arrayBuffer();
if (response.ok && buffer.byteLength > 0 && !/json/i.test(type) && response.status !== 508) {
gotKey = true;
return new Response(buffer, {
status: 200,
headers: {
"cache-control": "no-store",
"content-type": type || "application/octet-stream"
}
});
}
const text = new TextDecoder().decode(buffer);
if (!isUnusableUpstream(response.status, text, type) && /json/i.test(type)) {
// 明确业务错误且非「可换源」时仍试下一个源
}
} catch {
/* try next path / base */ }
}
if (gotKey) break;
}
return new Response("视频密钥暂不可用", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
async function proxyHls(request) {
const incoming = new URL(request.url);
for (const base of mediaPlaylistBases()){
const target = upstreamUrl(base, incoming.pathname, incoming.search);
try {
const response = await fetch(target, {
headers: forwardHeaders(request),
cache: "no-store",
redirect: "follow",
signal: AbortSignal.timeout(20_000)
});
const type = response.headers.get("content-type") || "";
const playlist = /\.m3u8$/i.test(incoming.pathname) || /mpegurl|m3u8/i.test(type);
if (!playlist) {
if (response.status === 508) continue;
return new Response(response.body, {
status: response.status,
headers: noStore(response)
});
}
const text = await response.text();
if (isUnusableUpstream(response.status, text, type) || !text.includes("#EXTM3U")) {
continue;
}
const headers = noStore(response);
headers.delete("content-length");
if (!headers.has("content-type")) headers.set("content-type", "application/vnd.apple.mpegurl");
return new Response(stripEnkeySlash(text), {
status: response.status,
headers
});
} catch {
/* try next base / CDN fallback */ }
}
return transformPlaylistFromCdn(request);
}
}),
]})(),
"[externals]/crypto [external] (crypto, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("crypto", () => require("crypto"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/@opentelemetry/api [external] (next/dist/compiled/@opentelemetry/api, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/@opentelemetry/api", () => require("next/dist/compiled/@opentelemetry/api"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/next-server/app-page-turbo.runtime.dev.js [external] (next/dist/compiled/next-server/app-page-turbo.runtime.dev.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/next-server/app-page-turbo.runtime.dev.js", () => require("next/dist/compiled/next-server/app-page-turbo.runtime.dev.js"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/next-server/app-route-turbo.runtime.dev.js [external] (next/dist/compiled/next-server/app-route-turbo.runtime.dev.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/next-server/app-route-turbo.runtime.dev.js", () => require("next/dist/compiled/next-server/app-route-turbo.runtime.dev.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/work-async-storage.external.js [external] (next/dist/server/app-render/work-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/work-async-storage.external.js", () => require("next/dist/server/app-render/work-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/work-unit-async-storage.external.js [external] (next/dist/server/app-render/work-unit-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/work-unit-async-storage.external.js", () => require("next/dist/server/app-render/work-unit-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/runtime-reacts.external.js [external] (next/dist/server/runtime-reacts.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/runtime-reacts.external.js", () => require("next/dist/server/runtime-reacts.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/shared/lib/no-fallback-error.external.js [external] (next/dist/shared/lib/no-fallback-error.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/shared/lib/no-fallback-error.external.js", () => require("next/dist/shared/lib/no-fallback-error.external.js"));
module.exports = mod;
}),
"[externals]/node:stream [external] (node:stream, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("node:stream", () => require("node:stream"));
module.exports = mod;
}),
"[externals]/path [external] (path, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("path", () => require("path"));
module.exports = mod;
}),
];
//# sourceMappingURL=%5Broot-of-the-server%5D__1dpw5ck2p-gjg._.js.map
File diff suppressed because one or more lines are too long
@@ -259,7 +259,7 @@ __turbopack_context__.s([
/**
* 浏览器接口根地址。
* 留空时走同域 `/api/*`,由服务端转到 API_PROXY_TARGET。
*/ const DEFAULT_UPSTREAM = "https://sgdj-h5.80sygtm.com";
*/ const DEFAULT_UPSTREAM = "https://webhgbapi.mfcg.me";
const raw = ("TURBOPACK compile-time value", "");
const API_BASE_URL = (raw ?? "").replace(/\/$/, "");
function pointsAtThisServer(base) {
File diff suppressed because one or more lines are too long
@@ -0,0 +1,625 @@
module.exports = [
(()=>{"use strict";return[
"[project]/src/app/enkey/route.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"GET",
()=>GET
]);
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$media$2f$proxy$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/media/proxy.ts [app-route] (ecmascript)");
;
function GET(request) {
return (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$media$2f$proxy$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["proxyKey"])(request, "/enkey");
}
}),
"[project]/src/lib/api/client-headers.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"buildBrowserApiHeaders",
()=>buildBrowserApiHeaders,
"clientHeaders",
()=>clientHeaders,
"clientIp",
()=>clientIp
]);
const APP_VER = ("TURBOPACK compile-time value", "1.0.0")?.trim() || "1.0.0";
function clean(value) {
return value.replace(/[^\x20-\x7E]|[;=]/g, " ").trim();
}
/** 不依赖 node:net,避免被浏览器端打包。 */ function isIP(value) {
if (/^(?:\d{1,3}\.){3}\d{1,3}$/.test(value)) {
return value.split(".").every((part)=>{
const n = Number(part);
return String(n) === part && n >= 0 && n <= 255;
});
}
// 宽松校验 IPv6,够用来转发 X-Real-IP。
return value.includes(":") && /^[0-9a-fA-F:.]+$/.test(value);
}
function sysType(ua) {
const value = ua.toLowerCase();
if (value.includes("android")) return "h5_android";
if (value.includes("iphone") || value.includes("ipad") || value.includes("ipod")) return "h5_ios";
return "h5_pc";
}
function guessAndroidBrand(model, ua) {
const value = `${model} ${ua}`;
const brands = [
[
/Build\/HONOR|\bHONOR\b/i,
"Honor"
],
[
/Build\/HUAWEI|HUAWEI|HW-/i,
"Huawei"
],
[
/SM-|samsung|Galaxy/i,
"Samsung"
],
[
/Pixel/i,
"Google"
],
[
/Redmi|POCO|XiaoMi|\bMi\b/i,
"Xiaomi"
],
[
/OPPO|\bCPH\d{3,4}/i,
"OPPO"
],
[
/vivo|\bV\d{4}/i,
"vivo"
],
[
/OnePlus|ONEPLUS/i,
"OnePlus"
],
[
/realme|\bRMX\d{3,4}/i,
"realme"
]
];
return brands.find(([pattern])=>pattern.test(value))?.[1] || "";
}
function parseBrowser(ua) {
const edge = ua.match(/Edg\/([\d.]+)/i);
if (edge) return `Edge ${edge[1]}`;
const opera = ua.match(/(?:OPR|Opera)\/([\d.]+)/i);
if (opera) return `Opera ${opera[1]}`;
const chrome = ua.match(/Chrome\/([\d.]+)/i);
if (chrome && !/Edg\//i.test(ua)) return `Chrome ${chrome[1]}`;
const safari = ua.match(/Version\/([\d.]+).*Safari/i);
if (safari) return `Safari ${safari[1]}`;
const firefox = ua.match(/Firefox\/([\d.]+)/i);
if (firefox) return `Firefox ${firefox[1]}`;
const ie = ua.match(/(?:MSIE\s|Trident.*rv:)([\d.]+)/i);
if (ie) return `IE ${ie[1]}`;
return "";
}
/** 从浏览器 User-Agent 解析设备公共字段,口径对齐 jha-1040 useragent.ParseDeviceFromUA。 */ function parseDeviceFromUA(ua) {
const raw = ua.trim();
let deviceBrand = "";
let deviceModel = "";
let deviceType = "desktop";
let systemName = "Other";
let systemVersion = "";
if (/iPhone|iPad|iPod/i.test(raw)) {
systemName = "iOS";
deviceBrand = "Apple";
const ios = raw.match(/OS (\d+[_\d]*) like Mac OS X/i);
if (ios) systemVersion = ios[1].replace(/_/g, ".");
if (/iPad/i.test(raw)) {
deviceModel = "iPad";
deviceType = "tablet";
} else if (/iPod/i.test(raw)) {
deviceModel = "iPod";
deviceType = "mobile";
} else {
deviceModel = "iPhone";
deviceType = "mobile";
}
} else if (/Android/i.test(raw)) {
systemName = "Android";
const version = raw.match(/Android ([\d.]+)/i);
if (version) systemVersion = version[1];
const model = raw.match(/Android\s+[\d.]+;\s*([^;)]+?)(?:\s+Build\/|\))/i);
if (model?.[1]) deviceModel = model[1].trim();
deviceBrand = guessAndroidBrand(deviceModel, raw);
deviceType = /Mobile/i.test(raw) ? "mobile" : "tablet";
} else if (/Windows/i.test(raw)) {
systemName = "Windows";
const win = raw.match(/Windows NT ([\d.]+)/i);
if (win) systemVersion = win[1];
} else if (/Mac OS X|Macintosh/i.test(raw)) {
systemName = "macOS";
deviceBrand = "Apple";
deviceModel = "Mac";
const mac = raw.match(/Mac OS X ([\d_]+)/i);
if (mac) systemVersion = mac[1].replace(/_/g, ".");
} else if (/Linux/i.test(raw)) {
systemName = "Linux";
}
const devType = [
deviceBrand,
deviceModel,
deviceType
].map((part)=>part.trim()).filter(Boolean).join(" ");
return {
devType: devType || "desktop",
sysType: sysType(raw),
buildID: clean(parseBrowser(raw)) || "web",
deviceBrand,
deviceModel,
systemName,
systemVersion
};
}
function xUserAgent(ua, extra = {}) {
const info = parseDeviceFromUA(ua);
return [
extra.devID ? `DevID=${clean(extra.devID)}` : "",
`DevType=${clean(info.devType)}`,
`SysType=${info.sysType}`,
`Ver=${clean(APP_VER)}`,
`BuildID=${clean(info.buildID) || "web"}`,
`device_brand=${clean(info.deviceBrand)}`,
`device_model=${clean(info.deviceModel)}`,
`system_name=${clean(info.systemName)}`,
`system_version=${clean(info.systemVersion)}`,
`sid=${clean(extra.sid || "")}`
].filter((part)=>part !== "").join(";");
}
function sessionId(source) {
const cookies = new Map((source.get("cookie") || "").split(";").map((value)=>{
const index = value.indexOf("=");
if (index < 0) return [
"",
""
];
return [
value.slice(0, index).trim(),
value.slice(index + 1).trim()
];
}));
const sid = cookies.get("sid");
if (sid) return sid;
const token = cookies.get("_s_token_") || "";
if (token.startsWith("{")) {
try {
return String(JSON.parse(token).sid || "");
} catch {
/* ignore */ }
}
return token;
}
function buildBrowserApiHeaders(devID = "", sid = "") {
const ua = typeof navigator !== "undefined" ? navigator.userAgent : "";
return {
"X-User-Agent": xUserAgent(ua, {
devID,
sid
})
};
}
function clientIp(source, fallback = "") {
const candidates = [
source.get("x-real-ip"),
source.get("x-forwarded-for")?.split(",")[0],
fallback
];
for (const value of candidates){
const ip = value?.trim() || "";
if (ip && isIP(ip)) return ip;
}
return "";
}
function clientHeaders(source, overrides = {}) {
const result = {};
const ua = (overrides.userAgent || source?.get("user-agent") || "").trim();
if (ua) result["User-Agent"] = ua;
const incomingXua = source?.get("x-user-agent")?.trim() || "";
if (incomingXua) {
result["X-User-Agent"] = incomingXua;
} else if (ua) {
result["X-User-Agent"] = xUserAgent(ua, {
sid: source ? sessionId(source) : ""
});
} else {
Object.assign(result, buildBrowserApiHeaders(overrides.devID || "web-ssr"));
}
const ip = overrides.clientIp || (source ? clientIp(source) : "");
if (ip) result["X-Real-IP"] = ip;
return result;
}
}),
"[project]/src/lib/api/config.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"API_BASE_URL",
()=>API_BASE_URL,
"getServerApiBaseUrl",
()=>getServerApiBaseUrl,
"pointsAtThisServer",
()=>pointsAtThisServer
]);
/**
* 浏览器接口根地址。
* 留空时走同域 `/api/*`,由服务端转到 API_PROXY_TARGET。
*/ const DEFAULT_UPSTREAM = "https://webhgbapi.mfcg.me";
const raw = ("TURBOPACK compile-time value", "");
const API_BASE_URL = (raw ?? "").replace(/\/$/, "");
function pointsAtThisServer(base) {
try {
const url = new URL(base);
const loopback = url.hostname === "127.0.0.1" || url.hostname === "localhost" || url.hostname === "::1";
if (!loopback) return false;
const port = url.port || (url.protocol === "https:" ? "443" : "80");
const listen = process.env.PORT?.trim();
return !listen || port === listen;
} catch {
return false;
}
}
function getServerApiBaseUrl() {
const proxy = process.env.API_PROXY_TARGET?.trim().replace(/\/$/, "");
const configured = proxy || raw?.trim().replace(/\/$/, "") || "";
if (configured && !pointsAtThisServer(configured)) return configured;
return DEFAULT_UPSTREAM;
}
}),
"[project]/src/lib/media/proxy.ts [app-route] (ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([
"proxyHls",
()=>proxyHls,
"proxyKey",
()=>proxyKey,
"stripEnkeySlash",
()=>stripEnkeySlash
]);
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/client-headers.ts [app-route] (ecmascript)");
var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$config$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/api/config.ts [app-route] (ecmascript)");
;
;
const FORWARD_HEADERS = [
"range",
"if-range",
"accept",
"cookie"
];
/** 正式服 app;H5 自指时代理会 508,密钥/媒资回退到这里。 */ const DEFAULT_MEDIA_API = "http://139.162.49.252:21036";
/** config/info.mediaAppUsCdn;Go 未配 cdnDomain 时用它拉原始 m3u8 / 分片。 */ const DEFAULT_MEDIA_CDN = "https://dyum53hre43nj.cloudfront.net";
function stripEnkeySlash(playlist) {
return playlist.replace(/enkey\/\?/g, "enkey?");
}
function uniqBases(...values) {
const bases = [];
for (const value of values){
const base = value?.trim().replace(/\/$/, "") || "";
if (base && !bases.includes(base)) bases.push(base);
}
return bases;
}
/**
* 测试/预发常把 API_PROXY_TARGET 写成公开 H5 自身。
* 媒资若再 fetch 该域名会打回本进程,请求挂死(线上表现为 /h5/m3u8 一直转圈)。
*/ function isSelfHostedMediaOrigin(base) {
try {
const host = new URL(base).hostname.toLowerCase();
if (host === "127.0.0.1" || host === "localhost" || host === "::1") return true;
const site = ("TURBOPACK compile-time value", "http://localhost:26149")?.trim();
if (site) {
try {
if (new URL(site).hostname.toLowerCase() === host) return true;
} catch {
/* ignore */ }
}
// 未配 SITE_URL 时,仍避开本项目常见公开 H5 域名
if (host === "huangguoduanju.im" || host === "www.huangguoduanju.im") return true;
return false;
} catch {
return true;
}
}
/** 可安全直连的媒资 API(排除 H5 自指)。 */ function mediaApiOrigin() {
const dedicated = process.env.MEDIA_API_PROXY_TARGET?.trim().replace(/\/$/, "");
if (dedicated && !isSelfHostedMediaOrigin(dedicated)) return dedicated;
const fromApi = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$config$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["getServerApiBaseUrl"])();
if (fromApi && !isSelfHostedMediaOrigin(fromApi)) return fromApi;
return DEFAULT_MEDIA_API;
}
/** 播放列表上游:只走 app 媒资 API,失败再 CDN 改写(绝不打回本站 H5)。 */ function mediaPlaylistBases() {
return uniqBases(mediaApiOrigin());
}
/** 密钥上游:app 缺 m3u8.key 时可额外回退其它 H5(仍排除本站)。 */ function mediaKeyBases() {
const extras = (process.env.MEDIA_KEY_FALLBACK_ORIGINS || // app 缺 m3u8.key 时的临时回退;与 config/*.env 中 MEDIA_KEY_FALLBACK_ORIGINS 一致
"https://91dj-h5.80sygtm.com").split(",").map((value)=>value.trim().replace(/\/$/, "")).filter((value)=>value && !isSelfHostedMediaOrigin(value));
return uniqBases(mediaApiOrigin(), ...extras);
}
function mediaCdnOrigin() {
return (process.env.MEDIA_CDN_ORIGIN || DEFAULT_MEDIA_CDN).replace(/\/$/, "");
}
function upstreamUrl(base, pathname, search) {
const target = new URL(base);
target.pathname = pathname;
target.search = search;
return target;
}
function forwardHeaders(request) {
const headers = new Headers();
for (const name of FORWARD_HEADERS){
const value = request.headers.get(name);
if (value) headers.set(name, value);
}
for (const [name, value] of Object.entries((0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["clientHeaders"])(request.headers))){
headers.set(name, value);
}
if (!headers.has("accept")) headers.set("accept", "*/*");
return headers;
}
function noStore(response) {
const headers = new Headers({
"cache-control": "no-store"
});
for (const name of [
"content-type",
"content-length",
"content-range",
"accept-ranges"
]){
const value = response.headers.get(name);
if (value) headers.set(name, value);
}
return headers;
}
function isUnusableUpstream(status, body, contentType) {
if (status === 508) return true;
if (status >= 500) return true;
if (!body.startsWith("{")) return false;
if (!/json/i.test(contentType) && status === 200) return false;
try {
const payload = JSON.parse(body);
const code = payload.code ?? 0;
if (code && code !== 200) return true;
const msg = `${payload.data?.msg || ""} ${payload.msg || ""} ${payload.tip || ""}`;
return /cdnDomain|origDomain|文件服务器|代理回环/i.test(msg);
} catch {
return false;
}
}
function joinUrl(base, ...parts) {
const path = parts.map((part)=>part.replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
return `${base.replace(/\/$/, "")}/${path}`;
}
/** 上游 m3u8 不可用时:从媒资 CDN 拉原始列表,改写密钥与分片为同域可播地址。 */ async function transformPlaylistFromCdn(request) {
const incoming = new URL(request.url);
const rel = incoming.pathname.replace(/^\/h5\/m3u8\/?/i, "").replace(/^\/+/, "");
if (!rel) return new Response("缺少媒资路径", {
status: 400,
headers: {
"cache-control": "no-store"
}
});
const cdn = mediaCdnOrigin();
const rawUrl = joinUrl(cdn, rel.split("?")[0]);
try {
const response = await fetch(rawUrl, {
headers: {
accept: "*/*",
"user-agent": request.headers.get("user-agent") || "Mozilla/5.0"
},
cache: "no-store",
redirect: "follow",
signal: AbortSignal.timeout(20_000)
});
if (!response.ok) {
return new Response("视频资源请求失败", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
const raw = await response.text();
if (!raw.includes("#EXTM3U")) {
return new Response("视频资源格式错误", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
const keyUri = `/enkey${incoming.search || ""}`;
const dir = rel.includes("/") ? rel.slice(0, rel.lastIndexOf("/")) : "";
const lines = raw.split(/\r?\n/).map((line)=>{
const trimmed = line.trim();
if (!trimmed) return line;
if (trimmed.startsWith("#EXT-X-KEY:")) {
return `#EXT-X-KEY:METHOD=AES-128,URI="${keyUri}"`;
}
if (trimmed.startsWith("#")) return line;
if (/^https?:\/\//i.test(trimmed)) return line;
const segment = trimmed.split("?")[0].replace(/^\/+/, "");
return joinUrl(cdn, dir, segment);
});
return new Response(stripEnkeySlash(lines.join("\n")), {
status: 200,
headers: {
"cache-control": "no-store",
"content-type": "application/vnd.apple.mpegurl"
}
});
} catch {
return new Response("视频资源请求失败", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
}
async function proxyKey(request, pathname) {
const incoming = new URL(request.url);
const keyHeaders = new Headers({
accept: "*/*"
});
const ua = request.headers.get("user-agent");
if (ua) keyHeaders.set("user-agent", ua);
for (const [name, value] of Object.entries((0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$api$2f$client$2d$headers$2e$ts__$5b$app$2d$route$5d$__$28$ecmascript$29$__["clientHeaders"])(request.headers))){
if (name === "User-Agent" || name === "X-User-Agent" || name === "X-Real-IP") {
keyHeaders.set(name, value);
}
}
for (const base of mediaKeyBases()){
// 直接打带尾斜杠路径,避免 301 在部分运行时丢 query
const pathWithSlash = pathname.endsWith("/") ? pathname : `${pathname}/`;
const candidates = [
pathWithSlash,
pathname
];
let gotKey = false;
for (const path of candidates){
const target = upstreamUrl(base, path, incoming.search);
try {
const response = await fetch(target.href, {
headers: keyHeaders,
cache: "no-store",
redirect: "follow",
signal: AbortSignal.timeout(15_000)
});
const type = response.headers.get("content-type") || "";
const buffer = await response.arrayBuffer();
if (response.ok && buffer.byteLength > 0 && !/json/i.test(type) && response.status !== 508) {
gotKey = true;
return new Response(buffer, {
status: 200,
headers: {
"cache-control": "no-store",
"content-type": type || "application/octet-stream"
}
});
}
const text = new TextDecoder().decode(buffer);
if (!isUnusableUpstream(response.status, text, type) && /json/i.test(type)) {
// 明确业务错误且非「可换源」时仍试下一个源
}
} catch {
/* try next path / base */ }
}
if (gotKey) break;
}
return new Response("视频密钥暂不可用", {
status: 502,
headers: {
"cache-control": "no-store"
}
});
}
async function proxyHls(request) {
const incoming = new URL(request.url);
for (const base of mediaPlaylistBases()){
const target = upstreamUrl(base, incoming.pathname, incoming.search);
try {
const response = await fetch(target, {
headers: forwardHeaders(request),
cache: "no-store",
redirect: "follow",
signal: AbortSignal.timeout(20_000)
});
const type = response.headers.get("content-type") || "";
const playlist = /\.m3u8$/i.test(incoming.pathname) || /mpegurl|m3u8/i.test(type);
if (!playlist) {
if (response.status === 508) continue;
return new Response(response.body, {
status: response.status,
headers: noStore(response)
});
}
const text = await response.text();
if (isUnusableUpstream(response.status, text, type) || !text.includes("#EXTM3U")) {
continue;
}
const headers = noStore(response);
headers.delete("content-length");
if (!headers.has("content-type")) headers.set("content-type", "application/vnd.apple.mpegurl");
return new Response(stripEnkeySlash(text), {
status: response.status,
headers
});
} catch {
/* try next base / CDN fallback */ }
}
return transformPlaylistFromCdn(request);
}
}),
]})(),
"[externals]/crypto [external] (crypto, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("crypto", () => require("crypto"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/@opentelemetry/api [external] (next/dist/compiled/@opentelemetry/api, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/@opentelemetry/api", () => require("next/dist/compiled/@opentelemetry/api"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/next-server/app-page-turbo.runtime.dev.js [external] (next/dist/compiled/next-server/app-page-turbo.runtime.dev.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/next-server/app-page-turbo.runtime.dev.js", () => require("next/dist/compiled/next-server/app-page-turbo.runtime.dev.js"));
module.exports = mod;
}),
"[externals]/next/dist/compiled/next-server/app-route-turbo.runtime.dev.js [external] (next/dist/compiled/next-server/app-route-turbo.runtime.dev.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/compiled/next-server/app-route-turbo.runtime.dev.js", () => require("next/dist/compiled/next-server/app-route-turbo.runtime.dev.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/work-async-storage.external.js [external] (next/dist/server/app-render/work-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/work-async-storage.external.js", () => require("next/dist/server/app-render/work-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/app-render/work-unit-async-storage.external.js [external] (next/dist/server/app-render/work-unit-async-storage.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/app-render/work-unit-async-storage.external.js", () => require("next/dist/server/app-render/work-unit-async-storage.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/server/runtime-reacts.external.js [external] (next/dist/server/runtime-reacts.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/server/runtime-reacts.external.js", () => require("next/dist/server/runtime-reacts.external.js"));
module.exports = mod;
}),
"[externals]/next/dist/shared/lib/no-fallback-error.external.js [external] (next/dist/shared/lib/no-fallback-error.external.js, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("next/dist/shared/lib/no-fallback-error.external.js", () => require("next/dist/shared/lib/no-fallback-error.external.js"));
module.exports = mod;
}),
"[externals]/node:stream [external] (node:stream, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("node:stream", () => require("node:stream"));
module.exports = mod;
}),
"[externals]/path [external] (path, cjs)", ((__turbopack_context__, module, exports) => {
var mod = __turbopack_context__.x("path", () => require("path"));
module.exports = mod;
}),
];
//# sourceMappingURL=%5Broot-of-the-server%5D__1y_dny-cu_otu._.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
module.exports = [
"[project]/.next-internal/server/app/enkey/route/actions.js [app-rsc] (server actions loader, ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([]);
}),
];
//# sourceMappingURL=_next-internal_server_app_enkey_route_actions_0jqwrpk0x1_pi.js.map
@@ -0,0 +1,6 @@
{
"version": 3,
"sources": [],
"sections": [
{"offset": {"line": 4, "column": 0}, "map": {"version":3,"sources":[],"names":[],"mappings":""}}]
}
@@ -0,0 +1,9 @@
module.exports = [
"[project]/.next-internal/server/app/h5/chapter-detail/route/actions.js [app-rsc] (server actions loader, ecmascript)", ((__turbopack_context__) => {
"use strict";
__turbopack_context__.s([]);
}),
];
//# sourceMappingURL=_next-internal_server_app_h5_chapter-detail_route_actions_1xc2wcl27dmcm.js.map

Some files were not shown because too many files have changed in this diff Show More