mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-08-28 14:17:25 +02:00
feat(settings): add HTTP version as an inherited request setting (#609)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
6777003b70
commit
b7b8ae5f94
@@ -2,7 +2,9 @@ import type {
|
|||||||
Folder,
|
Folder,
|
||||||
GrpcRequest,
|
GrpcRequest,
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
|
HttpVersion,
|
||||||
InheritedBoolSetting,
|
InheritedBoolSetting,
|
||||||
|
InheritedHttpVersionSetting,
|
||||||
InheritedIntSetting,
|
InheritedIntSetting,
|
||||||
WebsocketRequest,
|
WebsocketRequest,
|
||||||
Workspace,
|
Workspace,
|
||||||
@@ -13,6 +15,7 @@ import {
|
|||||||
modelSupportsSetting,
|
modelSupportsSetting,
|
||||||
type RequestSettingDefinition,
|
type RequestSettingDefinition,
|
||||||
SETTING_FOLLOW_REDIRECTS,
|
SETTING_FOLLOW_REDIRECTS,
|
||||||
|
SETTING_HTTP_VERSION,
|
||||||
SETTING_REQUEST_MESSAGE_SIZE,
|
SETTING_REQUEST_MESSAGE_SIZE,
|
||||||
SETTING_REQUEST_TIMEOUT,
|
SETTING_REQUEST_TIMEOUT,
|
||||||
SETTING_SEND_COOKIES,
|
SETTING_SEND_COOKIES,
|
||||||
@@ -21,6 +24,7 @@ import {
|
|||||||
} from "../lib/requestSettings";
|
} from "../lib/requestSettings";
|
||||||
import { Checkbox } from "./core/Checkbox";
|
import { Checkbox } from "./core/Checkbox";
|
||||||
import { PlainInput } from "./core/PlainInput";
|
import { PlainInput } from "./core/PlainInput";
|
||||||
|
import { Select } from "./core/Select";
|
||||||
import {
|
import {
|
||||||
SettingOverrideRow,
|
SettingOverrideRow,
|
||||||
SettingRow,
|
SettingRow,
|
||||||
@@ -38,37 +42,21 @@ interface Props {
|
|||||||
model: ModelWithSettings;
|
model: ModelWithSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModelWithSettings =
|
type ModelWithSettings = Workspace | Folder | HttpRequest | WebsocketRequest | GrpcRequest;
|
||||||
| Workspace
|
|
||||||
| Folder
|
|
||||||
| HttpRequest
|
|
||||||
| WebsocketRequest
|
|
||||||
| GrpcRequest;
|
|
||||||
type ModelWithHttpSettings = Workspace | Folder | HttpRequest;
|
type ModelWithHttpSettings = Workspace | Folder | HttpRequest;
|
||||||
type ModelWithTlsSettings =
|
type ModelWithTlsSettings = Workspace | Folder | HttpRequest | WebsocketRequest | GrpcRequest;
|
||||||
| Workspace
|
type ModelWithCookieSettings = Workspace | Folder | HttpRequest | WebsocketRequest;
|
||||||
| Folder
|
type ModelWithMessageSizeSettings = Workspace | Folder | WebsocketRequest | GrpcRequest;
|
||||||
| HttpRequest
|
|
||||||
| WebsocketRequest
|
|
||||||
| GrpcRequest;
|
|
||||||
type ModelWithCookieSettings =
|
|
||||||
| Workspace
|
|
||||||
| Folder
|
|
||||||
| HttpRequest
|
|
||||||
| WebsocketRequest;
|
|
||||||
type ModelWithMessageSizeSettings =
|
|
||||||
| Workspace
|
|
||||||
| Folder
|
|
||||||
| WebsocketRequest
|
|
||||||
| GrpcRequest;
|
|
||||||
type BooleanSetting = boolean | InheritedBoolSetting;
|
type BooleanSetting = boolean | InheritedBoolSetting;
|
||||||
type IntegerSetting = number | InheritedIntSetting;
|
type IntegerSetting = number | InheritedIntSetting;
|
||||||
|
type HttpVersionSetting = HttpVersion | InheritedHttpVersionSetting;
|
||||||
type CookieSettingsPatch = {
|
type CookieSettingsPatch = {
|
||||||
settingSendCookies?: ModelWithCookieSettings["settingSendCookies"];
|
settingSendCookies?: ModelWithCookieSettings["settingSendCookies"];
|
||||||
settingStoreCookies?: ModelWithCookieSettings["settingStoreCookies"];
|
settingStoreCookies?: ModelWithCookieSettings["settingStoreCookies"];
|
||||||
};
|
};
|
||||||
type HttpSettingsPatch = {
|
type HttpSettingsPatch = {
|
||||||
settingFollowRedirects?: ModelWithHttpSettings["settingFollowRedirects"];
|
settingFollowRedirects?: ModelWithHttpSettings["settingFollowRedirects"];
|
||||||
|
settingHttpVersion?: ModelWithHttpSettings["settingHttpVersion"];
|
||||||
settingRequestTimeout?: ModelWithHttpSettings["settingRequestTimeout"];
|
settingRequestTimeout?: ModelWithHttpSettings["settingRequestTimeout"];
|
||||||
};
|
};
|
||||||
type TlsSettingsPatch = {
|
type TlsSettingsPatch = {
|
||||||
@@ -78,10 +66,7 @@ type MessageSizeSettingsPatch = {
|
|||||||
settingRequestMessageSize?: ModelWithMessageSizeSettings["settingRequestMessageSize"];
|
settingRequestMessageSize?: ModelWithMessageSizeSettings["settingRequestMessageSize"];
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ModelSettingsEditor({
|
export function ModelSettingsEditor({ model, showSectionTitles = false }: Props) {
|
||||||
model,
|
|
||||||
showSectionTitles = false,
|
|
||||||
}: Props) {
|
|
||||||
const ancestors = useModelAncestors(model);
|
const ancestors = useModelAncestors(model);
|
||||||
const supportsHttpSettings = modelSupportsHttpSettings(model);
|
const supportsHttpSettings = modelSupportsHttpSettings(model);
|
||||||
const supportsCookieSettings = modelSupportsCookieSettings(model);
|
const supportsCookieSettings = modelSupportsCookieSettings(model);
|
||||||
@@ -154,12 +139,26 @@ export function ModelSettingsEditor({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{supportsHttpSettings && (
|
||||||
|
<HttpVersionSettingRow
|
||||||
|
settingDefinition={SETTING_HTTP_VERSION}
|
||||||
|
setting={model.settingHttpVersion}
|
||||||
|
inheritedValue={resolveInheritedValue(
|
||||||
|
ancestors,
|
||||||
|
SETTING_HTTP_VERSION.modelKey,
|
||||||
|
model.settingHttpVersion,
|
||||||
|
)}
|
||||||
|
onChange={(settingHttpVersion) =>
|
||||||
|
patchHttpSettings(model, {
|
||||||
|
settingHttpVersion,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
)}
|
)}
|
||||||
{supportsCookieSettings && (
|
{supportsCookieSettings && (
|
||||||
<SettingsSection
|
<SettingsSection title={supportsTlsSettings || showSectionTitles ? "Cookies" : null}>
|
||||||
title={supportsTlsSettings || showSectionTitles ? "Cookies" : null}
|
|
||||||
>
|
|
||||||
<BooleanSettingRow
|
<BooleanSettingRow
|
||||||
settingDefinition={SETTING_SEND_COOKIES}
|
settingDefinition={SETTING_SEND_COOKIES}
|
||||||
setting={model.settingSendCookies}
|
setting={model.settingSendCookies}
|
||||||
@@ -195,7 +194,7 @@ export function ModelSettingsEditor({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function countOverriddenSettings(model: ModelWithSettings) {
|
export function countOverriddenSettings(model: ModelWithSettings) {
|
||||||
const settings: (BooleanSetting | IntegerSetting)[] = [];
|
const settings: (BooleanSetting | IntegerSetting | HttpVersionSetting)[] = [];
|
||||||
|
|
||||||
if (modelSupportsCookieSettings(model)) {
|
if (modelSupportsCookieSettings(model)) {
|
||||||
settings.push(model.settingSendCookies, model.settingStoreCookies);
|
settings.push(model.settingSendCookies, model.settingStoreCookies);
|
||||||
@@ -204,22 +203,22 @@ export function countOverriddenSettings(model: ModelWithSettings) {
|
|||||||
settings.push(model.settingValidateCertificates);
|
settings.push(model.settingValidateCertificates);
|
||||||
|
|
||||||
if (modelSupportsHttpSettings(model)) {
|
if (modelSupportsHttpSettings(model)) {
|
||||||
settings.push(model.settingFollowRedirects, model.settingRequestTimeout);
|
settings.push(
|
||||||
|
model.settingFollowRedirects,
|
||||||
|
model.settingRequestTimeout,
|
||||||
|
model.settingHttpVersion,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modelSupportsMessageSizeSettings(model)) {
|
if (modelSupportsMessageSizeSettings(model)) {
|
||||||
settings.push(model.settingRequestMessageSize);
|
settings.push(model.settingRequestMessageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return settings.filter(
|
return settings.filter((setting) => isInheritedSetting(setting) && setting.enabled === true)
|
||||||
(setting) => isInheritedSetting(setting) && setting.enabled === true,
|
.length;
|
||||||
).length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchCookieSettings(
|
function patchCookieSettings(model: ModelWithCookieSettings, patch: Partial<CookieSettingsPatch>) {
|
||||||
model: ModelWithCookieSettings,
|
|
||||||
patch: Partial<CookieSettingsPatch>,
|
|
||||||
) {
|
|
||||||
switch (model.model) {
|
switch (model.model) {
|
||||||
case "workspace":
|
case "workspace":
|
||||||
return patchModel(model, patch as Partial<Workspace>);
|
return patchModel(model, patch as Partial<Workspace>);
|
||||||
@@ -232,10 +231,7 @@ function patchCookieSettings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchHttpSettings(
|
function patchHttpSettings(model: ModelWithHttpSettings, patch: Partial<HttpSettingsPatch>) {
|
||||||
model: ModelWithHttpSettings,
|
|
||||||
patch: Partial<HttpSettingsPatch>,
|
|
||||||
) {
|
|
||||||
switch (model.model) {
|
switch (model.model) {
|
||||||
case "workspace":
|
case "workspace":
|
||||||
return patchModel(model, patch as Partial<Workspace>);
|
return patchModel(model, patch as Partial<Workspace>);
|
||||||
@@ -246,10 +242,7 @@ function patchHttpSettings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function patchTlsSettings(
|
function patchTlsSettings(model: ModelWithTlsSettings, patch: Partial<TlsSettingsPatch>) {
|
||||||
model: ModelWithTlsSettings,
|
|
||||||
patch: Partial<TlsSettingsPatch>,
|
|
||||||
) {
|
|
||||||
switch (model.model) {
|
switch (model.model) {
|
||||||
case "workspace":
|
case "workspace":
|
||||||
return patchModel(model, patch as Partial<Workspace>);
|
return patchModel(model, patch as Partial<Workspace>);
|
||||||
@@ -280,21 +273,15 @@ function patchMessageSizeSettings(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function modelSupportsHttpSettings(
|
function modelSupportsHttpSettings(model: ModelWithSettings): model is ModelWithHttpSettings {
|
||||||
model: ModelWithSettings,
|
|
||||||
): model is ModelWithHttpSettings {
|
|
||||||
return modelSupportsSetting(model, SETTING_REQUEST_TIMEOUT);
|
return modelSupportsSetting(model, SETTING_REQUEST_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
function modelSupportsCookieSettings(
|
function modelSupportsCookieSettings(model: ModelWithSettings): model is ModelWithCookieSettings {
|
||||||
model: ModelWithSettings,
|
|
||||||
): model is ModelWithCookieSettings {
|
|
||||||
return modelSupportsSetting(model, SETTING_SEND_COOKIES);
|
return modelSupportsSetting(model, SETTING_SEND_COOKIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
function modelSupportsTlsSettings(
|
function modelSupportsTlsSettings(model: ModelWithSettings): model is ModelWithTlsSettings {
|
||||||
model: ModelWithSettings,
|
|
||||||
): model is ModelWithTlsSettings {
|
|
||||||
return modelSupportsSetting(model, SETTING_VALIDATE_CERTIFICATES);
|
return modelSupportsSetting(model, SETTING_VALIDATE_CERTIFICATES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,11 +304,7 @@ function BooleanSettingRow({
|
|||||||
}) {
|
}) {
|
||||||
const inherited = isInheritedSetting(setting);
|
const inherited = isInheritedSetting(setting);
|
||||||
const overridden = inherited ? setting.enabled === true : false;
|
const overridden = inherited ? setting.enabled === true : false;
|
||||||
const value = inherited
|
const value = inherited ? (overridden ? setting.value : inheritedValue) : setting;
|
||||||
? overridden
|
|
||||||
? setting.value
|
|
||||||
: inheritedValue
|
|
||||||
: setting;
|
|
||||||
|
|
||||||
if (!inherited) {
|
if (!inherited) {
|
||||||
return (
|
return (
|
||||||
@@ -352,6 +335,63 @@ function BooleanSettingRow({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HTTP_VERSION_OPTIONS: { label: string; value: HttpVersion }[] = [
|
||||||
|
{ label: "Automatic", value: "auto" },
|
||||||
|
{ label: "HTTP/1.1", value: "http1" },
|
||||||
|
{ label: "HTTP/2", value: "http2" },
|
||||||
|
];
|
||||||
|
|
||||||
|
function HttpVersionSettingRow({
|
||||||
|
inheritedValue,
|
||||||
|
setting,
|
||||||
|
settingDefinition,
|
||||||
|
onChange,
|
||||||
|
}: {
|
||||||
|
inheritedValue: HttpVersion;
|
||||||
|
setting: HttpVersionSetting;
|
||||||
|
settingDefinition: RequestSettingDefinition<"settingHttpVersion">;
|
||||||
|
onChange: (setting: HttpVersionSetting) => void;
|
||||||
|
}) {
|
||||||
|
const inherited = isInheritedSetting(setting);
|
||||||
|
const overridden = inherited ? setting.enabled === true : false;
|
||||||
|
const value = inherited ? (overridden ? setting.value : inheritedValue) : setting;
|
||||||
|
|
||||||
|
if (!inherited) {
|
||||||
|
return (
|
||||||
|
<SettingRow title={settingDefinition.title} description={settingDefinition.description}>
|
||||||
|
<Select
|
||||||
|
hideLabel
|
||||||
|
name={settingDefinition.modelKey}
|
||||||
|
label={settingDefinition.title}
|
||||||
|
size="sm"
|
||||||
|
value={value}
|
||||||
|
options={HTTP_VERSION_OPTIONS}
|
||||||
|
onChange={(value) => onChange(value)}
|
||||||
|
/>
|
||||||
|
</SettingRow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingOverrideRow
|
||||||
|
title={settingDefinition.title}
|
||||||
|
description={settingDefinition.description}
|
||||||
|
overridden={overridden}
|
||||||
|
onResetOverride={() => onChange({ ...setting, enabled: false })}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
hideLabel
|
||||||
|
name={settingDefinition.modelKey}
|
||||||
|
label={settingDefinition.title}
|
||||||
|
size="sm"
|
||||||
|
value={value}
|
||||||
|
options={HTTP_VERSION_OPTIONS}
|
||||||
|
onChange={(value) => onChange({ ...setting, enabled: true, value })}
|
||||||
|
/>
|
||||||
|
</SettingOverrideRow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function IntegerSettingRow({
|
function IntegerSettingRow({
|
||||||
inheritedValue,
|
inheritedValue,
|
||||||
setting,
|
setting,
|
||||||
@@ -365,18 +405,11 @@ function IntegerSettingRow({
|
|||||||
}) {
|
}) {
|
||||||
const inherited = isInheritedSetting(setting);
|
const inherited = isInheritedSetting(setting);
|
||||||
const overridden = inherited ? setting.enabled === true : false;
|
const overridden = inherited ? setting.enabled === true : false;
|
||||||
const value = inherited
|
const value = inherited ? (overridden ? setting.value : inheritedValue) : setting;
|
||||||
? overridden
|
|
||||||
? setting.value
|
|
||||||
: inheritedValue
|
|
||||||
: setting;
|
|
||||||
|
|
||||||
if (!inherited) {
|
if (!inherited) {
|
||||||
return (
|
return (
|
||||||
<SettingRow
|
<SettingRow title={settingDefinition.title} description={settingDefinition.description}>
|
||||||
title={settingDefinition.title}
|
|
||||||
description={settingDefinition.description}
|
|
||||||
>
|
|
||||||
<NumberUnitInput
|
<NumberUnitInput
|
||||||
name={settingDefinition.modelKey}
|
name={settingDefinition.modelKey}
|
||||||
label={settingDefinition.title}
|
label={settingDefinition.title}
|
||||||
@@ -429,20 +462,13 @@ function MessageSizeSettingRow({
|
|||||||
}) {
|
}) {
|
||||||
const inherited = isInheritedSetting(setting);
|
const inherited = isInheritedSetting(setting);
|
||||||
const overridden = inherited ? setting.enabled === true : false;
|
const overridden = inherited ? setting.enabled === true : false;
|
||||||
const value = inherited
|
const value = inherited ? (overridden ? setting.value : inheritedValue) : setting;
|
||||||
? overridden
|
|
||||||
? setting.value
|
|
||||||
: inheritedValue
|
|
||||||
: setting;
|
|
||||||
const displayValue = formatMegabytes(value);
|
const displayValue = formatMegabytes(value);
|
||||||
const placeholder = "0";
|
const placeholder = "0";
|
||||||
|
|
||||||
if (!inherited) {
|
if (!inherited) {
|
||||||
return (
|
return (
|
||||||
<SettingRow
|
<SettingRow title={settingDefinition.title} description={settingDefinition.description}>
|
||||||
title={settingDefinition.title}
|
|
||||||
description={settingDefinition.description}
|
|
||||||
>
|
|
||||||
<MessageSizeInput
|
<MessageSizeInput
|
||||||
name={settingDefinition.modelKey}
|
name={settingDefinition.modelKey}
|
||||||
label={settingDefinition.title}
|
label={settingDefinition.title}
|
||||||
@@ -567,13 +593,18 @@ function resolveInheritedValue(
|
|||||||
key: BooleanWorkspaceSettingKey,
|
key: BooleanWorkspaceSettingKey,
|
||||||
fallback: BooleanSetting,
|
fallback: BooleanSetting,
|
||||||
): boolean;
|
): boolean;
|
||||||
|
function resolveInheritedValue(
|
||||||
|
ancestors: (Folder | Workspace)[],
|
||||||
|
key: "settingHttpVersion",
|
||||||
|
fallback: HttpVersionSetting,
|
||||||
|
): HttpVersion;
|
||||||
function resolveInheritedValue(
|
function resolveInheritedValue(
|
||||||
ancestors: (Folder | Workspace)[],
|
ancestors: (Folder | Workspace)[],
|
||||||
key: keyof WorkspaceSettings,
|
key: keyof WorkspaceSettings,
|
||||||
fallback: BooleanSetting | IntegerSetting,
|
fallback: BooleanSetting | IntegerSetting | HttpVersionSetting,
|
||||||
) {
|
) {
|
||||||
for (const ancestor of ancestors) {
|
for (const ancestor of ancestors) {
|
||||||
const setting = ancestor[key] as BooleanSetting | IntegerSetting;
|
const setting = ancestor[key] as BooleanSetting | IntegerSetting | HttpVersionSetting;
|
||||||
if (isInheritedSetting(setting)) {
|
if (isInheritedSetting(setting)) {
|
||||||
if (setting.enabled === true) {
|
if (setting.enabled === true) {
|
||||||
return setting.value;
|
return setting.value;
|
||||||
@@ -589,6 +620,7 @@ function resolveInheritedValue(
|
|||||||
type WorkspaceSettings = Pick<
|
type WorkspaceSettings = Pick<
|
||||||
Workspace,
|
Workspace,
|
||||||
| "settingFollowRedirects"
|
| "settingFollowRedirects"
|
||||||
|
| "settingHttpVersion"
|
||||||
| "settingRequestMessageSize"
|
| "settingRequestMessageSize"
|
||||||
| "settingRequestTimeout"
|
| "settingRequestTimeout"
|
||||||
| "settingSendCookies"
|
| "settingSendCookies"
|
||||||
@@ -598,14 +630,12 @@ type WorkspaceSettings = Pick<
|
|||||||
|
|
||||||
type BooleanWorkspaceSettingKey = Exclude<
|
type BooleanWorkspaceSettingKey = Exclude<
|
||||||
keyof WorkspaceSettings,
|
keyof WorkspaceSettings,
|
||||||
"settingRequestTimeout" | "settingRequestMessageSize"
|
"settingRequestTimeout" | "settingRequestMessageSize" | "settingHttpVersion"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
function formatMegabytes(bytes: number) {
|
function formatMegabytes(bytes: number) {
|
||||||
const megabytes = bytes / BYTES_PER_MB;
|
const megabytes = bytes / BYTES_PER_MB;
|
||||||
return Number.isInteger(megabytes)
|
return Number.isInteger(megabytes) ? `${megabytes}` : megabytes.toFixed(3).replace(/\.?0+$/, "");
|
||||||
? `${megabytes}`
|
|
||||||
: megabytes.toFixed(3).replace(/\.?0+$/, "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseMegabytes(value: string) {
|
function parseMegabytes(value: string) {
|
||||||
@@ -626,9 +656,5 @@ function isValidInteger(value: string) {
|
|||||||
function isValidMegabytes(value: string) {
|
function isValidMegabytes(value: string) {
|
||||||
if (value === "") return true;
|
if (value === "") return true;
|
||||||
const megabytes = Number(value);
|
const megabytes = Number(value);
|
||||||
return (
|
return Number.isFinite(megabytes) && megabytes >= 0 && megabytes <= MAX_MESSAGE_SIZE_MB;
|
||||||
Number.isFinite(megabytes) &&
|
|
||||||
megabytes >= 0 &&
|
|
||||||
megabytes <= MAX_MESSAGE_SIZE_MB
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ type ModelType = AnyModel["model"];
|
|||||||
type WorkspaceRequestSettings = Pick<
|
type WorkspaceRequestSettings = Pick<
|
||||||
Workspace,
|
Workspace,
|
||||||
| "settingFollowRedirects"
|
| "settingFollowRedirects"
|
||||||
|
| "settingHttpVersion"
|
||||||
| "settingRequestMessageSize"
|
| "settingRequestMessageSize"
|
||||||
| "settingRequestTimeout"
|
| "settingRequestTimeout"
|
||||||
| "settingSendCookies"
|
| "settingSendCookies"
|
||||||
@@ -18,9 +19,7 @@ type ModelTypeWithSetting<K extends RequestSettingKey> = {
|
|||||||
[M in ModelType]: K extends keyof ModelForType<M> ? M : never;
|
[M in ModelType]: K extends keyof ModelForType<M> ? M : never;
|
||||||
}[ModelType];
|
}[ModelType];
|
||||||
|
|
||||||
export type RequestSettingDefinition<
|
export type RequestSettingDefinition<K extends RequestSettingKey = RequestSettingKey> = {
|
||||||
K extends RequestSettingKey = RequestSettingKey,
|
|
||||||
> = {
|
|
||||||
defaultValue: WorkspaceRequestSettings[K];
|
defaultValue: WorkspaceRequestSettings[K];
|
||||||
description: string;
|
description: string;
|
||||||
modelKey: K;
|
modelKey: K;
|
||||||
@@ -46,8 +45,7 @@ export const SETTING_REQUEST_TIMEOUT = defineRequestSetting({
|
|||||||
|
|
||||||
export const SETTING_REQUEST_MESSAGE_SIZE = defineRequestSetting({
|
export const SETTING_REQUEST_MESSAGE_SIZE = defineRequestSetting({
|
||||||
defaultValue: 64 * 1024 * 1024,
|
defaultValue: 64 * 1024 * 1024,
|
||||||
description:
|
description: "Maximum gRPC or WebSocket message size in MB. Set to 0 to disable.",
|
||||||
"Maximum gRPC or WebSocket message size in MB. Set to 0 to disable.",
|
|
||||||
modelKey: "settingRequestMessageSize",
|
modelKey: "settingRequestMessageSize",
|
||||||
models: ["workspace", "folder", "websocket_request", "grpc_request"],
|
models: ["workspace", "folder", "websocket_request", "grpc_request"],
|
||||||
title: "Message Size Limit",
|
title: "Message Size Limit",
|
||||||
@@ -57,13 +55,7 @@ export const SETTING_VALIDATE_CERTIFICATES = defineRequestSetting({
|
|||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
description: "When disabled, skip validation of server certificates.",
|
description: "When disabled, skip validation of server certificates.",
|
||||||
modelKey: "settingValidateCertificates",
|
modelKey: "settingValidateCertificates",
|
||||||
models: [
|
models: ["workspace", "folder", "http_request", "websocket_request", "grpc_request"],
|
||||||
"workspace",
|
|
||||||
"folder",
|
|
||||||
"http_request",
|
|
||||||
"websocket_request",
|
|
||||||
"grpc_request",
|
|
||||||
],
|
|
||||||
title: "Validate TLS certificates",
|
title: "Validate TLS certificates",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -75,10 +67,17 @@ export const SETTING_FOLLOW_REDIRECTS = defineRequestSetting({
|
|||||||
title: "Follow redirects",
|
title: "Follow redirects",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const SETTING_HTTP_VERSION = defineRequestSetting({
|
||||||
|
defaultValue: "auto",
|
||||||
|
description: "Force HTTP/1.1 or HTTP/2 for servers that don't negotiate the version correctly.",
|
||||||
|
modelKey: "settingHttpVersion",
|
||||||
|
models: ["workspace", "folder", "http_request"],
|
||||||
|
title: "HTTP version",
|
||||||
|
});
|
||||||
|
|
||||||
export const SETTING_SEND_COOKIES = defineRequestSetting({
|
export const SETTING_SEND_COOKIES = defineRequestSetting({
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
description:
|
description: "Attach matching cookies from the active cookie jar to outgoing requests.",
|
||||||
"Attach matching cookies from the active cookie jar to outgoing requests.",
|
|
||||||
modelKey: "settingSendCookies",
|
modelKey: "settingSendCookies",
|
||||||
models: ["workspace", "folder", "http_request", "websocket_request"],
|
models: ["workspace", "folder", "http_request", "websocket_request"],
|
||||||
title: "Automatically send cookies",
|
title: "Automatically send cookies",
|
||||||
@@ -86,8 +85,7 @@ export const SETTING_SEND_COOKIES = defineRequestSetting({
|
|||||||
|
|
||||||
export const SETTING_STORE_COOKIES = defineRequestSetting({
|
export const SETTING_STORE_COOKIES = defineRequestSetting({
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
description:
|
description: "Save cookies from Set-Cookie response headers to the active cookie jar.",
|
||||||
"Save cookies from Set-Cookie response headers to the active cookie jar.",
|
|
||||||
modelKey: "settingStoreCookies",
|
modelKey: "settingStoreCookies",
|
||||||
models: ["workspace", "folder", "http_request", "websocket_request"],
|
models: ["workspace", "folder", "http_request", "websocket_request"],
|
||||||
title: "Automatically store cookies",
|
title: "Automatically store cookies",
|
||||||
|
|||||||
+111
-24
@@ -1,48 +1,135 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
export type Cookie = { name: string, value: string, domain: CookieDomain, expires: CookieExpires, path: string, secure: boolean, httpOnly: boolean, sameSite: CookieSameSite | null, };
|
export type Cookie = {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
domain: CookieDomain;
|
||||||
|
expires: CookieExpires;
|
||||||
|
path: string;
|
||||||
|
secure: boolean;
|
||||||
|
httpOnly: boolean;
|
||||||
|
sameSite: CookieSameSite | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "NotPresent" | "Empty";
|
export type CookieDomain = { HostOnly: string } | { Suffix: string } | "NotPresent" | "Empty";
|
||||||
|
|
||||||
export type CookieExpires = { "AtUtc": string } | "SessionEnd";
|
export type CookieExpires = { AtUtc: string } | "SessionEnd";
|
||||||
|
|
||||||
export type CookieSameSite = "Strict" | "Lax" | "None";
|
export type CookieSameSite = "Strict" | "Lax" | "None";
|
||||||
|
|
||||||
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, description: string, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string,
|
export type HttpRequest = {
|
||||||
/**
|
model: "http_request";
|
||||||
* URL parameters used for both path placeholders (`:id`) and query string entries.
|
id: string;
|
||||||
*/
|
createdAt: string;
|
||||||
urlParameters: Array<HttpUrlParameter>, settingSendCookies: InheritedBoolSetting, settingStoreCookies: InheritedBoolSetting, settingValidateCertificates: InheritedBoolSetting, settingFollowRedirects: InheritedBoolSetting, settingRequestTimeout: InheritedIntSetting, };
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
folderId: string | null;
|
||||||
|
authentication: Record<string, any>;
|
||||||
|
authenticationType: string | null;
|
||||||
|
body: Record<string, any>;
|
||||||
|
bodyType: string | null;
|
||||||
|
description: string;
|
||||||
|
headers: Array<HttpRequestHeader>;
|
||||||
|
method: string;
|
||||||
|
name: string;
|
||||||
|
sortPriority: number;
|
||||||
|
url: string;
|
||||||
|
/**
|
||||||
|
* URL parameters used for both path placeholders (`:id`) and query string entries.
|
||||||
|
*/
|
||||||
|
urlParameters: Array<HttpUrlParameter>;
|
||||||
|
settingSendCookies: InheritedBoolSetting;
|
||||||
|
settingStoreCookies: InheritedBoolSetting;
|
||||||
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
|
};
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, };
|
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializable representation of HTTP response events for DB storage.
|
* Serializable representation of HTTP response events for DB storage.
|
||||||
* This mirrors `yaak_http::sender::HttpResponseEvent` but with serde support.
|
* This mirrors `yaak_http::sender::HttpResponseEvent` but with serde support.
|
||||||
* The `From` impl is in yaak-http to avoid circular dependencies.
|
* The `From` impl is in yaak-http to avoid circular dependencies.
|
||||||
*/
|
*/
|
||||||
export type HttpResponseEventData = { "type": "setting", name: string, value: string, source_model?: string, source_id?: string, source_name?: string, } | { "type": "info", message: string, } | { "type": "redirect", url: string, status: number, behavior: string, dropped_body: boolean, dropped_headers: Array<string>, } | { "type": "send_url", method: string, scheme: string, username: string, password: string, host: string, port: number, path: string, query: string, fragment: string, } | { "type": "receive_url", version: string, status: string, } | { "type": "header_up", name: string, value: string, } | { "type": "header_down", name: string, value: string, } | { "type": "chunk_sent", bytes: number, } | { "type": "chunk_received", bytes: number, } | { "type": "dns_resolved", hostname: string, addresses: Array<string>, duration: bigint, overridden: boolean, };
|
export type HttpResponseEventData =
|
||||||
|
| {
|
||||||
|
type: "setting";
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
source_model?: string;
|
||||||
|
source_id?: string;
|
||||||
|
source_name?: string;
|
||||||
|
}
|
||||||
|
| { type: "info"; message: string }
|
||||||
|
| {
|
||||||
|
type: "redirect";
|
||||||
|
url: string;
|
||||||
|
status: number;
|
||||||
|
behavior: string;
|
||||||
|
dropped_body: boolean;
|
||||||
|
dropped_headers: Array<string>;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "send_url";
|
||||||
|
method: string;
|
||||||
|
scheme: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
path: string;
|
||||||
|
query: string;
|
||||||
|
fragment: string;
|
||||||
|
}
|
||||||
|
| { type: "receive_url"; version: string; status: string }
|
||||||
|
| { type: "header_up"; name: string; value: string }
|
||||||
|
| { type: "header_down"; name: string; value: string }
|
||||||
|
| { type: "chunk_sent"; bytes: number }
|
||||||
|
| { type: "chunk_received"; bytes: number }
|
||||||
|
| {
|
||||||
|
type: "dns_resolved";
|
||||||
|
hostname: string;
|
||||||
|
addresses: Array<string>;
|
||||||
|
duration: bigint;
|
||||||
|
overridden: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type HttpResponseHeader = { name: string, value: string, };
|
export type HttpResponseHeader = { name: string; value: string };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The resolved send settings, values only: what an executor has to obey, with the sources
|
* The resolved send settings, values only: what an executor has to obey, with the sources
|
||||||
* (which model each came from) left behind in [`ResolvedHttpRequestSettings`]. This is what
|
* (which model each came from) left behind in [`ResolvedHttpRequestSettings`]. This is what
|
||||||
* crosses from a tab to the Yaak server, and what the server reads.
|
* crosses from a tab to the Yaak server, and what the server reads.
|
||||||
*/
|
*/
|
||||||
export type HttpSendSettings = { validateCertificates: boolean, followRedirects: boolean,
|
export type HttpSendSettings = {
|
||||||
/**
|
validateCertificates: boolean;
|
||||||
* Milliseconds. Zero or negative means no timeout.
|
followRedirects: boolean;
|
||||||
*/
|
/**
|
||||||
timeoutMs: number, sendCookies: boolean, storeCookies: boolean, };
|
* Milliseconds. Zero or negative means no timeout.
|
||||||
|
*/
|
||||||
|
timeoutMs: number;
|
||||||
|
sendCookies: boolean;
|
||||||
|
storeCookies: boolean;
|
||||||
|
httpVersion: HttpVersion;
|
||||||
|
};
|
||||||
|
|
||||||
export type HttpUrlParameter = { enabled?: boolean,
|
export type HttpUrlParameter = {
|
||||||
/**
|
enabled?: boolean;
|
||||||
* Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
|
/**
|
||||||
* Other entries are appended as query parameters
|
* Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
|
||||||
*/
|
* Other entries are appended as query parameters
|
||||||
name: string, value: string, id?: string, };
|
*/
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
id?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type InheritedBoolSetting = { enabled?: boolean, value: boolean, };
|
export type HttpVersion = "auto" | "http1" | "http2";
|
||||||
|
|
||||||
export type InheritedIntSetting = { enabled?: boolean, value: number, };
|
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
||||||
|
|
||||||
|
export type InheritedHttpVersionSetting = { enabled?: boolean; value: HttpVersion };
|
||||||
|
|
||||||
|
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ impl PreparedSend {
|
|||||||
let (client, resolver) = HttpConnectionOptions {
|
let (client, resolver) = HttpConnectionOptions {
|
||||||
id: uuid::Uuid::new_v4().to_string(),
|
id: uuid::Uuid::new_v4().to_string(),
|
||||||
validate_certificates: self.settings.validate_certificates,
|
validate_certificates: self.settings.validate_certificates,
|
||||||
|
http_version: self.settings.http_version,
|
||||||
// The proxy connects directly. Going through a system proxy would move DNS, and
|
// The proxy connects directly. Going through a system proxy would move DNS, and
|
||||||
// therefore the address check, somewhere this process can't see.
|
// therefore the address check, somewhere this process can't see.
|
||||||
proxy: HttpConnectionProxySetting::Disabled,
|
proxy: HttpConnectionProxySetting::Disabled,
|
||||||
|
|||||||
+452
-70
@@ -1,127 +1,509 @@
|
|||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
export type AnyModel = CookieJar | Environment | Folder | GraphQlIntrospection | GrpcConnection | GrpcEvent | GrpcRequest | HttpRequest | HttpResponse | HttpResponseEvent | KeyValue | Plugin | Settings | SyncState | WebsocketConnection | WebsocketEvent | WebsocketRequest | Workspace | WorkspaceMeta;
|
export type AnyModel =
|
||||||
|
| CookieJar
|
||||||
|
| Environment
|
||||||
|
| Folder
|
||||||
|
| GraphQlIntrospection
|
||||||
|
| GrpcConnection
|
||||||
|
| GrpcEvent
|
||||||
|
| GrpcRequest
|
||||||
|
| HttpRequest
|
||||||
|
| HttpResponse
|
||||||
|
| HttpResponseEvent
|
||||||
|
| KeyValue
|
||||||
|
| Plugin
|
||||||
|
| Settings
|
||||||
|
| SyncState
|
||||||
|
| WebsocketConnection
|
||||||
|
| WebsocketEvent
|
||||||
|
| WebsocketRequest
|
||||||
|
| Workspace
|
||||||
|
| WorkspaceMeta;
|
||||||
|
|
||||||
export type ClientCertificate = { host: string, port: number | null, crtFile: string | null, keyFile: string | null, pfxFile: string | null, passphrase: string | null, enabled?: boolean, };
|
export type ClientCertificate = {
|
||||||
|
host: string;
|
||||||
|
port: number | null;
|
||||||
|
crtFile: string | null;
|
||||||
|
keyFile: string | null;
|
||||||
|
pfxFile: string | null;
|
||||||
|
passphrase: string | null;
|
||||||
|
enabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type Cookie = { name: string, value: string, domain: CookieDomain, expires: CookieExpires, path: string, secure: boolean, httpOnly: boolean, sameSite: CookieSameSite | null, };
|
export type Cookie = {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
domain: CookieDomain;
|
||||||
|
expires: CookieExpires;
|
||||||
|
path: string;
|
||||||
|
secure: boolean;
|
||||||
|
httpOnly: boolean;
|
||||||
|
sameSite: CookieSameSite | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "NotPresent" | "Empty";
|
export type CookieDomain = { HostOnly: string } | { Suffix: string } | "NotPresent" | "Empty";
|
||||||
|
|
||||||
export type CookieExpires = { "AtUtc": string } | "SessionEnd";
|
export type CookieExpires = { AtUtc: string } | "SessionEnd";
|
||||||
|
|
||||||
export type CookieJar = { model: "cookie_jar", id: string, createdAt: string, updatedAt: string, workspaceId: string, cookies: Array<Cookie>, name: string, };
|
export type CookieJar = {
|
||||||
|
model: "cookie_jar";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
cookies: Array<Cookie>;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type CookieSameSite = "Strict" | "Lax" | "None";
|
export type CookieSameSite = "Strict" | "Lax" | "None";
|
||||||
|
|
||||||
export type DnsOverride = { hostname: string, ipv4: Array<string>, ipv6: Array<string>, enabled?: boolean, };
|
export type DnsOverride = {
|
||||||
|
hostname: string;
|
||||||
|
ipv4: Array<string>;
|
||||||
|
ipv6: Array<string>;
|
||||||
|
enabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
|
export type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
|
||||||
|
|
||||||
export type EncryptedKey = { encryptedKey: string, };
|
export type EncryptedKey = { encryptedKey: string };
|
||||||
|
|
||||||
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null,
|
export type Environment = {
|
||||||
/**
|
model: "environment";
|
||||||
* Variables defined in this environment scope.
|
id: string;
|
||||||
* Child environments override parent variables by name.
|
workspaceId: string;
|
||||||
*/
|
createdAt: string;
|
||||||
variables: Array<EnvironmentVariable>, color: string | null, sortPriority: number, };
|
updatedAt: string;
|
||||||
|
name: string;
|
||||||
|
public: boolean;
|
||||||
|
parentModel: string;
|
||||||
|
parentId: string | null;
|
||||||
|
/**
|
||||||
|
* Variables defined in this environment scope.
|
||||||
|
* Child environments override parent variables by name.
|
||||||
|
*/
|
||||||
|
variables: Array<EnvironmentVariable>;
|
||||||
|
color: string | null;
|
||||||
|
sortPriority: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
|
export type EnvironmentVariable = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
|
|
||||||
export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, name: string, sortPriority: number, settingSendCookies: InheritedBoolSetting, settingStoreCookies: InheritedBoolSetting, settingValidateCertificates: InheritedBoolSetting, settingFollowRedirects: InheritedBoolSetting, settingRequestTimeout: InheritedIntSetting, settingRequestMessageSize: InheritedIntSetting, };
|
export type Folder = {
|
||||||
|
model: "folder";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
folderId: string | null;
|
||||||
|
authentication: Record<string, any>;
|
||||||
|
authenticationType: string | null;
|
||||||
|
description: string;
|
||||||
|
headers: Array<HttpRequestHeader>;
|
||||||
|
name: string;
|
||||||
|
sortPriority: number;
|
||||||
|
settingSendCookies: InheritedBoolSetting;
|
||||||
|
settingStoreCookies: InheritedBoolSetting;
|
||||||
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
|
};
|
||||||
|
|
||||||
export type GraphQlIntrospection = { model: "graphql_introspection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, content: string | null, };
|
export type GraphQlIntrospection = {
|
||||||
|
model: "graphql_introspection";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
requestId: string;
|
||||||
|
content: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type GrpcConnection = { model: "grpc_connection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, elapsed: number, error: string | null, method: string, service: string, status: number, state: GrpcConnectionState, trailers: { [key in string]?: string }, url: string, };
|
export type GrpcConnection = {
|
||||||
|
model: "grpc_connection";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
requestId: string;
|
||||||
|
elapsed: number;
|
||||||
|
error: string | null;
|
||||||
|
method: string;
|
||||||
|
service: string;
|
||||||
|
status: number;
|
||||||
|
state: GrpcConnectionState;
|
||||||
|
trailers: { [key in string]?: string };
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type GrpcConnectionState = "initialized" | "connected" | "closed";
|
export type GrpcConnectionState = "initialized" | "connected" | "closed";
|
||||||
|
|
||||||
export type GrpcEvent = { model: "grpc_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, connectionId: string, content: string, error: string | null, eventType: GrpcEventType, metadata: { [key in string]?: string }, status: number | null, };
|
export type GrpcEvent = {
|
||||||
|
model: "grpc_event";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
requestId: string;
|
||||||
|
connectionId: string;
|
||||||
|
content: string;
|
||||||
|
error: string | null;
|
||||||
|
eventType: GrpcEventType;
|
||||||
|
metadata: { [key in string]?: string };
|
||||||
|
status: number | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type GrpcEventType = "info" | "error" | "client_message" | "server_message" | "connection_start" | "connection_end";
|
export type GrpcEventType =
|
||||||
|
| "info"
|
||||||
|
| "error"
|
||||||
|
| "client_message"
|
||||||
|
| "server_message"
|
||||||
|
| "connection_start"
|
||||||
|
| "connection_end";
|
||||||
|
|
||||||
export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record<string, any>, description: string, message: string, metadata: Array<HttpRequestHeader>, method: string | null, name: string, service: string | null, sortPriority: number,
|
export type GrpcRequest = {
|
||||||
/**
|
model: "grpc_request";
|
||||||
* Server URL (http for plaintext or https for secure)
|
id: string;
|
||||||
*/
|
createdAt: string;
|
||||||
url: string, settingValidateCertificates: InheritedBoolSetting, settingRequestMessageSize: InheritedIntSetting, };
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
folderId: string | null;
|
||||||
|
authenticationType: string | null;
|
||||||
|
authentication: Record<string, any>;
|
||||||
|
description: string;
|
||||||
|
message: string;
|
||||||
|
metadata: Array<HttpRequestHeader>;
|
||||||
|
method: string | null;
|
||||||
|
name: string;
|
||||||
|
service: string | null;
|
||||||
|
sortPriority: number;
|
||||||
|
/**
|
||||||
|
* Server URL (http for plaintext or https for secure)
|
||||||
|
*/
|
||||||
|
url: string;
|
||||||
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
};
|
||||||
|
|
||||||
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, description: string, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string,
|
export type HttpRequest = {
|
||||||
/**
|
model: "http_request";
|
||||||
* URL parameters used for both path placeholders (`:id`) and query string entries.
|
id: string;
|
||||||
*/
|
createdAt: string;
|
||||||
urlParameters: Array<HttpUrlParameter>, settingSendCookies: InheritedBoolSetting, settingStoreCookies: InheritedBoolSetting, settingValidateCertificates: InheritedBoolSetting, settingFollowRedirects: InheritedBoolSetting, settingRequestTimeout: InheritedIntSetting, };
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
folderId: string | null;
|
||||||
|
authentication: Record<string, any>;
|
||||||
|
authenticationType: string | null;
|
||||||
|
body: Record<string, any>;
|
||||||
|
bodyType: string | null;
|
||||||
|
description: string;
|
||||||
|
headers: Array<HttpRequestHeader>;
|
||||||
|
method: string;
|
||||||
|
name: string;
|
||||||
|
sortPriority: number;
|
||||||
|
url: string;
|
||||||
|
/**
|
||||||
|
* URL parameters used for both path placeholders (`:id`) and query string entries.
|
||||||
|
*/
|
||||||
|
urlParameters: Array<HttpUrlParameter>;
|
||||||
|
settingSendCookies: InheritedBoolSetting;
|
||||||
|
settingStoreCookies: InheritedBoolSetting;
|
||||||
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
|
};
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, };
|
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
|
|
||||||
export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, contentLength: number | null, contentLengthCompressed: number | null, elapsed: number, elapsedHeaders: number, elapsedDns: number, error: string | null, headers: Array<HttpResponseHeader>, remoteAddr: string | null, requestContentLength: number | null, requestHeaders: Array<HttpResponseHeader>, status: number, statusReason: string | null, state: HttpResponseState, url: string, version: string | null, };
|
export type HttpResponse = {
|
||||||
|
model: "http_response";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
requestId: string;
|
||||||
|
contentLength: number | null;
|
||||||
|
contentLengthCompressed: number | null;
|
||||||
|
elapsed: number;
|
||||||
|
elapsedHeaders: number;
|
||||||
|
elapsedDns: number;
|
||||||
|
error: string | null;
|
||||||
|
headers: Array<HttpResponseHeader>;
|
||||||
|
remoteAddr: string | null;
|
||||||
|
requestContentLength: number | null;
|
||||||
|
requestHeaders: Array<HttpResponseHeader>;
|
||||||
|
status: number;
|
||||||
|
statusReason: string | null;
|
||||||
|
state: HttpResponseState;
|
||||||
|
url: string;
|
||||||
|
version: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type HttpResponseEvent = { model: "http_response_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, responseId: string, event: HttpResponseEventData, };
|
export type HttpResponseEvent = {
|
||||||
|
model: "http_response_event";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
responseId: string;
|
||||||
|
event: HttpResponseEventData;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializable representation of HTTP response events for DB storage.
|
* Serializable representation of HTTP response events for DB storage.
|
||||||
* This mirrors `yaak_http::sender::HttpResponseEvent` but with serde support.
|
* This mirrors `yaak_http::sender::HttpResponseEvent` but with serde support.
|
||||||
* The `From` impl is in yaak-http to avoid circular dependencies.
|
* The `From` impl is in yaak-http to avoid circular dependencies.
|
||||||
*/
|
*/
|
||||||
export type HttpResponseEventData = { "type": "setting", name: string, value: string, source_model?: string, source_id?: string, source_name?: string, } | { "type": "info", message: string, } | { "type": "redirect", url: string, status: number, behavior: string, dropped_body: boolean, dropped_headers: Array<string>, } | { "type": "send_url", method: string, scheme: string, username: string, password: string, host: string, port: number, path: string, query: string, fragment: string, } | { "type": "receive_url", version: string, status: string, } | { "type": "header_up", name: string, value: string, } | { "type": "header_down", name: string, value: string, } | { "type": "chunk_sent", bytes: number, } | { "type": "chunk_received", bytes: number, } | { "type": "dns_resolved", hostname: string, addresses: Array<string>, duration: bigint, overridden: boolean, };
|
export type HttpResponseEventData =
|
||||||
|
| {
|
||||||
|
type: "setting";
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
source_model?: string;
|
||||||
|
source_id?: string;
|
||||||
|
source_name?: string;
|
||||||
|
}
|
||||||
|
| { type: "info"; message: string }
|
||||||
|
| {
|
||||||
|
type: "redirect";
|
||||||
|
url: string;
|
||||||
|
status: number;
|
||||||
|
behavior: string;
|
||||||
|
dropped_body: boolean;
|
||||||
|
dropped_headers: Array<string>;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "send_url";
|
||||||
|
method: string;
|
||||||
|
scheme: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
host: string;
|
||||||
|
port: number;
|
||||||
|
path: string;
|
||||||
|
query: string;
|
||||||
|
fragment: string;
|
||||||
|
}
|
||||||
|
| { type: "receive_url"; version: string; status: string }
|
||||||
|
| { type: "header_up"; name: string; value: string }
|
||||||
|
| { type: "header_down"; name: string; value: string }
|
||||||
|
| { type: "chunk_sent"; bytes: number }
|
||||||
|
| { type: "chunk_received"; bytes: number }
|
||||||
|
| {
|
||||||
|
type: "dns_resolved";
|
||||||
|
hostname: string;
|
||||||
|
addresses: Array<string>;
|
||||||
|
duration: bigint;
|
||||||
|
overridden: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export type HttpResponseHeader = { name: string, value: string, };
|
export type HttpResponseHeader = { name: string; value: string };
|
||||||
|
|
||||||
export type HttpResponseState = "initialized" | "connected" | "closed";
|
export type HttpResponseState = "initialized" | "connected" | "closed";
|
||||||
|
|
||||||
/**
|
export type HttpUrlParameter = {
|
||||||
* The resolved send settings, values only: what an executor has to obey, with the sources
|
enabled?: boolean;
|
||||||
* (which model each came from) left behind in [`ResolvedHttpRequestSettings`]. This is what
|
/**
|
||||||
* crosses from a tab to the Yaak server, and what the server reads.
|
* Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
|
||||||
*/
|
* Other entries are appended as query parameters
|
||||||
export type HttpSendSettings = { validateCertificates: boolean, followRedirects: boolean,
|
*/
|
||||||
/**
|
name: string;
|
||||||
* Milliseconds. Zero or negative means no timeout.
|
value: string;
|
||||||
*/
|
id?: string;
|
||||||
timeoutMs: number, sendCookies: boolean, storeCookies: boolean, };
|
};
|
||||||
|
|
||||||
export type HttpUrlParameter = { enabled?: boolean,
|
export type HttpVersion = "auto" | "http1" | "http2";
|
||||||
/**
|
|
||||||
* Colon-prefixed parameters are treated as path parameters if they match, like `/users/:id`
|
|
||||||
* Other entries are appended as query parameters
|
|
||||||
*/
|
|
||||||
name: string, value: string, id?: string, };
|
|
||||||
|
|
||||||
export type InheritedBoolSetting = { enabled?: boolean, value: boolean, };
|
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
||||||
|
|
||||||
export type InheritedIntSetting = { enabled?: boolean, value: number, };
|
export type InheritedHttpVersionSetting = { enabled?: boolean; value: HttpVersion };
|
||||||
|
|
||||||
export type KeyValue = { model: "key_value", id: string, createdAt: string, updatedAt: string, key: string, namespace: string, value: string, };
|
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
||||||
|
|
||||||
export type Plugin = { model: "plugin", id: string, createdAt: string, updatedAt: string, checkedAt: string | null, directory: string, enabled: boolean, url: string | null, source: PluginSource, };
|
export type KeyValue = {
|
||||||
|
model: "key_value";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
key: string;
|
||||||
|
namespace: string;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Plugin = {
|
||||||
|
model: "plugin";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
checkedAt: string | null;
|
||||||
|
directory: string;
|
||||||
|
enabled: boolean;
|
||||||
|
url: string | null;
|
||||||
|
source: PluginSource;
|
||||||
|
};
|
||||||
|
|
||||||
export type PluginSource = "bundled" | "filesystem" | "registry";
|
export type PluginSource = "bundled" | "filesystem" | "registry";
|
||||||
|
|
||||||
export type ProxySetting = { "type": "enabled", http: string, https: string, auth: ProxySettingAuth | null, bypass: string, disabled: boolean, } | { "type": "disabled" };
|
export type ProxySetting =
|
||||||
|
| {
|
||||||
|
type: "enabled";
|
||||||
|
http: string;
|
||||||
|
https: string;
|
||||||
|
auth: ProxySettingAuth | null;
|
||||||
|
bypass: string;
|
||||||
|
disabled: boolean;
|
||||||
|
}
|
||||||
|
| { type: "disabled" };
|
||||||
|
|
||||||
export type ProxySettingAuth = { user: string, password: string, };
|
export type ProxySettingAuth = { user: string; password: string };
|
||||||
|
|
||||||
export type Settings = { model: "settings", id: string, createdAt: string, updatedAt: string, appearance: string, clientCertificates: Array<ClientCertificate>, coloredMethods: boolean, editorFont: string | null, editorFontSize: number, editorKeymap: EditorKeymap, editorSoftWrap: boolean, hideWindowControls: boolean, useNativeTitlebar: boolean, interfaceFont: string | null, interfaceFontSize: number, interfaceScale: number, openWorkspaceNewWindow: boolean | null, proxy: ProxySetting | null, themeDark: string, themeLight: string, updateChannel: string, hideLicenseBadge: boolean, promptFeedback: boolean, autoupdate: boolean, autoDownloadUpdates: boolean, checkNotifications: boolean, hotkeys: { [key in string]?: Array<string> }, };
|
export type Settings = {
|
||||||
|
model: "settings";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
appearance: string;
|
||||||
|
clientCertificates: Array<ClientCertificate>;
|
||||||
|
coloredMethods: boolean;
|
||||||
|
editorFont: string | null;
|
||||||
|
editorFontSize: number;
|
||||||
|
editorKeymap: EditorKeymap;
|
||||||
|
editorSoftWrap: boolean;
|
||||||
|
hideWindowControls: boolean;
|
||||||
|
useNativeTitlebar: boolean;
|
||||||
|
interfaceFont: string | null;
|
||||||
|
interfaceFontSize: number;
|
||||||
|
interfaceScale: number;
|
||||||
|
openWorkspaceNewWindow: boolean | null;
|
||||||
|
proxy: ProxySetting | null;
|
||||||
|
themeDark: string;
|
||||||
|
themeLight: string;
|
||||||
|
updateChannel: string;
|
||||||
|
hideLicenseBadge: boolean;
|
||||||
|
promptFeedback: boolean;
|
||||||
|
autoupdate: boolean;
|
||||||
|
autoDownloadUpdates: boolean;
|
||||||
|
checkNotifications: boolean;
|
||||||
|
hotkeys: { [key in string]?: Array<string> };
|
||||||
|
};
|
||||||
|
|
||||||
export type SyncModel = { "type": "workspace" } & Workspace | { "type": "environment" } & Environment | { "type": "folder" } & Folder | { "type": "http_request" } & HttpRequest | { "type": "grpc_request" } & GrpcRequest | { "type": "websocket_request" } & WebsocketRequest;
|
export type SyncModel =
|
||||||
|
| ({ type: "workspace" } & Workspace)
|
||||||
|
| ({ type: "environment" } & Environment)
|
||||||
|
| ({ type: "folder" } & Folder)
|
||||||
|
| ({ type: "http_request" } & HttpRequest)
|
||||||
|
| ({ type: "grpc_request" } & GrpcRequest)
|
||||||
|
| ({ type: "websocket_request" } & WebsocketRequest);
|
||||||
|
|
||||||
export type SyncState = { model: "sync_state", id: string, workspaceId: string, createdAt: string, updatedAt: string, flushedAt: string, modelId: string, checksum: string, relPath: string, syncDir: string, };
|
export type SyncState = {
|
||||||
|
model: "sync_state";
|
||||||
|
id: string;
|
||||||
|
workspaceId: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
flushedAt: string;
|
||||||
|
modelId: string;
|
||||||
|
checksum: string;
|
||||||
|
relPath: string;
|
||||||
|
syncDir: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type WebsocketConnection = { model: "websocket_connection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, elapsed: number, error: string | null, headers: Array<HttpResponseHeader>, state: WebsocketConnectionState, status: number, url: string, };
|
export type WebsocketConnection = {
|
||||||
|
model: "websocket_connection";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
requestId: string;
|
||||||
|
elapsed: number;
|
||||||
|
error: string | null;
|
||||||
|
headers: Array<HttpResponseHeader>;
|
||||||
|
state: WebsocketConnectionState;
|
||||||
|
status: number;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type WebsocketConnectionState = "initialized" | "connected" | "closing" | "closed";
|
export type WebsocketConnectionState = "initialized" | "connected" | "closing" | "closed";
|
||||||
|
|
||||||
export type WebsocketEvent = { model: "websocket_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, connectionId: string, isServer: boolean, message: Array<number>, messageType: WebsocketEventType, };
|
export type WebsocketEvent = {
|
||||||
|
model: "websocket_event";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
requestId: string;
|
||||||
|
connectionId: string;
|
||||||
|
isServer: boolean;
|
||||||
|
message: Array<number>;
|
||||||
|
messageType: WebsocketEventType;
|
||||||
|
};
|
||||||
|
|
||||||
export type WebsocketEventType = "binary" | "close" | "error" | "frame" | "open" | "ping" | "pong" | "text";
|
export type WebsocketEventType =
|
||||||
|
| "binary"
|
||||||
|
| "close"
|
||||||
|
| "error"
|
||||||
|
| "frame"
|
||||||
|
| "open"
|
||||||
|
| "ping"
|
||||||
|
| "pong"
|
||||||
|
| "text";
|
||||||
|
|
||||||
export type WebsocketRequest = { model: "websocket_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, message: string, name: string, sortPriority: number, url: string,
|
export type WebsocketRequest = {
|
||||||
/**
|
model: "websocket_request";
|
||||||
* URL parameters used for both path placeholders (`:id`) and query string entries.
|
id: string;
|
||||||
*/
|
createdAt: string;
|
||||||
urlParameters: Array<HttpUrlParameter>, settingSendCookies: InheritedBoolSetting, settingStoreCookies: InheritedBoolSetting, settingValidateCertificates: InheritedBoolSetting, settingRequestMessageSize: InheritedIntSetting, };
|
updatedAt: string;
|
||||||
|
workspaceId: string;
|
||||||
|
folderId: string | null;
|
||||||
|
authentication: Record<string, any>;
|
||||||
|
authenticationType: string | null;
|
||||||
|
description: string;
|
||||||
|
headers: Array<HttpRequestHeader>;
|
||||||
|
message: string;
|
||||||
|
name: string;
|
||||||
|
sortPriority: number;
|
||||||
|
url: string;
|
||||||
|
/**
|
||||||
|
* URL parameters used for both path placeholders (`:id`) and query string entries.
|
||||||
|
*/
|
||||||
|
urlParameters: Array<HttpUrlParameter>;
|
||||||
|
settingSendCookies: InheritedBoolSetting;
|
||||||
|
settingStoreCookies: InheritedBoolSetting;
|
||||||
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
};
|
||||||
|
|
||||||
export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, name: string, encryptionKeyChallenge: string | null, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, settingRequestMessageSize: number, settingDnsOverrides: Array<DnsOverride>, settingSendCookies: boolean, settingStoreCookies: boolean, };
|
export type Workspace = {
|
||||||
|
model: "workspace";
|
||||||
|
id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
authentication: Record<string, any>;
|
||||||
|
authenticationType: string | null;
|
||||||
|
description: string;
|
||||||
|
headers: Array<HttpRequestHeader>;
|
||||||
|
name: string;
|
||||||
|
encryptionKeyChallenge: string | null;
|
||||||
|
settingValidateCertificates: boolean;
|
||||||
|
settingFollowRedirects: boolean;
|
||||||
|
settingRequestTimeout: number;
|
||||||
|
settingRequestMessageSize: number;
|
||||||
|
settingDnsOverrides: Array<DnsOverride>;
|
||||||
|
settingSendCookies: boolean;
|
||||||
|
settingStoreCookies: boolean;
|
||||||
|
settingHttpVersion: HttpVersion;
|
||||||
|
};
|
||||||
|
|
||||||
export type WorkspaceMeta = { model: "workspace_meta", id: string, workspaceId: string, createdAt: string, updatedAt: string, encryptionKey: EncryptedKey | null, settingSyncDir: string | null, };
|
export type WorkspaceMeta = {
|
||||||
|
model: "workspace_meta";
|
||||||
|
id: string;
|
||||||
|
workspaceId: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
encryptionKey: EncryptedKey | null;
|
||||||
|
settingSyncDir: string | null;
|
||||||
|
};
|
||||||
|
|||||||
Generated
+7
@@ -47,6 +47,7 @@ export type Folder = {
|
|||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
settingRequestMessageSize: InheritedIntSetting;
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GrpcRequest = {
|
export type GrpcRequest = {
|
||||||
@@ -99,6 +100,7 @@ export type HttpRequest = {
|
|||||||
settingValidateCertificates: InheritedBoolSetting;
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
@@ -114,8 +116,12 @@ export type HttpUrlParameter = {
|
|||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type HttpVersion = "auto" | "http1" | "http2";
|
||||||
|
|
||||||
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
||||||
|
|
||||||
|
export type InheritedHttpVersionSetting = { enabled?: boolean; value: HttpVersion };
|
||||||
|
|
||||||
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
||||||
|
|
||||||
export type SyncModel =
|
export type SyncModel =
|
||||||
@@ -169,4 +175,5 @@ export type Workspace = {
|
|||||||
settingDnsOverrides: Array<DnsOverride>;
|
settingDnsOverrides: Array<DnsOverride>;
|
||||||
settingSendCookies: boolean;
|
settingSendCookies: boolean;
|
||||||
settingStoreCookies: boolean;
|
settingStoreCookies: boolean;
|
||||||
|
settingHttpVersion: HttpVersion;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::error::Result;
|
|||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
use reqwest::{Client, ClientBuilder, Proxy, redirect};
|
use reqwest::{Client, ClientBuilder, Proxy, redirect};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use yaak_models::models::DnsOverride;
|
use yaak_models::models::{DnsOverride, HttpVersion};
|
||||||
use yaak_tls::{
|
use yaak_tls::{
|
||||||
ClientCertificateConfig, NativeClientIdentity, get_tls_config, load_native_client_identity,
|
ClientCertificateConfig, NativeClientIdentity, get_tls_config, load_native_client_identity,
|
||||||
};
|
};
|
||||||
@@ -39,6 +39,7 @@ impl ConfiguredClient {
|
|||||||
/// supports TLS 1.0+ for legacy servers.
|
/// supports TLS 1.0+ for legacy servers.
|
||||||
fn build_native_tls_connector(
|
fn build_native_tls_connector(
|
||||||
client_cert: Option<ClientCertificateConfig>,
|
client_cert: Option<ClientCertificateConfig>,
|
||||||
|
http_version: HttpVersion,
|
||||||
) -> Result<native_tls::TlsConnector> {
|
) -> Result<native_tls::TlsConnector> {
|
||||||
let mut builder = native_tls::TlsConnector::builder();
|
let mut builder = native_tls::TlsConnector::builder();
|
||||||
builder.danger_accept_invalid_certs(true);
|
builder.danger_accept_invalid_certs(true);
|
||||||
@@ -46,7 +47,11 @@ fn build_native_tls_connector(
|
|||||||
builder.min_protocol_version(Some(native_tls::Protocol::Tlsv10));
|
builder.min_protocol_version(Some(native_tls::Protocol::Tlsv10));
|
||||||
// reqwest cannot add ALPN to a connector it did not build, so without this
|
// reqwest cannot add ALPN to a connector it did not build, so without this
|
||||||
// the native path would silently negotiate HTTP/1.1 for every request.
|
// the native path would silently negotiate HTTP/1.1 for every request.
|
||||||
builder.request_alpns(&["h2", "http/1.1"]);
|
match http_version {
|
||||||
|
HttpVersion::Auto => builder.request_alpns(&["h2", "http/1.1"]),
|
||||||
|
HttpVersion::Http1 => builder.request_alpns(&["http/1.1"]),
|
||||||
|
HttpVersion::Http2 => builder.request_alpns(&["h2"]),
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(identity) = build_native_tls_identity(client_cert)? {
|
if let Some(identity) = build_native_tls_identity(client_cert)? {
|
||||||
builder.identity(identity);
|
builder.identity(identity);
|
||||||
@@ -100,6 +105,7 @@ pub enum HttpConnectionProxySetting {
|
|||||||
pub struct HttpConnectionOptions {
|
pub struct HttpConnectionOptions {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub validate_certificates: bool,
|
pub validate_certificates: bool,
|
||||||
|
pub http_version: HttpVersion,
|
||||||
pub proxy: HttpConnectionProxySetting,
|
pub proxy: HttpConnectionProxySetting,
|
||||||
pub client_certificate: Option<ClientCertificateConfig>,
|
pub client_certificate: Option<ClientCertificateConfig>,
|
||||||
pub dns_overrides: Vec<DnsOverride>,
|
pub dns_overrides: Vec<DnsOverride>,
|
||||||
@@ -128,14 +134,28 @@ impl HttpConnectionOptions {
|
|||||||
// This is needed so we can emit DNS timing events for each request
|
// This is needed so we can emit DNS timing events for each request
|
||||||
.pool_max_idle_per_host(0);
|
.pool_max_idle_per_host(0);
|
||||||
|
|
||||||
|
match self.http_version {
|
||||||
|
HttpVersion::Auto => {}
|
||||||
|
HttpVersion::Http1 => client = client.http1_only(),
|
||||||
|
HttpVersion::Http2 => client = client.http2_prior_knowledge(),
|
||||||
|
}
|
||||||
|
|
||||||
// Configure TLS
|
// Configure TLS
|
||||||
if self.validate_certificates {
|
if self.validate_certificates {
|
||||||
// Use rustls with platform certificate verification (TLS 1.2+ only)
|
// Use rustls with platform certificate verification (TLS 1.2+ only)
|
||||||
let config = get_tls_config(true, true, self.client_certificate.clone())?;
|
let mut config = get_tls_config(true, true, self.client_certificate.clone())?;
|
||||||
|
// A forced version must also constrain ALPN, or the server may
|
||||||
|
// negotiate a protocol the client then refuses to speak
|
||||||
|
match self.http_version {
|
||||||
|
HttpVersion::Auto => {}
|
||||||
|
HttpVersion::Http1 => config.alpn_protocols = vec![b"http/1.1".to_vec()],
|
||||||
|
HttpVersion::Http2 => config.alpn_protocols = vec![b"h2".to_vec()],
|
||||||
|
}
|
||||||
client = client.use_preconfigured_tls(config);
|
client = client.use_preconfigured_tls(config);
|
||||||
} else {
|
} else {
|
||||||
// Use native TLS for maximum compatibility (supports TLS 1.0+)
|
// Use native TLS for maximum compatibility (supports TLS 1.0+)
|
||||||
let connector = build_native_tls_connector(self.client_certificate.clone())?;
|
let connector =
|
||||||
|
build_native_tls_connector(self.client_certificate.clone(), self.http_version)?;
|
||||||
client = client.use_preconfigured_tls(connector);
|
client = client.use_preconfigured_tls(connector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ impl HttpConnectionManager {
|
|||||||
|
|
||||||
pub async fn get_client(&self, opt: &HttpConnectionOptions) -> Result<CachedClient> {
|
pub async fn get_client(&self, opt: &HttpConnectionOptions) -> Result<CachedClient> {
|
||||||
let mut connections = self.connections.write().await;
|
let mut connections = self.connections.write().await;
|
||||||
let id = opt.id.clone();
|
// The key must include any per-request option that changes how the
|
||||||
|
// client is built, or a send after a settings change reuses a client
|
||||||
|
// built with the old value for up to the cache TTL.
|
||||||
|
let id = format!("{}::{}::{}", opt.id, opt.validate_certificates, opt.http_version);
|
||||||
|
|
||||||
// Clean old connections
|
// Clean old connections
|
||||||
connections.retain(|_, (_, last_used)| last_used.elapsed() <= self.ttl);
|
connections.retain(|_, (_, last_used)| last_used.elapsed() <= self.ttl);
|
||||||
|
|||||||
+16
-1
@@ -110,6 +110,7 @@ export type Folder = {
|
|||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
settingRequestMessageSize: InheritedIntSetting;
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GraphQlIntrospection = {
|
export type GraphQlIntrospection = {
|
||||||
@@ -214,6 +215,7 @@ export type HttpRequest = {
|
|||||||
settingValidateCertificates: InheritedBoolSetting;
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
@@ -318,6 +320,7 @@ export type HttpSendSettings = {
|
|||||||
timeoutMs: number;
|
timeoutMs: number;
|
||||||
sendCookies: boolean;
|
sendCookies: boolean;
|
||||||
storeCookies: boolean;
|
storeCookies: boolean;
|
||||||
|
httpVersion: HttpVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HttpUrlParameter = {
|
export type HttpUrlParameter = {
|
||||||
@@ -331,8 +334,12 @@ export type HttpUrlParameter = {
|
|||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type HttpVersion = "auto" | "http1" | "http2";
|
||||||
|
|
||||||
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
||||||
|
|
||||||
|
export type InheritedHttpVersionSetting = { enabled?: boolean; value: HttpVersion };
|
||||||
|
|
||||||
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
||||||
|
|
||||||
export type KeyValue = {
|
export type KeyValue = {
|
||||||
@@ -475,7 +482,14 @@ export type WebsocketEvent = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type WebsocketEventType =
|
export type WebsocketEventType =
|
||||||
"binary" | "close" | "error" | "frame" | "open" | "ping" | "pong" | "text";
|
| "binary"
|
||||||
|
| "close"
|
||||||
|
| "error"
|
||||||
|
| "frame"
|
||||||
|
| "open"
|
||||||
|
| "ping"
|
||||||
|
| "pong"
|
||||||
|
| "text";
|
||||||
|
|
||||||
export type WebsocketMessageType = "text" | "binary";
|
export type WebsocketMessageType = "text" | "binary";
|
||||||
|
|
||||||
@@ -522,6 +536,7 @@ export type Workspace = {
|
|||||||
settingDnsOverrides: Array<DnsOverride>;
|
settingDnsOverrides: Array<DnsOverride>;
|
||||||
settingSendCookies: boolean;
|
settingSendCookies: boolean;
|
||||||
settingStoreCookies: boolean;
|
settingStoreCookies: boolean;
|
||||||
|
settingHttpVersion: HttpVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkspaceMeta = {
|
export type WorkspaceMeta = {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE workspaces ADD COLUMN setting_http_version TEXT DEFAULT 'auto' NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE folders ADD COLUMN setting_http_version TEXT DEFAULT '{"enabled":false,"value":"auto"}' NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE http_requests ADD COLUMN setting_http_version TEXT DEFAULT '{"enabled":false,"value":"auto"}' NOT NULL;
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::models::HttpRequestIden::{
|
use crate::models::HttpRequestIden::{
|
||||||
Authentication, AuthenticationType, Body, BodyType, CreatedAt, Description, FolderId, Headers,
|
Authentication, AuthenticationType, Body, BodyType, CreatedAt, Description, FolderId, Headers,
|
||||||
Method, Name, SettingFollowRedirects, SettingRequestTimeout, SettingSendCookies,
|
Method, Name, SettingFollowRedirects, SettingHttpVersion, SettingRequestTimeout,
|
||||||
SettingStoreCookies, SettingValidateCertificates, SortPriority, UpdatedAt, Url, UrlParameters,
|
SettingSendCookies, SettingStoreCookies, SettingValidateCertificates, SortPriority, UpdatedAt,
|
||||||
WorkspaceId,
|
Url, UrlParameters, WorkspaceId,
|
||||||
};
|
};
|
||||||
use crate::util::generate_prefixed_id;
|
use crate::util::generate_prefixed_id;
|
||||||
use chrono::{NaiveDateTime, Utc};
|
use chrono::{NaiveDateTime, Utc};
|
||||||
@@ -143,6 +143,7 @@ pub struct ResolvedHttpRequestSettings {
|
|||||||
pub request_message_size: ResolvedSetting<i32>,
|
pub request_message_size: ResolvedSetting<i32>,
|
||||||
pub send_cookies: ResolvedSetting<bool>,
|
pub send_cookies: ResolvedSetting<bool>,
|
||||||
pub store_cookies: ResolvedSetting<bool>,
|
pub store_cookies: ResolvedSetting<bool>,
|
||||||
|
pub http_version: ResolvedSetting<HttpVersion>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ResolvedHttpRequestSettings {
|
impl Default for ResolvedHttpRequestSettings {
|
||||||
@@ -154,6 +155,7 @@ impl Default for ResolvedHttpRequestSettings {
|
|||||||
request_message_size: ResolvedSetting::default_source(DEFAULT_REQUEST_MESSAGE_SIZE),
|
request_message_size: ResolvedSetting::default_source(DEFAULT_REQUEST_MESSAGE_SIZE),
|
||||||
send_cookies: ResolvedSetting::default_source(true),
|
send_cookies: ResolvedSetting::default_source(true),
|
||||||
store_cookies: ResolvedSetting::default_source(true),
|
store_cookies: ResolvedSetting::default_source(true),
|
||||||
|
http_version: ResolvedSetting::default_source(HttpVersion::Auto),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,6 +193,7 @@ impl ResolvedHttpRequestSettings {
|
|||||||
event("timeout", timeout, &self.request_timeout),
|
event("timeout", timeout, &self.request_timeout),
|
||||||
event("send_cookies", self.send_cookies.value.to_string(), &self.send_cookies),
|
event("send_cookies", self.send_cookies.value.to_string(), &self.send_cookies),
|
||||||
event("store_cookies", self.store_cookies.value.to_string(), &self.store_cookies),
|
event("store_cookies", self.store_cookies.value.to_string(), &self.store_cookies),
|
||||||
|
event("http_version", self.http_version.value.to_string(), &self.http_version),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,6 +211,8 @@ pub struct HttpSendSettings {
|
|||||||
pub timeout_ms: i32,
|
pub timeout_ms: i32,
|
||||||
pub send_cookies: bool,
|
pub send_cookies: bool,
|
||||||
pub store_cookies: bool,
|
pub store_cookies: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub http_version: HttpVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&ResolvedHttpRequestSettings> for HttpSendSettings {
|
impl From<&ResolvedHttpRequestSettings> for HttpSendSettings {
|
||||||
@@ -218,6 +223,7 @@ impl From<&ResolvedHttpRequestSettings> for HttpSendSettings {
|
|||||||
timeout_ms: s.request_timeout.value,
|
timeout_ms: s.request_timeout.value,
|
||||||
send_cookies: s.send_cookies.value,
|
send_cookies: s.send_cookies.value,
|
||||||
store_cookies: s.store_cookies.value,
|
store_cookies: s.store_cookies.value,
|
||||||
|
http_version: s.http_version.value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,6 +261,49 @@ impl Default for InheritedIntSetting {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema, TS)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[ts(export, export_to = "gen_models.ts")]
|
||||||
|
pub enum HttpVersion {
|
||||||
|
#[default]
|
||||||
|
Auto,
|
||||||
|
Http1,
|
||||||
|
Http2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for HttpVersion {
|
||||||
|
type Err = crate::error::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self> {
|
||||||
|
match s {
|
||||||
|
"http1" => Ok(Self::Http1),
|
||||||
|
"http2" => Ok(Self::Http2),
|
||||||
|
_ => Ok(Self::Auto),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for HttpVersion {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let str = match self {
|
||||||
|
HttpVersion::Auto => "auto",
|
||||||
|
HttpVersion::Http1 => "http1",
|
||||||
|
HttpVersion::Http2 => "http2",
|
||||||
|
};
|
||||||
|
write!(f, "{}", str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize, JsonSchema, TS)]
|
||||||
|
#[serde(default, rename_all = "camelCase")]
|
||||||
|
#[ts(export, export_to = "gen_models.ts")]
|
||||||
|
pub struct InheritedHttpVersionSetting {
|
||||||
|
#[serde(default)]
|
||||||
|
#[ts(optional, as = "Option<bool>")]
|
||||||
|
pub enabled: bool,
|
||||||
|
pub value: HttpVersion,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
#[ts(export, export_to = "gen_models.ts")]
|
#[ts(export, export_to = "gen_models.ts")]
|
||||||
@@ -484,6 +533,7 @@ impl Default for Workspace {
|
|||||||
setting_dns_overrides: Vec::new(),
|
setting_dns_overrides: Vec::new(),
|
||||||
setting_send_cookies: true,
|
setting_send_cookies: true,
|
||||||
setting_store_cookies: true,
|
setting_store_cookies: true,
|
||||||
|
setting_http_version: HttpVersion::Auto,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -516,6 +566,7 @@ pub struct Workspace {
|
|||||||
pub setting_dns_overrides: Vec<DnsOverride>,
|
pub setting_dns_overrides: Vec<DnsOverride>,
|
||||||
pub setting_send_cookies: bool,
|
pub setting_send_cookies: bool,
|
||||||
pub setting_store_cookies: bool,
|
pub setting_store_cookies: bool,
|
||||||
|
pub setting_http_version: HttpVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpsertModelInfo for Workspace {
|
impl UpsertModelInfo for Workspace {
|
||||||
@@ -560,6 +611,7 @@ impl UpsertModelInfo for Workspace {
|
|||||||
(SettingDnsOverrides, serde_json::to_string(&self.setting_dns_overrides)?.into()),
|
(SettingDnsOverrides, serde_json::to_string(&self.setting_dns_overrides)?.into()),
|
||||||
(SettingSendCookies, self.setting_send_cookies.into()),
|
(SettingSendCookies, self.setting_send_cookies.into()),
|
||||||
(SettingStoreCookies, self.setting_store_cookies.into()),
|
(SettingStoreCookies, self.setting_store_cookies.into()),
|
||||||
|
(SettingHttpVersion, self.setting_http_version.to_string().into()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,6 +631,7 @@ impl UpsertModelInfo for Workspace {
|
|||||||
WorkspaceIden::SettingDnsOverrides,
|
WorkspaceIden::SettingDnsOverrides,
|
||||||
WorkspaceIden::SettingSendCookies,
|
WorkspaceIden::SettingSendCookies,
|
||||||
WorkspaceIden::SettingStoreCookies,
|
WorkspaceIden::SettingStoreCookies,
|
||||||
|
WorkspaceIden::SettingHttpVersion,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,6 +642,7 @@ impl UpsertModelInfo for Workspace {
|
|||||||
let headers: String = row.get("headers")?;
|
let headers: String = row.get("headers")?;
|
||||||
let authentication: String = row.get("authentication")?;
|
let authentication: String = row.get("authentication")?;
|
||||||
let setting_dns_overrides: String = row.get("setting_dns_overrides")?;
|
let setting_dns_overrides: String = row.get("setting_dns_overrides")?;
|
||||||
|
let setting_http_version: String = row.get("setting_http_version")?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: row.get("id")?,
|
id: row.get("id")?,
|
||||||
model: row.get("model")?,
|
model: row.get("model")?,
|
||||||
@@ -607,6 +661,7 @@ impl UpsertModelInfo for Workspace {
|
|||||||
setting_dns_overrides: serde_json::from_str(&setting_dns_overrides).unwrap_or_default(),
|
setting_dns_overrides: serde_json::from_str(&setting_dns_overrides).unwrap_or_default(),
|
||||||
setting_send_cookies: row.get("setting_send_cookies")?,
|
setting_send_cookies: row.get("setting_send_cookies")?,
|
||||||
setting_store_cookies: row.get("setting_store_cookies")?,
|
setting_store_cookies: row.get("setting_store_cookies")?,
|
||||||
|
setting_http_version: setting_http_version.parse().unwrap_or_default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1078,6 +1133,7 @@ impl Default for Folder {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
value: DEFAULT_REQUEST_MESSAGE_SIZE,
|
value: DEFAULT_REQUEST_MESSAGE_SIZE,
|
||||||
},
|
},
|
||||||
|
setting_http_version: InheritedHttpVersionSetting::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1108,6 +1164,7 @@ pub struct Folder {
|
|||||||
pub setting_follow_redirects: InheritedBoolSetting,
|
pub setting_follow_redirects: InheritedBoolSetting,
|
||||||
pub setting_request_timeout: InheritedIntSetting,
|
pub setting_request_timeout: InheritedIntSetting,
|
||||||
pub setting_request_message_size: InheritedIntSetting,
|
pub setting_request_message_size: InheritedIntSetting,
|
||||||
|
pub setting_http_version: InheritedHttpVersionSetting,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpsertModelInfo for Folder {
|
impl UpsertModelInfo for Folder {
|
||||||
@@ -1159,6 +1216,7 @@ impl UpsertModelInfo for Folder {
|
|||||||
SettingRequestMessageSize,
|
SettingRequestMessageSize,
|
||||||
serde_json::to_string(&self.setting_request_message_size)?.into(),
|
serde_json::to_string(&self.setting_request_message_size)?.into(),
|
||||||
),
|
),
|
||||||
|
(SettingHttpVersion, serde_json::to_string(&self.setting_http_version)?.into()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1178,6 +1236,7 @@ impl UpsertModelInfo for Folder {
|
|||||||
FolderIden::SettingFollowRedirects,
|
FolderIden::SettingFollowRedirects,
|
||||||
FolderIden::SettingRequestTimeout,
|
FolderIden::SettingRequestTimeout,
|
||||||
FolderIden::SettingRequestMessageSize,
|
FolderIden::SettingRequestMessageSize,
|
||||||
|
FolderIden::SettingHttpVersion,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1193,6 +1252,7 @@ impl UpsertModelInfo for Folder {
|
|||||||
let setting_follow_redirects: String = row.get("setting_follow_redirects")?;
|
let setting_follow_redirects: String = row.get("setting_follow_redirects")?;
|
||||||
let setting_request_timeout: String = row.get("setting_request_timeout")?;
|
let setting_request_timeout: String = row.get("setting_request_timeout")?;
|
||||||
let setting_request_message_size: String = row.get("setting_request_message_size")?;
|
let setting_request_message_size: String = row.get("setting_request_message_size")?;
|
||||||
|
let setting_http_version: String = row.get("setting_http_version")?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: row.get("id")?,
|
id: row.get("id")?,
|
||||||
model: row.get("model")?,
|
model: row.get("model")?,
|
||||||
@@ -1216,6 +1276,7 @@ impl UpsertModelInfo for Folder {
|
|||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
setting_request_message_size: serde_json::from_str(&setting_request_message_size)
|
setting_request_message_size: serde_json::from_str(&setting_request_message_size)
|
||||||
.unwrap_or_else(|_| default_request_message_size_setting()),
|
.unwrap_or_else(|_| default_request_message_size_setting()),
|
||||||
|
setting_http_version: serde_json::from_str(&setting_http_version).unwrap_or_default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1283,6 +1344,7 @@ impl Default for HttpRequest {
|
|||||||
setting_validate_certificates: InheritedBoolSetting::default(),
|
setting_validate_certificates: InheritedBoolSetting::default(),
|
||||||
setting_follow_redirects: InheritedBoolSetting::default(),
|
setting_follow_redirects: InheritedBoolSetting::default(),
|
||||||
setting_request_timeout: InheritedIntSetting::default(),
|
setting_request_timeout: InheritedIntSetting::default(),
|
||||||
|
setting_http_version: InheritedHttpVersionSetting::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1319,6 +1381,7 @@ pub struct HttpRequest {
|
|||||||
pub setting_validate_certificates: InheritedBoolSetting,
|
pub setting_validate_certificates: InheritedBoolSetting,
|
||||||
pub setting_follow_redirects: InheritedBoolSetting,
|
pub setting_follow_redirects: InheritedBoolSetting,
|
||||||
pub setting_request_timeout: InheritedIntSetting,
|
pub setting_request_timeout: InheritedIntSetting,
|
||||||
|
pub setting_http_version: InheritedHttpVersionSetting,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpsertModelInfo for HttpRequest {
|
impl UpsertModelInfo for HttpRequest {
|
||||||
@@ -1370,6 +1433,7 @@ impl UpsertModelInfo for HttpRequest {
|
|||||||
),
|
),
|
||||||
(SettingFollowRedirects, serde_json::to_string(&self.setting_follow_redirects)?.into()),
|
(SettingFollowRedirects, serde_json::to_string(&self.setting_follow_redirects)?.into()),
|
||||||
(SettingRequestTimeout, serde_json::to_string(&self.setting_request_timeout)?.into()),
|
(SettingRequestTimeout, serde_json::to_string(&self.setting_request_timeout)?.into()),
|
||||||
|
(SettingHttpVersion, serde_json::to_string(&self.setting_http_version)?.into()),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1394,6 +1458,7 @@ impl UpsertModelInfo for HttpRequest {
|
|||||||
SettingValidateCertificates,
|
SettingValidateCertificates,
|
||||||
SettingFollowRedirects,
|
SettingFollowRedirects,
|
||||||
SettingRequestTimeout,
|
SettingRequestTimeout,
|
||||||
|
SettingHttpVersion,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1407,6 +1472,7 @@ impl UpsertModelInfo for HttpRequest {
|
|||||||
let setting_validate_certificates: String = row.get("setting_validate_certificates")?;
|
let setting_validate_certificates: String = row.get("setting_validate_certificates")?;
|
||||||
let setting_follow_redirects: String = row.get("setting_follow_redirects")?;
|
let setting_follow_redirects: String = row.get("setting_follow_redirects")?;
|
||||||
let setting_request_timeout: String = row.get("setting_request_timeout")?;
|
let setting_request_timeout: String = row.get("setting_request_timeout")?;
|
||||||
|
let setting_http_version: String = row.get("setting_http_version")?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: row.get("id")?,
|
id: row.get("id")?,
|
||||||
model: row.get("model")?,
|
model: row.get("model")?,
|
||||||
@@ -1433,6 +1499,7 @@ impl UpsertModelInfo for HttpRequest {
|
|||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
setting_request_timeout: serde_json::from_str(&setting_request_timeout)
|
setting_request_timeout: serde_json::from_str(&setting_request_timeout)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
setting_http_version: serde_json::from_str(&setting_http_version).unwrap_or_default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,6 +208,14 @@ impl<'a> ClientDb<'a> {
|
|||||||
} else {
|
} else {
|
||||||
parent.store_cookies
|
parent.store_cookies
|
||||||
},
|
},
|
||||||
|
http_version: if folder.setting_http_version.enabled {
|
||||||
|
ResolvedSetting::from_model(
|
||||||
|
folder.setting_http_version.value,
|
||||||
|
AnyModel::Folder(folder.clone()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
parent.http_version
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,6 +153,14 @@ impl<'a> ClientDb<'a> {
|
|||||||
} else {
|
} else {
|
||||||
parent.store_cookies
|
parent.store_cookies
|
||||||
},
|
},
|
||||||
|
http_version: if http_request.setting_http_version.enabled {
|
||||||
|
ResolvedSetting::from_model(
|
||||||
|
http_request.setting_http_version.value,
|
||||||
|
AnyModel::HttpRequest(http_request.clone()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
parent.http_version
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +182,10 @@ impl<'a> ClientDb<'a> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::init_in_memory;
|
use crate::init_in_memory;
|
||||||
use crate::models::{HttpRequest, HttpRequestHeader};
|
use crate::models::{
|
||||||
|
Folder, HttpRequest, HttpRequestHeader, HttpVersion, InheritedHttpVersionSetting, Workspace,
|
||||||
|
};
|
||||||
|
use crate::util::UpdateSource;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn request_resolution_preserves_duplicate_request_headers() {
|
fn request_resolution_preserves_duplicate_request_headers() {
|
||||||
@@ -210,4 +221,77 @@ mod tests {
|
|||||||
assert_eq!(cookies[1].value, "optional=1");
|
assert_eq!(cookies[1].value, "optional=1");
|
||||||
assert!(!cookies[1].enabled);
|
assert!(!cookies[1].enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn http_version_resolves_through_the_inheritance_chain() {
|
||||||
|
let (query_manager, _blob_manager, _rx) = init_in_memory().expect("Failed to init DB");
|
||||||
|
let db = query_manager.connect();
|
||||||
|
|
||||||
|
let workspace = db
|
||||||
|
.upsert_workspace(
|
||||||
|
&Workspace {
|
||||||
|
name: "Test".to_string(),
|
||||||
|
setting_http_version: HttpVersion::Http2,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&UpdateSource::Background,
|
||||||
|
)
|
||||||
|
.expect("Failed to upsert workspace");
|
||||||
|
|
||||||
|
let folder = db
|
||||||
|
.upsert_folder(
|
||||||
|
&Folder { workspace_id: workspace.id.clone(), ..Default::default() },
|
||||||
|
&UpdateSource::Background,
|
||||||
|
)
|
||||||
|
.expect("Failed to upsert folder");
|
||||||
|
|
||||||
|
let request = db
|
||||||
|
.upsert_http_request(
|
||||||
|
&HttpRequest {
|
||||||
|
workspace_id: workspace.id.clone(),
|
||||||
|
folder_id: Some(folder.id.clone()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
&UpdateSource::Background,
|
||||||
|
)
|
||||||
|
.expect("Failed to upsert request");
|
||||||
|
|
||||||
|
// No overrides, so the workspace base value applies
|
||||||
|
let resolved = db.resolve_settings_for_http_request(&request).expect("Failed to resolve");
|
||||||
|
assert_eq!(resolved.http_version.value, HttpVersion::Http2);
|
||||||
|
assert_eq!(resolved.http_version.source_model, "workspace");
|
||||||
|
|
||||||
|
// A folder override beats the workspace base
|
||||||
|
db.upsert_folder(
|
||||||
|
&Folder {
|
||||||
|
setting_http_version: InheritedHttpVersionSetting {
|
||||||
|
enabled: true,
|
||||||
|
value: HttpVersion::Http1,
|
||||||
|
},
|
||||||
|
..folder
|
||||||
|
},
|
||||||
|
&UpdateSource::Background,
|
||||||
|
)
|
||||||
|
.expect("Failed to update folder");
|
||||||
|
let resolved = db.resolve_settings_for_http_request(&request).expect("Failed to resolve");
|
||||||
|
assert_eq!(resolved.http_version.value, HttpVersion::Http1);
|
||||||
|
assert_eq!(resolved.http_version.source_model, "folder");
|
||||||
|
|
||||||
|
// A request override beats them both
|
||||||
|
let request = db
|
||||||
|
.upsert_http_request(
|
||||||
|
&HttpRequest {
|
||||||
|
setting_http_version: InheritedHttpVersionSetting {
|
||||||
|
enabled: true,
|
||||||
|
value: HttpVersion::Auto,
|
||||||
|
},
|
||||||
|
..request
|
||||||
|
},
|
||||||
|
&UpdateSource::Background,
|
||||||
|
)
|
||||||
|
.expect("Failed to update request");
|
||||||
|
let resolved = db.resolve_settings_for_http_request(&request).expect("Failed to resolve");
|
||||||
|
assert_eq!(resolved.http_version.value, HttpVersion::Auto);
|
||||||
|
assert_eq!(resolved.http_version.source_model, "http_request");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ impl<'a> ClientDb<'a> {
|
|||||||
deleted
|
deleted
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = conn
|
let _ =
|
||||||
.execute_batch("ROLLBACK TO delete_workspace; RELEASE delete_workspace");
|
conn.execute_batch("ROLLBACK TO delete_workspace; RELEASE delete_workspace");
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -177,6 +177,10 @@ impl<'a> ClientDb<'a> {
|
|||||||
workspace.setting_store_cookies,
|
workspace.setting_store_cookies,
|
||||||
AnyModel::Workspace(workspace.clone()),
|
AnyModel::Workspace(workspace.clone()),
|
||||||
),
|
),
|
||||||
|
http_version: ResolvedSetting::from_model(
|
||||||
|
workspace.setting_http_version,
|
||||||
|
AnyModel::Workspace(workspace.clone()),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-1
@@ -109,6 +109,7 @@ export type Folder = {
|
|||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
settingRequestMessageSize: InheritedIntSetting;
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GraphQlIntrospection = {
|
export type GraphQlIntrospection = {
|
||||||
@@ -213,6 +214,7 @@ export type HttpRequest = {
|
|||||||
settingValidateCertificates: InheritedBoolSetting;
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
@@ -314,8 +316,12 @@ export type HttpUrlParameter = {
|
|||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type HttpVersion = "auto" | "http1" | "http2";
|
||||||
|
|
||||||
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
||||||
|
|
||||||
|
export type InheritedHttpVersionSetting = { enabled?: boolean; value: HttpVersion };
|
||||||
|
|
||||||
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
||||||
|
|
||||||
export type KeyValue = {
|
export type KeyValue = {
|
||||||
@@ -378,6 +384,7 @@ export type Settings = {
|
|||||||
themeLight: string;
|
themeLight: string;
|
||||||
updateChannel: string;
|
updateChannel: string;
|
||||||
hideLicenseBadge: boolean;
|
hideLicenseBadge: boolean;
|
||||||
|
promptFeedback: boolean;
|
||||||
autoupdate: boolean;
|
autoupdate: boolean;
|
||||||
autoDownloadUpdates: boolean;
|
autoDownloadUpdates: boolean;
|
||||||
checkNotifications: boolean;
|
checkNotifications: boolean;
|
||||||
@@ -428,7 +435,14 @@ export type WebsocketEvent = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type WebsocketEventType =
|
export type WebsocketEventType =
|
||||||
"binary" | "close" | "error" | "frame" | "open" | "ping" | "pong" | "text";
|
| "binary"
|
||||||
|
| "close"
|
||||||
|
| "error"
|
||||||
|
| "frame"
|
||||||
|
| "open"
|
||||||
|
| "ping"
|
||||||
|
| "pong"
|
||||||
|
| "text";
|
||||||
|
|
||||||
export type WebsocketRequest = {
|
export type WebsocketRequest = {
|
||||||
model: "websocket_request";
|
model: "websocket_request";
|
||||||
@@ -473,6 +487,7 @@ export type Workspace = {
|
|||||||
settingDnsOverrides: Array<DnsOverride>;
|
settingDnsOverrides: Array<DnsOverride>;
|
||||||
settingSendCookies: boolean;
|
settingSendCookies: boolean;
|
||||||
settingStoreCookies: boolean;
|
settingStoreCookies: boolean;
|
||||||
|
settingHttpVersion: HttpVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkspaceMeta = {
|
export type WorkspaceMeta = {
|
||||||
|
|||||||
Generated
+7
@@ -47,6 +47,7 @@ export type Folder = {
|
|||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
settingRequestMessageSize: InheritedIntSetting;
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GrpcRequest = {
|
export type GrpcRequest = {
|
||||||
@@ -99,6 +100,7 @@ export type HttpRequest = {
|
|||||||
settingValidateCertificates: InheritedBoolSetting;
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
@@ -114,8 +116,12 @@ export type HttpUrlParameter = {
|
|||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type HttpVersion = "auto" | "http1" | "http2";
|
||||||
|
|
||||||
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
||||||
|
|
||||||
|
export type InheritedHttpVersionSetting = { enabled?: boolean; value: HttpVersion };
|
||||||
|
|
||||||
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
||||||
|
|
||||||
export type SyncModel =
|
export type SyncModel =
|
||||||
@@ -182,4 +188,5 @@ export type Workspace = {
|
|||||||
settingDnsOverrides: Array<DnsOverride>;
|
settingDnsOverrides: Array<DnsOverride>;
|
||||||
settingSendCookies: boolean;
|
settingSendCookies: boolean;
|
||||||
settingStoreCookies: boolean;
|
settingStoreCookies: boolean;
|
||||||
|
settingHttpVersion: HttpVersion;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ impl SendRequestExecutor for ConnectionManagerSendRequestExecutor<'_> {
|
|||||||
.get_client(&HttpConnectionOptions {
|
.get_client(&HttpConnectionOptions {
|
||||||
id: self.plugin_context_id.clone(),
|
id: self.plugin_context_id.clone(),
|
||||||
validate_certificates: runtime_config.settings.validate_certificates.value,
|
validate_certificates: runtime_config.settings.validate_certificates.value,
|
||||||
|
http_version: runtime_config.settings.http_version.value,
|
||||||
proxy: runtime_config.proxy.clone(),
|
proxy: runtime_config.proxy.clone(),
|
||||||
client_certificate,
|
client_certificate,
|
||||||
dns_overrides: runtime_config.dns_overrides.clone(),
|
dns_overrides: runtime_config.dns_overrides.clone(),
|
||||||
|
|||||||
+16
-1
@@ -109,6 +109,7 @@ export type Folder = {
|
|||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
settingRequestMessageSize: InheritedIntSetting;
|
settingRequestMessageSize: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GraphQlIntrospection = {
|
export type GraphQlIntrospection = {
|
||||||
@@ -213,6 +214,7 @@ export type HttpRequest = {
|
|||||||
settingValidateCertificates: InheritedBoolSetting;
|
settingValidateCertificates: InheritedBoolSetting;
|
||||||
settingFollowRedirects: InheritedBoolSetting;
|
settingFollowRedirects: InheritedBoolSetting;
|
||||||
settingRequestTimeout: InheritedIntSetting;
|
settingRequestTimeout: InheritedIntSetting;
|
||||||
|
settingHttpVersion: InheritedHttpVersionSetting;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id?: string };
|
||||||
@@ -314,8 +316,12 @@ export type HttpUrlParameter = {
|
|||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type HttpVersion = "auto" | "http1" | "http2";
|
||||||
|
|
||||||
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
export type InheritedBoolSetting = { enabled?: boolean; value: boolean };
|
||||||
|
|
||||||
|
export type InheritedHttpVersionSetting = { enabled?: boolean; value: HttpVersion };
|
||||||
|
|
||||||
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
export type InheritedIntSetting = { enabled?: boolean; value: number };
|
||||||
|
|
||||||
export type KeyValue = {
|
export type KeyValue = {
|
||||||
@@ -378,6 +384,7 @@ export type Settings = {
|
|||||||
themeLight: string;
|
themeLight: string;
|
||||||
updateChannel: string;
|
updateChannel: string;
|
||||||
hideLicenseBadge: boolean;
|
hideLicenseBadge: boolean;
|
||||||
|
promptFeedback: boolean;
|
||||||
autoupdate: boolean;
|
autoupdate: boolean;
|
||||||
autoDownloadUpdates: boolean;
|
autoDownloadUpdates: boolean;
|
||||||
checkNotifications: boolean;
|
checkNotifications: boolean;
|
||||||
@@ -428,7 +435,14 @@ export type WebsocketEvent = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type WebsocketEventType =
|
export type WebsocketEventType =
|
||||||
"binary" | "close" | "error" | "frame" | "open" | "ping" | "pong" | "text";
|
| "binary"
|
||||||
|
| "close"
|
||||||
|
| "error"
|
||||||
|
| "frame"
|
||||||
|
| "open"
|
||||||
|
| "ping"
|
||||||
|
| "pong"
|
||||||
|
| "text";
|
||||||
|
|
||||||
export type WebsocketRequest = {
|
export type WebsocketRequest = {
|
||||||
model: "websocket_request";
|
model: "websocket_request";
|
||||||
@@ -473,6 +487,7 @@ export type Workspace = {
|
|||||||
settingDnsOverrides: Array<DnsOverride>;
|
settingDnsOverrides: Array<DnsOverride>;
|
||||||
settingSendCookies: boolean;
|
settingSendCookies: boolean;
|
||||||
settingStoreCookies: boolean;
|
settingStoreCookies: boolean;
|
||||||
|
settingHttpVersion: HttpVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkspaceMeta = {
|
export type WorkspaceMeta = {
|
||||||
|
|||||||
Reference in New Issue
Block a user