mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-11 17:46:41 -05:00
Refactor default headers to be injected dynamically (#367)
This commit is contained in:
@@ -19,6 +19,7 @@ type Props = {
|
||||
forceUpdateKey: string;
|
||||
headers: HttpRequestHeader[];
|
||||
inheritedHeaders?: HttpRequestHeader[];
|
||||
inheritedHeadersLabel?: string;
|
||||
stateKey: string;
|
||||
onChange: (headers: HttpRequestHeader[]) => void;
|
||||
label?: string;
|
||||
@@ -28,11 +29,20 @@ export function HeadersEditor({
|
||||
stateKey,
|
||||
headers,
|
||||
inheritedHeaders,
|
||||
inheritedHeadersLabel = 'Inherited',
|
||||
onChange,
|
||||
forceUpdateKey,
|
||||
}: Props) {
|
||||
// Get header names defined at current level (case-insensitive)
|
||||
const currentHeaderNames = new Set(
|
||||
headers.filter((h) => h.name).map((h) => h.name.toLowerCase()),
|
||||
);
|
||||
// Filter inherited headers: must be enabled, have content, and not be overridden by current level
|
||||
const validInheritedHeaders =
|
||||
inheritedHeaders?.filter((pair) => pair.enabled && (pair.name || pair.value)) ?? [];
|
||||
inheritedHeaders?.filter(
|
||||
(pair) =>
|
||||
pair.enabled && (pair.name || pair.value) && !currentHeaderNames.has(pair.name.toLowerCase()),
|
||||
) ?? [];
|
||||
const hasInheritedHeaders = validInheritedHeaders.length > 0;
|
||||
return (
|
||||
<div
|
||||
@@ -48,7 +58,7 @@ export function HeadersEditor({
|
||||
className="text-sm"
|
||||
summary={
|
||||
<HStack>
|
||||
Inherited <CountBadge count={validInheritedHeaders.length} />
|
||||
{inheritedHeadersLabel} <CountBadge count={validInheritedHeaders.length} />
|
||||
</HStack>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -95,6 +95,7 @@ export function WorkspaceSettingsDialog({ workspaceId, hide, tab }: Props) {
|
||||
<TabContent value={TAB_HEADERS} className="overflow-y-auto h-full px-4">
|
||||
<HeadersEditor
|
||||
inheritedHeaders={inheritedHeaders}
|
||||
inheritedHeadersLabel="Defaults"
|
||||
forceUpdateKey={workspace.id}
|
||||
headers={workspace.headers}
|
||||
onChange={(headers) => patchModel(workspace, { headers })}
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
} from '@yaakapp-internal/models';
|
||||
import { foldersAtom, workspacesAtom } from '@yaakapp-internal/models';
|
||||
import { atom, useAtomValue } from 'jotai';
|
||||
import { defaultHeaders } from '../lib/defaultHeaders';
|
||||
|
||||
const ancestorsAtom = atom((get) => [...get(foldersAtom), ...get(workspacesAtom)]);
|
||||
|
||||
@@ -17,12 +18,12 @@ export function useInheritedHeaders(baseModel: HeaderModel | null) {
|
||||
const parents = useAtomValue(ancestorsAtom);
|
||||
|
||||
if (baseModel == null) return [];
|
||||
if (baseModel.model === 'workspace') return [];
|
||||
if (baseModel.model === 'workspace') return defaultHeaders;
|
||||
|
||||
const next = (child: HeaderModel): HttpRequestHeader[] => {
|
||||
// Short-circuit
|
||||
// Short-circuit at workspace level - return global defaults + workspace headers
|
||||
if (child.model === 'workspace') {
|
||||
return [];
|
||||
return [...defaultHeaders, ...child.headers];
|
||||
}
|
||||
|
||||
// Recurse up the tree
|
||||
@@ -40,5 +41,13 @@ export function useInheritedHeaders(baseModel: HeaderModel | null) {
|
||||
return [...headers, ...parent.headers];
|
||||
};
|
||||
|
||||
return next(baseModel);
|
||||
const allHeaders = next(baseModel);
|
||||
|
||||
// Deduplicate by header name (case-insensitive), keeping the latest (most specific) value
|
||||
const headersByName = new Map<string, HttpRequestHeader>();
|
||||
for (const header of allHeaders) {
|
||||
headersByName.set(header.name.toLowerCase(), header);
|
||||
}
|
||||
|
||||
return Array.from(headersByName.values());
|
||||
}
|
||||
|
||||
8
src-web/lib/defaultHeaders.ts
Normal file
8
src-web/lib/defaultHeaders.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import type { HttpRequestHeader } from '@yaakapp-internal/models';
|
||||
import { invokeCmd } from './tauri';
|
||||
|
||||
/**
|
||||
* Global default headers fetched from the backend.
|
||||
* These are static and fetched once on module load.
|
||||
*/
|
||||
export const defaultHeaders: HttpRequestHeader[] = await invokeCmd('cmd_default_headers');
|
||||
@@ -12,6 +12,7 @@ type TauriCmd =
|
||||
| 'cmd_create_grpc_request'
|
||||
| 'cmd_curl_to_request'
|
||||
| 'cmd_decrypt_template'
|
||||
| 'cmd_default_headers'
|
||||
| 'cmd_delete_all_grpc_connections'
|
||||
| 'cmd_delete_all_http_responses'
|
||||
| 'cmd_delete_send_history'
|
||||
|
||||
Reference in New Issue
Block a user