318 lines
7.3 KiB
TypeScript
318 lines
7.3 KiB
TypeScript
import { invoke } from "@tauri-apps/api/core"
|
|
|
|
export type Method =
|
|
| "GET" // Retrieve resource
|
|
| "POST" // Create resource
|
|
| "PUT" // Replace resource
|
|
| "DELETE" // Remove resource
|
|
| "PATCH" // Modify resource
|
|
| "HEAD" // GET without body
|
|
| "OPTIONS" // Get allowed methods
|
|
| "CONNECT" // Create tunnel
|
|
| "TRACE" // Loop-back test
|
|
|
|
export type Version = "HTTP/1.0" | "HTTP/1.1" | "HTTP/2.0" | "HTTP/3.0"
|
|
|
|
export type StatusCode =
|
|
| 100 // Continue
|
|
| 101 // Switching Protocols
|
|
| 102 // Processing
|
|
| 103 // Early Hints
|
|
| 200 // OK
|
|
| 201 // Created
|
|
| 202 // Accepted
|
|
| 203 // Non-Authoritative Info
|
|
| 204 // No Content
|
|
| 205 // Reset Content
|
|
| 206 // Partial Content
|
|
| 207 // Multi-Status
|
|
| 208 // Already Reported
|
|
| 226 // IM Used
|
|
| 300 // Multiple Choices
|
|
| 301 // Moved Permanently
|
|
| 302 // Found
|
|
| 303 // See Other
|
|
| 304 // Not Modified
|
|
| 305 // Use Proxy
|
|
| 306 // Switch Proxy
|
|
| 307 // Temporary Redirect
|
|
| 308 // Permanent Redirect
|
|
| 400 // Bad Request
|
|
| 401 // Unauthorized
|
|
| 402 // Payment Required
|
|
| 403 // Forbidden
|
|
| 404 // Not Found
|
|
| 405 // Method Not Allowed
|
|
| 406 // Not Acceptable
|
|
| 407 // Proxy Auth Required
|
|
| 408 // Request Timeout
|
|
| 409 // Conflict
|
|
| 410 // Gone
|
|
| 411 // Length Required
|
|
| 412 // Precondition Failed
|
|
| 413 // Payload Too Large
|
|
| 414 // URI Too Long
|
|
| 415 // Unsupported Media
|
|
| 416 // Range Not Satisfiable
|
|
| 417 // Expectation Failed
|
|
| 418 // I'm a teapot
|
|
| 421 // Misdirected Request
|
|
| 422 // Unprocessable Entity
|
|
| 423 // Locked
|
|
| 424 // Failed Dependency
|
|
| 425 // Too Early
|
|
| 426 // Upgrade Required
|
|
| 428 // Precondition Required
|
|
| 429 // Too Many Requests
|
|
| 431 // Headers Too Large
|
|
| 451 // Unavailable Legal
|
|
| 500 // Server Error
|
|
| 501 // Not Implemented
|
|
| 502 // Bad Gateway
|
|
| 503 // Service Unavailable
|
|
| 504 // Gateway Timeout
|
|
| 505 // HTTP Ver. Not Supported
|
|
| 506 // Variant Negotiates
|
|
| 507 // Insufficient Storage
|
|
| 508 // Loop Detected
|
|
| 510 // Not Extended
|
|
| 511 // Network Auth Required
|
|
|
|
export type FormDataValue =
|
|
| { kind: "text"; value: string }
|
|
| { kind: "file"; filename: string; contentType: string; data: Uint8Array }
|
|
|
|
export type FormData = [string, FormDataValue[]][]
|
|
|
|
export enum MediaType {
|
|
TEXT_PLAIN = "text/plain",
|
|
TEXT_HTML = "text/html",
|
|
TEXT_CSS = "text/css",
|
|
TEXT_CSV = "text/csv",
|
|
APPLICATION_JSON = "application/json",
|
|
APPLICATION_LD_JSON = "application/ld+json",
|
|
APPLICATION_XML = "application/xml",
|
|
TEXT_XML = "text/xml",
|
|
APPLICATION_FORM = "application/x-www-form-urlencoded",
|
|
APPLICATION_OCTET = "application/octet-stream",
|
|
MULTIPART_FORM = "multipart/form-data",
|
|
}
|
|
|
|
export type ContentType =
|
|
| {
|
|
kind: "text"
|
|
content: string
|
|
mediaType:
|
|
| MediaType.TEXT_PLAIN
|
|
| MediaType.TEXT_HTML
|
|
| MediaType.TEXT_CSS
|
|
| MediaType.TEXT_CSV
|
|
}
|
|
| {
|
|
kind: "json"
|
|
content: unknown
|
|
mediaType: MediaType.APPLICATION_JSON | MediaType.APPLICATION_LD_JSON
|
|
}
|
|
| {
|
|
kind: "xml"
|
|
content: string
|
|
mediaType: MediaType.APPLICATION_XML | MediaType.TEXT_XML
|
|
}
|
|
| { kind: "form"; content: FormData; mediaType: MediaType.APPLICATION_FORM }
|
|
| {
|
|
kind: "binary"
|
|
content: Uint8Array
|
|
mediaType: MediaType.APPLICATION_OCTET | string
|
|
filename?: string
|
|
}
|
|
| {
|
|
kind: "multipart"
|
|
content: FormData
|
|
mediaType: MediaType.MULTIPART_FORM
|
|
}
|
|
| {
|
|
kind: "urlencoded"
|
|
content: string
|
|
mediaType: MediaType.APPLICATION_FORM
|
|
}
|
|
| { kind: "stream"; content: ReadableStream; mediaType: string }
|
|
|
|
export interface ResponseBody {
|
|
body: Uint8Array
|
|
mediaType: MediaType | string
|
|
}
|
|
|
|
export type AuthType =
|
|
| { kind: "none" }
|
|
| { kind: "basic"; username: string; password: string }
|
|
| { kind: "bearer"; token: string }
|
|
| {
|
|
kind: "digest"
|
|
username: string
|
|
password: string
|
|
realm?: string
|
|
nonce?: string
|
|
opaque?: string
|
|
algorithm?: "MD5" | "SHA-256" | "SHA-512"
|
|
qop?: "auth" | "auth-int"
|
|
nc?: string
|
|
cnonce?: string
|
|
}
|
|
| {
|
|
kind: "oauth2"
|
|
grantType:
|
|
| {
|
|
kind: "authorization_code"
|
|
authEndpoint: string
|
|
tokenEndpoint: string
|
|
clientId: string
|
|
clientSecret?: string
|
|
}
|
|
| {
|
|
kind: "client_credentials"
|
|
tokenEndpoint: string
|
|
clientId: string
|
|
clientSecret?: string
|
|
}
|
|
| {
|
|
kind: "password"
|
|
tokenEndpoint: string
|
|
username: string
|
|
password: string
|
|
}
|
|
| {
|
|
kind: "implicit"
|
|
authEndpoint: string
|
|
clientId: string
|
|
}
|
|
accessToken?: string
|
|
refreshToken?: string
|
|
}
|
|
| {
|
|
kind: "apikey"
|
|
key: string
|
|
value: string
|
|
in: "header" | "query"
|
|
}
|
|
| {
|
|
kind: "aws"
|
|
accessKey: string
|
|
secretKey: string
|
|
region: string
|
|
service: string
|
|
sessionToken?: string
|
|
in: "header" | "query"
|
|
}
|
|
|
|
export type CertificateType =
|
|
| {
|
|
kind: "pem"
|
|
cert: Uint8Array
|
|
key: Uint8Array
|
|
}
|
|
| {
|
|
kind: "pfx"
|
|
data: Uint8Array
|
|
password: string
|
|
}
|
|
|
|
export interface RequestOptions {
|
|
timeout?: number
|
|
followRedirects?: boolean
|
|
maxRedirects?: number
|
|
decompress?: boolean
|
|
cookies?: boolean
|
|
keepAlive?: boolean
|
|
}
|
|
|
|
export interface RequestMeta {
|
|
options?: RequestOptions
|
|
}
|
|
|
|
export interface Request {
|
|
id: number
|
|
url: string
|
|
method: Method
|
|
version: Version
|
|
headers?: Record<string, string>
|
|
params?: Record<string, string>
|
|
content?: ContentType
|
|
auth?: AuthType
|
|
|
|
security?: {
|
|
certificates?: {
|
|
client?: CertificateType
|
|
ca?: Array<Uint8Array>
|
|
}
|
|
verifyHost?: boolean
|
|
verifyPeer?: boolean
|
|
}
|
|
|
|
proxy?: {
|
|
url: string
|
|
auth?: {
|
|
username: string
|
|
password: string
|
|
}
|
|
}
|
|
|
|
meta?: RequestMeta
|
|
}
|
|
|
|
export interface Response {
|
|
id: number
|
|
status: StatusCode
|
|
statusText: string
|
|
version: Version
|
|
headers: Record<string, string>
|
|
cookies?: Array<{
|
|
name: string
|
|
value: string
|
|
domain?: string
|
|
path?: string
|
|
expires?: Date
|
|
secure?: boolean
|
|
httpOnly?: boolean
|
|
sameSite?: "Strict" | "Lax" | "None"
|
|
}>
|
|
body: ResponseBody
|
|
|
|
meta: {
|
|
timing: {
|
|
start: number
|
|
end: number
|
|
}
|
|
size: {
|
|
headers: number
|
|
body: number
|
|
total: number
|
|
}
|
|
}
|
|
}
|
|
|
|
export type UnsupportedFeatureError = {
|
|
kind: "unsupported_feature"
|
|
feature: string
|
|
message: string
|
|
relay: string
|
|
}
|
|
|
|
export type RelayError =
|
|
| UnsupportedFeatureError
|
|
| { kind: "network"; message: string; cause?: unknown }
|
|
| { kind: "timeout"; message: string; phase?: "connect" | "tls" | "response" }
|
|
| { kind: "certificate"; message: string; cause?: unknown }
|
|
| { kind: "parse"; message: string; cause?: unknown }
|
|
| { kind: "abort"; message: string }
|
|
|
|
export type RequestResult =
|
|
| { kind: "success"; response: Response }
|
|
| { kind: "error"; error: RelayError }
|
|
|
|
export async function execute(request: Request): Promise<RequestResult> {
|
|
return await invoke<RequestResult>("plugin:relay|execute", { request })
|
|
}
|
|
|
|
export async function cancel(requestId: number): Promise<void> {
|
|
return await invoke<void>("plugin:relay|cancel", { requestId })
|
|
}
|