@yeepay/yop-typescript-sdk
Version:
TypeScript SDK for interacting with YOP (YeePay Open Platform)
105 lines • 3.84 kB
JavaScript
export class HttpUtils {
/**
* Normalizes a value by encoding special characters according to RFC 3986
*
* 严格遵循 RFC 3986 标准进行 URL 编码:
* - 保留非保留字符(unreserved characters): [A-Za-z0-9-_.~]
* - 空格编码为 %20 (不是 +)
* - + 编码为 %2B
* - * 编码为 %2A
* - ~ 不编码(是非保留字符)
* - 其他字符按 UTF-8 编码后转为 %XX 格式
*
* @param value - The value to normalize
* @returns Normalized string according to RFC 3986
*/
static normalize(value) {
if (value === undefined || value === null) {
return '';
}
const valueStr = value.toString();
let vStr = '';
const bytes = Buffer.from(valueStr, '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'; // Convert + to %2B (RFC 3986)
}
else if (s === '*') {
vStr += '%2A'; // Convert * to %2A
}
else if (s === ' ') {
vStr += '%20'; // Convert space to %20 (RFC 3986)
}
else if (s === '%' && i + 2 < bytes.length) {
// Check if this is %7E which should be converted to ~
const nextTwoChars = String.fromCharCode(bytes[i + 1]) +
String.fromCharCode(bytes[i + 2]);
if (nextTwoChars.toUpperCase() === '7E') {
vStr += '~';
i += 2; // Skip the next two bytes
}
else {
// 确保十六进制值是两位数
const hex = byte.toString(16).toUpperCase();
vStr += '%' + (hex.length === 1 ? '0' + hex : hex);
}
}
else {
// 确保十六进制值是两位数
const hex = byte.toString(16).toUpperCase();
vStr += '%' + (hex.length === 1 ? '0' + hex : hex);
}
}
}
return vStr;
}
/**
* 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 the types that HttpUtils.normalize accepts
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