@yeepay/yop-typescript-sdk
Version:
TypeScript SDK for interacting with YOP (YeePay Open Platform)
137 lines • 4.83 kB
JavaScript
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