-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy patherrors.ts
More file actions
126 lines (96 loc) · 3.4 KB
/
Copy patherrors.ts
File metadata and controls
126 lines (96 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
* Machine-readable error codes returned by the HTTP client plugin.
*
* Use these with {@link HttpClientError.code} for programmatic error
* handling.
*/
export enum HttpErrorCode {
/** URL host is not in the domain allowlist. */
DOMAIN_NOT_ALLOWED = 'DOMAIN_NOT_ALLOWED',
/** Non-HTTP(S) scheme (e.g. `ftp://`, `file://`). */
SCHEME_NOT_ALLOWED = 'SCHEME_NOT_ALLOWED',
/** IP address used instead of a domain name. */
IP_ADDRESS_NOT_ALLOWED = 'IP_ADDRESS_NOT_ALLOWED',
/** Malformed URL. */
INVALID_URL = 'INVALID_URL',
/** Request timed out. */
TIMEOUT = 'TIMEOUT',
/** TCP or TLS connection failure. */
CONNECTION_ERROR = 'CONNECTION_ERROR',
/** Other request-level error. */
REQUEST_ERROR = 'REQUEST_ERROR',
/** Request cancelled via `AbortController`. */
ABORTED = 'ABORTED',
/** Response body exceeds the configured size limit. */
RESPONSE_TOO_LARGE = 'RESPONSE_TOO_LARGE',
/** A redirect targeted a domain not in the allowlist. */
REDIRECT_BLOCKED = 'REDIRECT_BLOCKED',
/** Adding a domain would exceed the allowlist size cap. */
ALLOWLIST_SIZE_EXCEEDED = 'ALLOWLIST_SIZE_EXCEEDED',
/** Wildcard patterns cannot be added at runtime. */
WILDCARD_NOT_ALLOWED_AT_RUNTIME = 'WILDCARD_NOT_ALLOWED_AT_RUNTIME',
/** Domain pattern is malformed. */
INVALID_DOMAIN_PATTERN = 'INVALID_DOMAIN_PATTERN',
/** A forbidden header was provided (e.g. Host). */
FORBIDDEN_HEADER = 'FORBIDDEN_HEADER',
/** IPC response could not be decoded (malformed binary frame). */
PROTOCOL_ERROR = 'PROTOCOL_ERROR',
/** Unclassified error. */
ERROR = 'ERROR',
}
const KNOWN_CODES = new Set<string>(Object.values(HttpErrorCode));
/**
* Error thrown by the HTTP client plugin.
*
* Contains a machine-readable {@link code} for programmatic error handling.
*/
export class HttpClientError extends Error {
public readonly code: HttpErrorCode;
public constructor(code: HttpErrorCode, message: string) {
super(message);
// Required for instanceof when transpiled to ES5
Object.setPrototypeOf(this, new.target.prototype);
this.name = 'HttpClientError';
this.code = code;
}
}
/**
* Parses the structured `{code, message}` error from the Rust backend
* into an `HttpClientError`.
*/
export function parseError(err: unknown): HttpClientError {
if (err instanceof HttpClientError) {
return err;
}
// Tauri invoke errors come as strings or objects
let code = HttpErrorCode.ERROR,
message = 'unknown error';
if (typeof err === 'string') {
try {
const parsed = JSON.parse(err) as { code?: string; message?: string };
if (parsed.code && parsed.message) {
code = toErrorCode(parsed.code);
message = parsed.message;
} else {
message = err;
}
} catch{
message = err;
}
} else if (err && typeof err === 'object') {
const obj = err as Record<string, unknown>;
if (typeof obj.code === 'string' && typeof obj.message === 'string') {
code = toErrorCode(obj.code);
message = obj.message;
} else if (typeof obj.message === 'string') {
message = obj.message;
}
}
return new HttpClientError(code, message);
}
function toErrorCode(raw: string): HttpErrorCode {
if (KNOWN_CODES.has(raw)) {
return raw as HttpErrorCode;
}
return HttpErrorCode.ERROR;
}