HttpSystem.ts 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. import { _decorator, Component, CCString, Enum, game } from 'cc';
  2. import { Log } from '../utils/Log';
  3. import { Random } from '../utils/Random';
  4. import { RC4 } from '../utils/RC4';
  5. import { HttpMethod, HttpResponseCode } from './Http';
  6. import { HttpRequest } from './HttpRequest';
  7. const { ccclass, property, executionOrder } = _decorator;
  8. @ccclass("HostData")
  9. export class HostData {
  10. @property({ tooltip: "别名" })
  11. public alias: string = "袁浩";
  12. @property({ tooltip: "地址" })
  13. public host: string = "172.16.15.214";
  14. @property({ tooltip: "端口", min: 0, step: 1 })
  15. public port: number = 80;
  16. @property({ tooltip: "SSL" })
  17. public SSL: boolean = false;
  18. }
  19. /**
  20. * 当请求出错时,抛出错误还是返回对象
  21. */
  22. export enum ErrorDataType {
  23. /**
  24. * 返回空对象
  25. */
  26. Null,
  27. /**
  28. * 抛出异常
  29. */
  30. Throw,
  31. /**
  32. * 返回无key对象:{}
  33. */
  34. Object
  35. }
  36. /**
  37. * Http配置组件
  38. * @description 用于配置HTTP
  39. * @author 袁浩
  40. */
  41. @ccclass('HttpSystem')
  42. export class HttpSystem extends Component {
  43. @property({ tooltip: "默认主机", step: 1, min: 0 })
  44. public hostIndex: number = 0;
  45. @property({ type: [HostData], tooltip: "主机列表" })
  46. public hosts = [];
  47. @property({ tooltip: "请求带的公共的参数,xxx=xxx", type: [CCString] })
  48. public tails: string[] = [];
  49. @property({ tooltip: "当请求出错时,抛出错误还是返回对象", type: Enum(ErrorDataType) })
  50. public errorDataType: ErrorDataType = ErrorDataType.Null;
  51. @property({ tooltip: "消息日志" })
  52. public useDebugLog: boolean = true;
  53. @property({ tooltip: "加密密钥" })
  54. public key = '🧧🎁🎉💰🤩😍💯🉐📦💥';
  55. private encryptionKey: number;
  56. private randomList: string[];
  57. private static thisObject: HttpSystem;
  58. private defaultTails: string[];
  59. start() {
  60. game.addPersistRootNode(this.node);
  61. HttpSystem.thisObject = this;
  62. this.randomList = Array.from(this.key);
  63. this.defaultTails = this.tails.concat();
  64. }
  65. private random: Random;
  66. private _publicKey: string;
  67. /**
  68. * 公钥
  69. */
  70. private get publicKey() {
  71. return this._publicKey;
  72. }
  73. private set publicKey(value: string) {
  74. this._publicKey = value;
  75. let values = Array.from(value);
  76. let seed = '';
  77. for (let i = 0; i < values.length; i++) {
  78. seed += this.randomList.indexOf(values[i]);
  79. }
  80. this.random = new Random(parseInt(seed));
  81. Log.trace(`随机密钥:${value} 随机值:${seed}`);
  82. }
  83. private resetPublicKey() {
  84. let randomValue = Math.floor(this.random.range(0, 10000000000)) + '';
  85. let randomStr = "";
  86. for (let i = 0; i < randomValue.length; i++) {
  87. randomStr += this.randomList[randomValue.charAt(i)];
  88. }
  89. this._publicKey = randomStr;
  90. this.random.seed = parseInt(randomValue);
  91. Log.trace(`随机密钥:${randomStr} 随机值:${randomValue}`);
  92. }
  93. private getErrorDataType() {
  94. return this.errorDataType;
  95. }
  96. public getConfig(hostAlias?: string): HostData {
  97. if (!hostAlias) {
  98. return this.hosts[this.hostIndex];
  99. }
  100. for (let i = 0; i < this.hosts.length; i++) {
  101. const host = this.hosts[i];
  102. if (host.alias == hostAlias) {
  103. return host;
  104. }
  105. }
  106. }
  107. public get tailString() {
  108. var result = "";
  109. for (let i = 0; i < this.tails.length; i++) {
  110. const tail = this.tails[i];
  111. result = (result.length ? `${result}&${tail}` : `${tail}`)
  112. }
  113. return result;
  114. }
  115. public addTail(tails: string | string[]) {
  116. if (typeof tails == 'string') {
  117. this.tails.push(tails);
  118. }
  119. else {
  120. this.tails = this.tails.concat(tails);
  121. }
  122. }
  123. public resetTail() {
  124. this.tails = this.defaultTails.concat();
  125. }
  126. public setEncryptionKey(encryptionKey: number) {
  127. this.encryptionKey = encryptionKey;
  128. }
  129. public getPrivateKey(): number {
  130. return this.encryptionKey;
  131. }
  132. private serverTimestamp: number;
  133. private tempTime: number;
  134. public initServerTimestamp(value: number) {
  135. this.serverTimestamp = value;
  136. this.tempTime = Date.now();
  137. }
  138. public get serverTime() {
  139. return this.serverTimestamp + (Date.now() - this.tempTime);
  140. }
  141. public static dataToString(data: any): string {
  142. data = data || {};
  143. let result = "";
  144. for (let key in data) {
  145. let v = data[key];
  146. if (typeof data[key] == 'object') {
  147. v = JSON.stringify(data[key]);
  148. }
  149. result += encodeURI(key) + "=" + encodeURI(v) + "&";
  150. }
  151. return result;
  152. }
  153. public static encrypt(data: string, method: HttpMethod) {
  154. data = encodeURIComponent(data);
  155. let privateKey = HttpSystem.getPrivateKey();
  156. data = encodeURIComponent(RC4.rc4(HttpSystem.publicKey + data, privateKey.toString()));
  157. if (method == HttpMethod.GET) {
  158. return "d=" + data + "&";
  159. }
  160. else {
  161. return JSON.stringify({ d: data });
  162. }
  163. }
  164. public static decrypt(data: any) {
  165. if (data) {
  166. data = decodeURIComponent(data.d);
  167. data = RC4.rc4(data, HttpSystem.publicKey);
  168. let keyIndex = data.indexOf(HttpSystem.publicKey);
  169. if (keyIndex != 0) {//密钥不正确
  170. return JSON.stringify({ code: HttpResponseCode.KeyError });
  171. }
  172. data = data.substr(HttpSystem.publicKey.length);
  173. }
  174. return data;
  175. }
  176. public send(path: string, useEncrypt: boolean, data?: any, useTail: boolean = true, method: HttpMethod = HttpMethod.GET, onProgress?: (loaded: number, total: number) => void) {
  177. return new Promise<any>((resolve: (data: HttpRequest) => void, reject) => {
  178. let request = new HttpRequest(reject, resolve, onProgress);
  179. data = data || {};
  180. data.timestamp = HttpSystem.serverTime;
  181. let getData: string = typeof data == 'object' ? HttpSystem.dataToString(data) : data;
  182. let postData = method == HttpMethod.GET ? null : (typeof data == 'object' ? JSON.stringify(data) : data);
  183. let url: string = this.getRootURL() + (method == HttpMethod.GET ? path + "?" + getData : path);
  184. this.useDebugLog && HttpSystem.useDebugLog && Log.info(`http请求[${url}]发送`);
  185. if (useEncrypt) {//如果消息加密
  186. if (method == HttpMethod.GET) {
  187. getData = HttpSystem.encrypt(getData, method);
  188. }
  189. else {
  190. postData = HttpSystem.encrypt(postData, method);
  191. }
  192. }
  193. useTail && (getData += HttpSystem.tailString);
  194. url = this.getRootURL() + (method == HttpMethod.GET ? path + "?" + getData : path);
  195. request.open(url, method);
  196. request.send(postData);
  197. })
  198. }
  199. public getRootURL(hostAlias = ""): string {
  200. let config = HttpSystem.getConfig();
  201. var port = `:${config.port}`;
  202. if (config.SSL && config.port == 443 || !config.SSL && config.port == 80) {
  203. port = '';
  204. }
  205. return `${config.SSL ? "https://" : "http://"}${config.host}${port}`;
  206. }
  207. /**
  208. * 根据主机别名获取主机的配置
  209. * @param hostAlias 主机别名
  210. * @returns
  211. */
  212. public static getConfig(hostAlias?: string): HostData {
  213. return this.thisObject.getConfig(hostAlias);
  214. }
  215. /**
  216. * 续签公钥
  217. */
  218. public static resetPublicKey() {
  219. return this.thisObject.resetPublicKey();
  220. }
  221. /**
  222. * 请求出错返回的数据类型
  223. * @returns
  224. */
  225. public static getErrorDataType() {
  226. return this.thisObject.getErrorDataType();
  227. }
  228. /**
  229. * 尾巴内容
  230. */
  231. public static get tailString() {
  232. return this.thisObject.tailString;
  233. }
  234. /**
  235. * 是否启用日志
  236. */
  237. public static get useDebugLog() {
  238. return this.thisObject.useDebugLog;
  239. }
  240. public static set useDebugLog(value: boolean) {
  241. this.thisObject.useDebugLog = value;
  242. }
  243. /**
  244. * 服务器当前时间
  245. * @returns
  246. */
  247. public static get serverTime() {
  248. return this.thisObject.serverTime;
  249. }
  250. /**
  251. * 初始化服务器时间戳
  252. */
  253. public static initServerTimestamp(value: number) {
  254. this.thisObject.initServerTimestamp(value);
  255. }
  256. /**
  257. * 获取加密私钥
  258. * @returns 私钥
  259. */
  260. public static getPrivateKey(): number {
  261. return this.thisObject.getPrivateKey();
  262. }
  263. /**
  264. * 加密公钥
  265. * @returns 私钥
  266. */
  267. public static get publicKey(): string {
  268. return this.thisObject.publicKey;
  269. }
  270. public static set publicKey(value: string) {
  271. this.thisObject.publicKey = value;
  272. }
  273. /**
  274. * 新增一个尾巴内容
  275. * @param tails 尾巴内容,xxx=xxx
  276. */
  277. public static addTail(tails: string | string[]) {
  278. this.thisObject.addTail(tails);
  279. }
  280. /**
  281. * 重置尾巴内容到默认值
  282. */
  283. public static resetTail() {
  284. this.thisObject.resetTail();
  285. }
  286. /**
  287. * 设置加密密钥
  288. * @param encryptionKey 密钥
  289. */
  290. public static setEncryptionKey(encryptionKey: number) {
  291. this.thisObject.setEncryptionKey(encryptionKey);
  292. }
  293. /**
  294. * 发送Http请求
  295. * @param url 请求地址
  296. * @param data 数据
  297. * @param method 请求类型方法
  298. * @param onProgress 进度
  299. * @returns
  300. */
  301. public static send(path: string, useEncrypt: boolean, data?: any, useTail: boolean = true, method: HttpMethod = HttpMethod.GET, onProgress?: (loaded: number, total: number) => void) {
  302. this.thisObject.send(path, useEncrypt, data, useTail, method, onProgress);
  303. }
  304. }