| const NON_REDIRECTABLE_STATUS_CODES = new Set([504, 524]); |
|
|
| export const STATUS_CODE_RISK_I18N_KEYS = { |
| title: '高危操作确认', |
| detailTitle: '检测到以下高危状态码重定向规则', |
| inputPrompt: '操作确认', |
| confirmButton: '我确认开启高危重试', |
| markdown: '高危状态码重试风险告知与免责声明Markdown', |
| confirmText: '高危状态码重试风险确认输入文本', |
| inputPlaceholder: '高危状态码重试风险输入框占位文案', |
| mismatchText: '高危状态码重试风险输入不匹配提示', |
| }; |
|
|
| export const STATUS_CODE_RISK_CHECKLIST_KEYS = [ |
| '高危状态码重试风险确认项1', |
| '高危状态码重试风险确认项2', |
| '高危状态码重试风险确认项3', |
| '高危状态码重试风险确认项4', |
| ]; |
|
|
| function parseStatusCodeKey(rawKey) { |
| if (typeof rawKey !== 'string') { |
| return null; |
| } |
| const normalized = rawKey.trim(); |
| if (!/^[1-5]\d{2}$/.test(normalized)) { |
| return null; |
| } |
| return Number.parseInt(normalized, 10); |
| } |
|
|
| function parseStatusCodeMappingTarget(rawValue) { |
| if (typeof rawValue === 'number' && Number.isInteger(rawValue)) { |
| return rawValue >= 100 && rawValue <= 599 ? rawValue : null; |
| } |
| if (typeof rawValue === 'string') { |
| const normalized = rawValue.trim(); |
| if (!/^[1-5]\d{2}$/.test(normalized)) { |
| return null; |
| } |
| const code = Number.parseInt(normalized, 10); |
| return code >= 100 && code <= 599 ? code : null; |
| } |
| return null; |
| } |
|
|
| export function collectInvalidStatusCodeEntries(statusCodeMappingStr) { |
| if ( |
| typeof statusCodeMappingStr !== 'string' || |
| statusCodeMappingStr.trim() === '' |
| ) { |
| return []; |
| } |
|
|
| let parsed; |
| try { |
| parsed = JSON.parse(statusCodeMappingStr); |
| } catch { |
| return []; |
| } |
|
|
| if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { |
| return []; |
| } |
|
|
| const invalid = []; |
| for (const [rawKey, rawValue] of Object.entries(parsed)) { |
| const fromCode = parseStatusCodeKey(rawKey); |
| const toCode = parseStatusCodeMappingTarget(rawValue); |
| if (fromCode === null || toCode === null) { |
| invalid.push(`${rawKey} → ${rawValue}`); |
| } |
| } |
|
|
| return invalid; |
| } |
|
|
| export function collectDisallowedStatusCodeRedirects(statusCodeMappingStr) { |
| if ( |
| typeof statusCodeMappingStr !== 'string' || |
| statusCodeMappingStr.trim() === '' |
| ) { |
| return []; |
| } |
|
|
| let parsed; |
| try { |
| parsed = JSON.parse(statusCodeMappingStr); |
| } catch (error) { |
| return []; |
| } |
|
|
| if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { |
| return []; |
| } |
|
|
| const riskyMappings = []; |
| Object.entries(parsed).forEach(([rawFrom, rawTo]) => { |
| const fromCode = parseStatusCodeKey(rawFrom); |
| const toCode = parseStatusCodeMappingTarget(rawTo); |
| if (fromCode === null || toCode === null) { |
| return; |
| } |
| if (!NON_REDIRECTABLE_STATUS_CODES.has(fromCode)) { |
| return; |
| } |
| if (fromCode === toCode) { |
| return; |
| } |
| riskyMappings.push(`${fromCode} -> ${toCode}`); |
| }); |
|
|
| return Array.from(new Set(riskyMappings)).sort(); |
| } |
|
|
| export function collectNewDisallowedStatusCodeRedirects( |
| originalStatusCodeMappingStr, |
| currentStatusCodeMappingStr, |
| ) { |
| const currentRisky = collectDisallowedStatusCodeRedirects( |
| currentStatusCodeMappingStr, |
| ); |
| if (currentRisky.length === 0) { |
| return []; |
| } |
|
|
| const originalRiskySet = new Set( |
| collectDisallowedStatusCodeRedirects(originalStatusCodeMappingStr), |
| ); |
|
|
| return currentRisky.filter((mapping) => !originalRiskySet.has(mapping)); |
| } |
|
|