fix(cropper): alias the queue's core domain to uc; show server error text

Saving failed with 400 'Unknown domain.' because queue items carry the
legacy domain 'core', which the old bot mapped to 'uc' for a2loft URLs —
my domain validation (added in the review pass) rejected it. The save now
applies the same alias before validating and forwarding.

Also: the client showed axios's generic 'Request failed with status code
400' because the catch destructured error.message; all cropper handlers now
prefer the server's response.data.message (errMessage helper), so the real
reason is visible.

Verified: save with a 'core' item forwards to /identity/uc/profile/picture;
a 400 shows 'Unknown domain.'; 46 tests.
This commit is contained in:
2026-10-01 10:35:02 +01:00
parent 001290a789
commit 645d3d2bc9
3 changed files with 56 additions and 12 deletions
+5 -2
View File
@@ -12,6 +12,8 @@ import { stripPhonePrefix, cropPermission } from './permit.js';
const require = createRequire(import.meta.url);
const QUEUE_NAME = 'id-images';
/** Queue domains that differ from their a2loft code (legacy bot behaviour). */
const DOMAIN_ALIASES = { core: 'uc' };
const BUCKET = 'files';
const REMOVEBG_URL = 'https://removebg.itcass.net/api/removebg';
@@ -348,13 +350,14 @@ export function createCropperRouter(cfg) {
message: { upload_id, domain, agentDeviceHash } = {},
},
} = req.body;
if (!domainCodes.has(domain)) {
const urlDomain = DOMAIN_ALIASES[domain] || domain;
if (!domainCodes.has(urlDomain)) {
return res.status(400).json({ ok: false, message: 'Unknown domain.' });
}
const q = new URLSearchParams({ phone: req.session.phone, otp: req.query.otp });
try {
const r = await fetchImpl(
`${base}/${encodeURIComponent(domain)}/profile/picture?${q.toString()}`,
`${base}/${encodeURIComponent(urlDomain)}/profile/picture?${q.toString()}`,
{
signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS),
method: 'POST',