UNPKG

@yeepay/yop-typescript-sdk

Version:

TypeScript SDK for interacting with YOP (YeePay Open Platform)

137 lines 4.83 kB
export class HttpUtils { /** * Normalizes a value by encoding special characters * @param value - The value to normalize * @returns Normalized string */ /** * Normalizes a value by encoding special characters according to RFC 3986 * @param value - The value to normalize * @returns Normalized string */ static normalize(value) { // 处理 undefined 和 null if (value === undefined || value === null) { return ""; } // 将值转换为字符串 const strValue = value.toString(); // 如果是空字符串,直接返回 if (strValue === "") { return ""; } // 特殊处理:检查是否是百分号编码的波浪号 %7E,应该转换为 ~ if (strValue === '%7E') { return '~'; } let vStr = ""; const bytes = Buffer.from(strValue, 'utf-8'); for (let i = 0; i < bytes.length; i++) { const byte = bytes[i]; const s = String.fromCharCode(byte); // Assert non-null: loop guarantees it's defined if (s.match(/[0-9a-zA-Z._~-]/)) { // RFC 3986 unreserved characters vStr += s; } else { // Handle special cases according to RFC 3986 if (s === '+') { vStr += '%2B'; // 修复:将 + 编码为 %2B 而不是 %20 } else if (s === '*') { vStr += '%2A'; // Convert * to %2A } else if (s === '%') { // 检查是否是 %7E 序列(编码的波浪号) if (i + 2 < bytes.length && String.fromCharCode(bytes[i + 1]) === '7' && String.fromCharCode(bytes[i + 2]) === 'E') { vStr += '~'; // 将 %7E 转换为 ~ i += 2; // 跳过后面两个字符 } else { vStr += '%25'; // 其他情况下,将 % 编码为 %25 } } else { // 确保十六进制值始终是两位数 const hex = byte.toString(16).toUpperCase().padStart(2, '0'); vStr += '%' + hex; } } } return vStr; } /** * Converts a string to bytes (UTF-8 encoding) * @param str - The string to convert * @returns Array of bytes */ static stringToByte(str) { const bytes = []; const len = str.length; for (let i = 0; i < len; i++) { const c = str.charCodeAt(i); if (c >= 0x010000 && c <= 0x10FFFF) { bytes.push(((c >> 18) & 0x07) | 0xF0); bytes.push(((c >> 12) & 0x3F) | 0x80); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000800 && c <= 0x00FFFF) { bytes.push(((c >> 12) & 0x0F) | 0xE0); bytes.push(((c >> 6) & 0x3F) | 0x80); bytes.push((c & 0x3F) | 0x80); } else if (c >= 0x000080 && c <= 0x0007FF) { bytes.push(((c >> 6) & 0x1F) | 0xC0); bytes.push((c & 0x3F) | 0x80); } else { bytes.push(c & 0xFF); } } return bytes; } /** * Encodes parameters in a request * @param req - The request containing parameters * @returns Encoded parameters */ static encodeParams(req) { const encoded = {}; for (const k in req.paramMap) { const v = req.paramMap[k]; // Cast v to any as HttpUtils.normalize is designed to handle various input types encoded[this.normalize(k)] = this.normalize(v); } return encoded; } /** * Checks if a string starts with a substring * @param haystack - The string to check * @param needle - The substring to look for * @returns True if haystack starts with needle */ static startsWith(haystack, needle) { if (!needle) { return true; } return haystack.lastIndexOf(needle) >= 0; } /** * Checks if a string ends with a substring * @param haystack - The string to check * @param needle - The substring to look for * @returns True if haystack ends with needle */ static endsWith(haystack, needle) { if (!needle) { return true; } const temp = (haystack.length - needle.length); return temp >= 0; } } export default HttpUtils; //# sourceMappingURL=HttpUtils.js.map