fix: lsky gateway reads links.url + strategy_id support (COS strategy verified end-to-end: https cos url, public access ok)
This commit is contained in:
@@ -19,8 +19,9 @@ services:
|
|||||||
- ../app/server:/app/app-server:ro # 命令层整目录挂载(避免单文件嵌套遮蔽的不可靠行为)
|
- ../app/server:/app/app-server:ro # 命令层整目录挂载(避免单文件嵌套遮蔽的不可靠行为)
|
||||||
environment:
|
environment:
|
||||||
- REGISTER_ENABLED=true
|
- REGISTER_ENABLED=true
|
||||||
# - LSKY_API=https://img.linyux.cn/api/v1 # 兰空图床(对接 COS):填入后附件自动直传对象存储
|
# - LSKY_API=https://img.linyux.cn/api/v1 # 兰空图床(已对接 COS):填入后附件自动直传对象存储
|
||||||
# - LSKY_TOKEN= # 兰空 个人中心 → API 令牌
|
# - LSKY_TOKEN=1|xxxxxxxx # 兰空 个人中心 → API 接口 → 复制 Token
|
||||||
|
# - LSKY_STRATEGY_ID=2 # 存储策略 ID(2=COS 策略)
|
||||||
- INVITE_CODE=please-change-me # 多用户:注册须携带此邀请码(留空则不校验)
|
- INVITE_CODE=please-change-me # 多用户:注册须携带此邀请码(留空则不校验)
|
||||||
- MAX_USERS=20 # 用户数上限,0=不限
|
- MAX_USERS=20 # 用户数上限,0=不限
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -6,9 +6,16 @@ import zlib from 'node:zlib';
|
|||||||
// 图床网关:Lsky Pro(已对接 COS),附件直传对象存储,应用服务器不做搬运工
|
// 图床网关:Lsky Pro(已对接 COS),附件直传对象存储,应用服务器不做搬运工
|
||||||
const LSKY_API = (process.env.LSKY_API || '').replace(/\/$/, '');
|
const LSKY_API = (process.env.LSKY_API || '').replace(/\/$/, '');
|
||||||
const LSKY_TOKEN = process.env.LSKY_TOKEN || '';
|
const LSKY_TOKEN = process.env.LSKY_TOKEN || '';
|
||||||
|
const LSKY_STRATEGY_ID = process.env.LSKY_STRATEGY_ID || ''; // 存储策略(如 2=COS),不填用默认策略
|
||||||
|
function sanitizeImageUrl(u) {
|
||||||
|
// 裸 IP:port 的 http 地址在 HTTPS 站点会被拦截;域名地址统一切 https
|
||||||
|
if (!u) return u;
|
||||||
|
return /^http:\/\/\d+\./.test(u) ? u : u.replace(/^http:\/\//, 'https://');
|
||||||
|
}
|
||||||
async function lskyUpload(buf, fileName, mime) {
|
async function lskyUpload(buf, fileName, mime) {
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('file', new Blob([buf], { type: mime || 'application/octet-stream' }), fileName);
|
fd.append('file', new Blob([buf], { type: mime || 'application/octet-stream' }), fileName);
|
||||||
|
if (LSKY_STRATEGY_ID) fd.append('strategy_id', LSKY_STRATEGY_ID);
|
||||||
const r = await fetch(LSKY_API + '/upload', {
|
const r = await fetch(LSKY_API + '/upload', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { authorization: 'Bearer ' + LSKY_TOKEN, accept: 'application/json' },
|
headers: { authorization: 'Bearer ' + LSKY_TOKEN, accept: 'application/json' },
|
||||||
@@ -16,8 +23,9 @@ async function lskyUpload(buf, fileName, mime) {
|
|||||||
signal: AbortSignal.timeout(60_000),
|
signal: AbortSignal.timeout(60_000),
|
||||||
});
|
});
|
||||||
const j = await r.json().catch(() => null);
|
const j = await r.json().catch(() => null);
|
||||||
if (!j || j.status !== true || !j.data?.url) throw new Error('LSKY ' + r.status + ': ' + (j?.message || 'no url'));
|
const url = sanitizeImageUrl(j?.data?.links?.url || j?.data?.url);
|
||||||
return j.data;
|
if (!j || j.status !== true || !url) throw new Error('LSKY ' + r.status + ': ' + (j?.message || 'no url'));
|
||||||
|
return { url, thumb_url: sanitizeImageUrl(j?.data?.thumbnail_url) || undefined, key: j.data.key };
|
||||||
}
|
}
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|||||||
Reference in New Issue
Block a user