mirror of
https://github.com/iflytek/skillhub.git
synced 2026-09-17 23:51:11 +00:00
fix(cli): handle 302 redirect in download and fix --skill-version option parsing
- undici does not auto-follow HTTP redirects, manually follow 302/307/308 to MinIO presigned URL before piping response body - Commander.js parses --skill-version as skillVersion (camelCase), not skill-version (kebab-case), fix option access in install and download commands
This commit is contained in:
parent
8c87cc5fe4
commit
af6ebf3058
2 changed files with 26 additions and 7 deletions
|
|
@ -28,18 +28,27 @@ export function registerDownload(program: Command) {
|
|||
const spinner = ora(`Downloading ${skillSlug} from ${namespace}`).start();
|
||||
|
||||
let downloadUrl = `${ApiRoutes.skillDownload.replace("{namespace}", namespace).replace("{slug}", skillSlug)}`;
|
||||
if (opts["skill-version"]) {
|
||||
downloadUrl = `/api/v1/skills/${namespace}/${skillSlug}/versions/${opts["skill-version"]}/download`;
|
||||
if (opts.skillVersion) {
|
||||
downloadUrl = `/api/v1/skills/${namespace}/${skillSlug}/versions/${opts.skillVersion}/download`;
|
||||
} else if (opts.tag) {
|
||||
downloadUrl = `/api/v1/skills/${namespace}/${skillSlug}/tags/${opts.tag}/download`;
|
||||
}
|
||||
|
||||
const { request } = await import("undici");
|
||||
const url = new URL(downloadUrl, config.registry);
|
||||
const { statusCode, body } = await request(url.toString(), {
|
||||
let response = await request(url.toString(), {
|
||||
method: "GET",
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
if (response.statusCode === 302 || response.statusCode === 307 || response.statusCode === 308) {
|
||||
const location = response.headers.location;
|
||||
if (!location) {
|
||||
spinner.fail(`Redirect response has no Location header`);
|
||||
process.exit(1);
|
||||
}
|
||||
response = await request(location, { method: "GET" });
|
||||
}
|
||||
const { statusCode, body } = response;
|
||||
|
||||
if (statusCode >= 400) {
|
||||
spinner.fail(`Download failed: HTTP ${statusCode}`);
|
||||
|
|
|
|||
|
|
@ -240,9 +240,8 @@ async function installFromRegistry(slug: string, opts: Record<string, string | s
|
|||
|
||||
// Present version selection
|
||||
let selectedVersion: string = "latest";
|
||||
if (opts.yes && opts["skill-version"]) {
|
||||
// Non-interactive: use command-line version if provided
|
||||
selectedVersion = opts["skill-version"] as string;
|
||||
if (opts.yes && opts.skillVersion) {
|
||||
selectedVersion = String(opts.skillVersion);
|
||||
} else if (opts.yes && opts.tag) {
|
||||
// Non-interactive: resolve tag to version
|
||||
for (const [vid, tags] of versionTagsMap) {
|
||||
|
|
@ -285,10 +284,21 @@ async function installFromRegistry(slug: string, opts: Record<string, string | s
|
|||
spinner.text = "Downloading";
|
||||
|
||||
const { request } = await import("undici");
|
||||
const { statusCode, body } = await request(downloadUrl, {
|
||||
let response = await request(downloadUrl, {
|
||||
method: "GET",
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
});
|
||||
// undici 不自动跟随 redirect,手动处理 302/307/308
|
||||
if (response.statusCode === 302 || response.statusCode === 307 || response.statusCode === 308) {
|
||||
const location = response.headers.location;
|
||||
if (!location) {
|
||||
spinner.fail(`Redirect response has no Location header`);
|
||||
await rm(tmpDir, { recursive: true, force: true });
|
||||
process.exit(1);
|
||||
}
|
||||
response = await request(location, { method: "GET" });
|
||||
}
|
||||
const { statusCode, body } = response;
|
||||
|
||||
if (statusCode >= 400) {
|
||||
spinner.fail(`Skill not found: ${ns}/${actualSlug}`);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue