• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15interface NativeUri {
16  new(input: string): NativeUri;
17  normalize(): string;
18  equals(other: NativeUri): boolean;
19  equalsTo(other: NativeUri): boolean;
20  checkIsAbsolute(): boolean;
21  toString(): string;
22  checkIsRelative(): boolean;
23  checkIsOpaque(): boolean;
24  checkIsHierarchical(): boolean;
25  addQueryValue(key: string, value: string): string;
26  addSegment(pathSegment: string):string;
27  getLastSegment(): string | null;
28  clearQuery(): string;
29  scheme: string | null;
30  authority: string | null;
31  ssp: string;
32  userInfo: string | null;
33  host: string | null;
34  port: string;
35  path: string | null;
36  query: string | null;
37  fragment: string | null;
38  isFailed: string;
39  encodedUserInfo: string | null;
40  encodedPath: string | null;
41  encodedQuery: string | null;
42  encodedFragment: string | null;
43  encodedAuthority: string | null;
44  encodedSSP: string | null;
45}
46interface UriInterface {
47  Uri: NativeUri;
48}
49declare function requireInternal(s: string): UriInterface;
50const uri = requireInternal('uri');
51
52const TypeErrorCodeId = 401;
53const SyntaxErrorCodeId = 10200002;
54
55class BusinessError extends Error {
56  code: number;
57  constructor(msg: string) {
58    super(msg);
59    this.name = 'BusinessError';
60    this.code = TypeErrorCodeId;
61  }
62}
63
64class URI {
65  uricalss: NativeUri;
66  constructor(input: string) {
67    if (typeof input !== 'string' || input.length === 0) {
68      throw new BusinessError(`Parameter error. The type of ${input} must be string`);
69    }
70    this.uricalss = new uri.Uri(input);
71    let errStr: string = this.uricalss.isFailed;
72    if (errStr.length !== 0) {
73      let err : BusinessError = new BusinessError(`Syntax Error. Invalid Uri string: The ${errStr}`);
74      err.code = SyntaxErrorCodeId;
75      throw err;
76    }
77  }
78
79  static createFromParts(scheme: string, ssp: string, fragment: string): URI {
80    if (scheme === null || typeof scheme !== 'string') {
81      throw new BusinessError(`Parameter error. The type of ${scheme} must be string`);
82    }
83    if (ssp === null || typeof ssp !== 'string') {
84      throw new BusinessError(`Parameter error. The type of ${ssp} must be string`);
85    }
86    if (typeof fragment !== 'string') {
87      throw new BusinessError(`Parameter error. The type of ${fragment} must be string`);
88    }
89    let uriStr: string = scheme;
90    uriStr += ':' + encodeURIComponent(ssp);
91    if (fragment !== null && fragment !== '') {
92      uriStr += '#' + encodeURIComponent(fragment);
93    }
94    return createNewUri(uriStr);
95  }
96
97  toString(): string {
98    return toAscllString(this.uricalss.toString());
99  }
100
101  equals(other: URI): boolean {
102    return this.uricalss.equals(other.uricalss);
103  }
104
105  equalsTo(other: URI): boolean {
106    if (other instanceof URI) {
107      return this.uricalss.equals(other.uricalss);
108    }
109    throw new BusinessError(`Parameter error. The type of ${other} must be URI`);
110  }
111
112  checkIsAbsolute(): boolean {
113    return this.uricalss.checkIsAbsolute();
114  }
115
116  checkRelative(): boolean {
117    return this.uricalss.checkIsRelative();
118  }
119
120  checkOpaque(): boolean {
121    return this.uricalss.checkIsOpaque();
122  }
123
124  checkHierarchical(): boolean {
125    return this.uricalss.checkIsHierarchical();
126  }
127
128  addQueryValue(key: string, value: string): URI {
129    if (key === null || typeof key !== 'string') {
130      throw new BusinessError(`Parameter error. The type of ${key} must be string`);
131    }
132    if (value === null || typeof value !== 'string') {
133      throw new BusinessError(`Parameter error. The type of ${value} must be string`);
134    }
135    let uriStr = this.uricalss.addQueryValue(encodeURIComponent(key), encodeURIComponent(value));
136    return createNewUri(uriStr);
137  }
138
139  addEncodedSegment(pathSegment: string): URI {
140    if (pathSegment === null || typeof pathSegment !== 'string') {
141      throw new BusinessError(`Parameter error. The type of ${pathSegment} must be string`);
142    }
143    let uriStr: string = this.uricalss.addSegment(pathSegment);
144    return createNewUri(uriStr);
145  }
146
147  addSegment(pathSegment: string): URI {
148    if (pathSegment === null || typeof pathSegment !== 'string') {
149      throw new BusinessError(`Parameter error. The type of ${pathSegment} must be string`);
150    }
151    let uriStr = this.uricalss.addSegment(encodeURIComponent(pathSegment));
152    return createNewUri(uriStr);
153  }
154
155  getQueryValue(key: string): string | null {
156    if (key === null || typeof key !== 'string') {
157      throw new BusinessError(`Parameter error. The type of ${key} must be string`);
158    }
159    let value: string | null = null;
160    if (this.uricalss.query === null) {
161      return null;
162    }
163    let queryStrs: string[] = this.uricalss.query.split('&') || [];
164    for (let item of queryStrs) {
165      if (key === '' && item === '') {
166        return '';
167      }
168      let str = item.split('=') || [];
169      if (str.length === 1 && this.decodeSafelyInner(str[0]) === key) {
170        return '';
171      } else if (this.decodeSafelyInner(str[0]) === key) {
172        return this.decodeSafelyInner(item.substring(str[0].length + 1).replace(/\+/g, ' '));
173      }
174    }
175    return value;
176  }
177
178  decodeSafelyOut(input: string): string {
179    let decodedString: string = '';
180    let decodedTemp: string = '';
181    let index: number = 0;
182    while (index < input.length) {
183      if (input[index] === '%' && /[0-9A-Fa-f]{2}/.test(input.slice(index + 1, index + 3))) {
184        const encodedChar = input.slice(index, index + 3);
185        try {
186          decodedString += decodeURIComponent(decodedTemp + encodedChar);
187          decodedTemp = '';
188        } catch (e) {
189          decodedTemp += encodedChar;
190        }
191        index += 3;
192        continue;
193      }
194      if (decodedTemp === '') {
195        decodedString += input[index];
196      } else {
197        decodedString += decodedTemp;
198        decodedString += input[index];
199        decodedTemp = '';
200      }
201      index++;
202    }
203    return decodedTemp === '' ? decodedString : decodedString += decodedTemp;
204  }
205
206  decodeSafelyInner(input: string): string {
207    if (input === undefined || input === '') {
208      return input;
209    }
210    let strVal: string = '';
211    try {
212      strVal = decodeURIComponent(input);
213    } catch (e) {
214      strVal = this.decodeSafelyOut(input);
215    }
216    return strVal;
217  }
218
219  getQueryNames(): string[] {
220    let names: Set<string> = new Set<string>();
221    if (this.uricalss.query === null) {
222      return [];
223    }
224    let start: number = 0;
225    while (start < this.uricalss.query.length) {
226      let next: number = this.uricalss.query.indexOf('&', start);
227      let end: number = (next === -1) ? this.uricalss.query.length : next;
228      let separator: number = this.uricalss.query.indexOf('=', start);
229      if (separator > end || separator === -1) {
230        separator = end;
231      }
232      let name: string = this.uricalss.query.substring(start, separator);
233      names.add(this.decodeSafelyInner(name));
234      start = end + 1;
235    }
236    return Array.from(names);
237  }
238
239  getQueryValues(key: string): string[] {
240    if (key === null || typeof key !== 'string') {
241      throw new BusinessError(`Parameter error. The type of ${key} must be string`);
242    }
243    let values = new Array();
244    if (this.uricalss.query === null) {
245      return values;
246    }
247    let queryStrs: string[] = this.uricalss.query.split('&') || [];
248    for (let item of queryStrs) {
249      if (key === '' && item === '') {
250        values.push(item);
251      }
252      let str = item.split('=') || [];
253      if (str.length === 1 && this.decodeSafelyInner(str[0]) === key) {
254        values.push('');
255      } else if (this.decodeSafelyInner(str[0]) === key) {
256        values.push(this.decodeSafelyInner(item.substring(str[0].length + 1)));
257      }
258    }
259    return values;
260  }
261
262  getBooleanQueryValue(key: string, defaultValue: boolean): boolean {
263    if (key === null || typeof key !== 'string') {
264      throw new BusinessError(`Parameter error. The type of ${key} must be string`);
265    }
266    if (defaultValue === null || typeof defaultValue !== 'boolean') {
267      throw new BusinessError(`Parameter error. The type of ${key} must be boolean`);
268    }
269    let flag = this.getQueryValue(key);
270    if (flag == null) {
271      return defaultValue;
272    }
273    flag = flag.toLocaleLowerCase();
274    return 'false' !== flag && '0' !== flag;
275  }
276
277  getLastSegment(): string {
278    let segments = this.uricalss.getLastSegment();
279    if (!segments) {
280      return '';
281    }
282    return this.decodeSafelyInner(segments);
283  }
284
285  getSegment(): string[] {
286    let array = new Array();
287    let encodedPath: string | null = this.encodedPath;
288    if (encodedPath) {
289      const result: Array<string> = [];
290      encodedPath.split('/').forEach(segment => {
291        if (segment !== '') {
292          result.push(this.decodeSafelyInner(segment));
293        }
294      });
295      return result;
296    }
297    return array;
298  }
299
300  clearQuery(): URI {
301    let uriStr: string = this.uricalss.clearQuery();
302    return createNewUri(uriStr);
303  }
304
305  normalize(): URI {
306    let uriStr: string = this.uricalss.normalize();
307    return createNewUri(uriStr);
308  }
309
310  get scheme(): string | null {
311    return this.uricalss.scheme;
312  }
313
314  set scheme(input: string | null) {
315    if (input === null || input.length === 0) {
316      return;
317    }
318    this.uricalss.scheme = input;
319  }
320
321  set path(input: string | null) {
322    if (input === null) {
323      return;
324    }
325    this.uricalss.path = encodeURI(input);
326  }
327
328  set ssp(input: string | null) {
329    if (input === null) {
330      return;
331    }
332    this.uricalss.ssp = encodeURI(input);
333  }
334
335  get authority(): string | null {
336    if (this.uricalss.authority === null) {
337      return null;
338    }
339    let thisAuthority: string = this.uricalss.authority;
340    if (thisAuthority.indexOf('[') !== -1) {
341      let arr: string[] = thisAuthority.split('[');
342      let brr: string[] = arr[1].split(']');
343      arr[1] = '[' + brr[0] + ']';
344      arr[2] = brr[1];
345      arr[0] = this.decodeSafelyInner(arr[0]);
346      arr[2] = this.decodeSafelyInner(arr[2]);
347      return arr.join('');
348    } else {
349      return this.decodeSafelyInner(thisAuthority);
350    }
351  }
352
353  set authority(input: string | null) {
354    if (input === null) {
355      return;
356    }
357    this.uricalss.authority = encodeURI(input);
358  }
359
360  get ssp(): string {
361    let thisSsp: string = this.uricalss.ssp;
362    if (thisSsp.indexOf('[') !== -1) {
363      let arr: string[] = thisSsp.split('[');
364      let brr: string[] = arr[1].split(']');
365      arr[1] = '[' + brr[0] + ']';
366      arr[2] = brr[1];
367      arr[0] = this.decodeSafelyInner(arr[0]);
368      arr[2] = this.decodeSafelyInner(arr[2]);
369      return arr.join('');
370    } else {
371      return this.decodeSafelyInner(thisSsp);
372    }
373  }
374
375  get userInfo(): string | null {
376    return this.uricalss.userInfo === null ? null : this.decodeSafelyInner(this.uricalss.userInfo);
377  }
378
379  set userInfo(input: string | null) {
380    if (input === null) {
381      return;
382    }
383    this.uricalss.userInfo = encodeURIComponent(input);
384  }
385
386  get host(): string | null {
387    return this.uricalss.host;
388  }
389
390  get port(): string {
391    return this.uricalss.port;
392  }
393
394  get path(): string | null {
395    return this.uricalss.path === null ? null : this.decodeSafelyInner(this.uricalss.path);
396  }
397
398  get query(): string | null {
399    return this.uricalss.query === null ? null : this.decodeSafelyInner(this.uricalss.query);
400  }
401
402  set query(input: string | null) {
403    if (input === null) {
404      return;
405    }
406    this.uricalss.query = encodeURIComponent(input);
407  }
408
409  get fragment(): string | null {
410    return this.uricalss.fragment === null ? null : this.decodeSafelyInner(this.uricalss.fragment);
411  }
412
413  set fragment(input: string | null) {
414    if (input === null) {
415      return;
416    }
417    this.uricalss.fragment = encodeURIComponent(input);
418  }
419
420  set encodedUserInfo(input: string | null) {
421    if (input === null) {
422      return;
423    }
424    this.uricalss.userInfo = input;
425  }
426
427  set encodedPath(input: string | null) {
428    if (input === null) {
429      return;
430    }
431    this.uricalss.path = input;
432  }
433
434  set encodedQuery(input: string | null) {
435    if (input === null) {
436      return;
437    }
438    this.uricalss.query = input;
439  }
440
441  set encodedFragment(input: string | null) {
442    if (input === null) {
443      return;
444    }
445    this.uricalss.fragment = input;
446  }
447
448  set encodedAuthority(input: string | null) {
449    if (input === null) {
450      return;
451    }
452    this.uricalss.authority = input;
453  }
454
455  set encodedSSP(input: string | null) {
456    if (input === null) {
457      return;
458    }
459    this.uricalss.ssp = input;
460  }
461
462  get encodedUserInfo(): string | null {
463    return this.uricalss.userInfo;
464  }
465
466  get encodedPath(): string | null {
467    return this.uricalss.path;
468  }
469
470  get encodedQuery(): string | null {
471    return this.uricalss.query;
472  }
473
474  get encodedFragment(): string | null {
475    return this.uricalss.fragment;
476  }
477
478  get encodedAuthority(): string | null {
479    if (this.uricalss.authority === null) {
480      return null;
481    }
482    let thisAuthority: string = this.uricalss.authority;
483    if (thisAuthority.indexOf('[') !== -1) {
484      let arr: string[] = thisAuthority.split('[');
485      let brr: string[] = arr[1].split(']');
486      arr[1] = '[' + brr[0] + ']';
487      arr[2] = brr[1];
488      return arr.join('');
489    } else {
490      return thisAuthority;
491    }
492  }
493
494  get encodedSSP(): string {
495    let thisSsp: string = this.uricalss.ssp;
496    if (thisSsp.indexOf('[') !== -1) {
497      let arr: string[] = thisSsp.split('[');
498      let brr: string[] = arr[1].split(']');
499      arr[1] = '[' + brr[0] + ']';
500      arr[2] = brr[1];
501      return arr.join('');
502    } else {
503      return thisSsp;
504    }
505  }
506}
507
508function toAscllString(uriStr: string): string {
509  return encodeURI(uriStr).replace(/%5B/g, '[').replace(/%5D/g, ']').replace(/%25/g, '%');
510}
511
512function createNewUri(uriStr: string): URI {
513  return new URI(uriStr);
514}
515
516export default {
517  URI: URI
518};