v64:观影豆瓣自动获取 + 海报/多图上传(移动端 API)
端上「记一场」要与网页端同步实现(用户 2026-10-19 六条), 服务端这一半只加**移动端入口**,网页端(index.php 那条路由)一行没动。 - ApiHandler:新增 `/movies/douban` 子路由(action=suggest / action=thumb / 默认抓详情+海报落盘),逻辑与网页端 `movies/douban` 逐条对齐; 新增 `/movies/<id>/poster` 与 `/movies/<id>/photos`(multipart 上传), 字段名与端上一致(poster / photo); 新增 `normalizeFiles()` 把 `photo[]` 的多文件从"按字段竖切"转成"一行一个"; `movieData()` 认 `poster_key` 并**校验形态**(只接受 posters/xxx 形式); features 声明 movies_douban / movie_media(端上可探测老服务端)。 - Douban:新增 `apiThumbUrl()` —— 端上打不到 `index.php?r=...`, 把豆瓣图片代理换成 `/api/v1/...` 形式(拼法只此一处); 联想候选带上**过白名单后**的原始图片地址(未过白名单给空串,不下发 SSRF 跳板)。 - Movie:新增 `setPoster()`(单字段更新 —— 端上是"先建记录再传图"两段式, 用 update() 要拼一份完整草稿,漏一个字段就静默覆盖用户刚填的内容)与 `addPhotos()`(**追加**语义,与网页表单用的 savePhotos() 替换语义并存不混用)。 验证:接口 e2e 57/0(自带豆瓣 mock,离线可跑)· 反向验证 18/0 · 本地全量 e2e 1521/0 · 线上部署 + 站点自检 19 条全过 + `/api/v1/movies/douban` 401(路由通)· ping.features 已含两条新能力
This commit is contained in:
@@ -327,6 +327,14 @@ final class Douban
|
||||
'episode' => $episode,
|
||||
'kind' => self::kindLabel($type, $episode),
|
||||
'thumb' => $img !== '' ? self::thumbProxyUrl($img) : '',
|
||||
/* 🔴 v64:**原始**豆瓣图片地址(已过白名单)也带上。
|
||||
⚠️ 为什么需要它:`thumb` 是**网页路由**的代理地址
|
||||
(`index.php?r=movies/douban&action=thumb&u=…`),
|
||||
手机端拿不到 `index.php?r=` 这种入口 —— 它只会打 `/api/v1/…`。
|
||||
端上要用 `apiThumbUrl()` 把这个原始地址重新拼成 **API 形式**。
|
||||
⚠️ 只有过白名单的才给(没过的一律空串)——
|
||||
否则等于把"服务端代取任意 URL"的 SSRF 跳板下发给客户端。 */
|
||||
'img' => self::imageUrlAllowed($img) ? $img : '',
|
||||
];
|
||||
if (count($items) >= $limit) {
|
||||
break;
|
||||
@@ -381,6 +389,31 @@ final class Douban
|
||||
return 'index.php?r=movies/douban&action=thumb&u=' . rawurlencode($img);
|
||||
}
|
||||
|
||||
/**
|
||||
* 豆瓣图片地址 → **移动端 API** 代理地址(`/api/v1/movies/douban?action=thumb&u=…`)。
|
||||
*
|
||||
* 🔴 v64:端上只能打 `/api/v1/…`,拿不到 `index.php?r=` 那种网页入口
|
||||
* (见 `buildSuggestItems` 里 `img` 字段的说明)。
|
||||
* ⇒ 拼法在这里**定义一次**,端上不自己拼串 ——
|
||||
* 免得以后接口路径一改,两端各改一份还对不齐。
|
||||
*
|
||||
* ⚠️ 与网页路由**同构**(那边是 `movies/douban&action=thumb`):
|
||||
* `Api::dispatch()` 只解析到「资源 / id / 子动作」两层,
|
||||
* `/movies/douban/thumb` 这种三段路径它认不出来(会把 thumb 当子动作丢掉)。
|
||||
* 用 query 传 action 是最省事、也不会跟现有路由打架的形态。
|
||||
*
|
||||
* ⚠️ 返回值是**相对路径**,端上要自己补服务器基址并追加 `&token=`
|
||||
* (`Image()` 加不了请求头,见 `media.php` 的说明)。
|
||||
* 这样同一个地址在"用户换服务器"后仍然有效。
|
||||
*/
|
||||
public static function apiThumbUrl(string $img): string
|
||||
{
|
||||
if (!self::imageUrlAllowed($img)) {
|
||||
return '';
|
||||
}
|
||||
return '/api/v1/movies/douban?action=thumb&u=' . rawurlencode($img);
|
||||
}
|
||||
|
||||
// ---------------- HTTP 与格式识别 ----------------
|
||||
|
||||
private static function searchEndpoint(string $q): string
|
||||
|
||||
Reference in New Issue
Block a user