diff --git a/src-web/components/HeadersEditor.tsx b/src-web/components/HeadersEditor.tsx
index 05d08ac58..79dc12ea3 100644
--- a/src-web/components/HeadersEditor.tsx
+++ b/src-web/components/HeadersEditor.tsx
@@ -1,5 +1,7 @@
import type { HttpRequestHeader } from '@yaakapp-internal/models';
import type { GenericCompletionOption } from '@yaakapp-internal/plugins';
+import { Fragment } from 'react';
+import type { InheritedHeader } from '../hooks/useInheritedHeaders';
import { charsets } from '../lib/data/charsets';
import { connections } from '../lib/data/connections';
import { encodings } from '../lib/data/encodings';
@@ -8,6 +10,7 @@ import { mimeTypes } from '../lib/data/mimetypes';
import { CountBadge } from './core/CountBadge';
import { DetailsBanner } from './core/DetailsBanner';
import type { GenericCompletionConfig } from './core/Editor/genericCompletion';
+import { Icon } from './core/Icon';
import type { InputProps } from './core/Input';
import type { Pair, PairEditorProps } from './core/PairEditor';
import { PairEditorRow } from './core/PairEditor';
@@ -18,7 +21,7 @@ import { HStack } from './core/Stacks';
type Props = {
forceUpdateKey: string;
headers: HttpRequestHeader[];
- inheritedHeaders?: HttpRequestHeader[];
+ inheritedHeaders?: InheritedHeader[];
inheritedHeadersLabel?: string;
stateKey: string;
onChange: (headers: HttpRequestHeader[]) => void;
@@ -62,21 +65,29 @@ export function HeadersEditor({
}
>
-
+
{validInheritedHeaders?.map((pair, i) => (
-
+
+
+
+ {pair.source.model === 'default' && }
+ {pair.source.model === 'workspace' && }
+ {pair.source.model === 'workspace' && pair.source.name}
+ {pair.source.model === 'folder' && }
+ {pair.source.model === 'folder' && pair.source.name}
+
+
))}
diff --git a/src-web/hooks/useInheritedHeaders.ts b/src-web/hooks/useInheritedHeaders.ts
index a60610f05..b8447705b 100644
--- a/src-web/hooks/useInheritedHeaders.ts
+++ b/src-web/hooks/useInheritedHeaders.ts
@@ -14,16 +14,34 @@ const ancestorsAtom = atom((get) => [...get(foldersAtom), ...get(workspacesAtom)
export type HeaderModel = HttpRequest | GrpcRequest | WebsocketRequest | Folder | Workspace;
-export function useInheritedHeaders(baseModel: HeaderModel | null) {
+export type HeaderSource = {
+ id: string;
+ name: string;
+ model: 'workspace' | 'folder' | 'default';
+};
+
+export type InheritedHeader = HttpRequestHeader & {
+ source: HeaderSource;
+};
+
+export function useInheritedHeaders(baseModel: HeaderModel | null): InheritedHeader[] {
const parents = useAtomValue(ancestorsAtom);
+ const defaultSource: HeaderSource = { id: 'default', name: 'Default', model: 'default' };
+
if (baseModel == null) return [];
- if (baseModel.model === 'workspace') return defaultHeaders;
+ if (baseModel.model === 'workspace') {
+ return defaultHeaders.map((h) => ({ ...h, source: defaultSource }));
+ }
- const next = (child: HeaderModel): HttpRequestHeader[] => {
+ const next = (child: HeaderModel): InheritedHeader[] => {
// Short-circuit at workspace level - return global defaults + workspace headers
if (child.model === 'workspace') {
- return [...defaultHeaders, ...child.headers];
+ const workspaceSource: HeaderSource = { id: child.id, name: child.name, model: 'workspace' };
+ return [
+ ...defaultHeaders.map((h) => ({ ...h, source: defaultSource })),
+ ...child.headers.map((h) => ({ ...h, source: workspaceSource })),
+ ];
}
// Recurse up the tree
@@ -38,13 +56,18 @@ export function useInheritedHeaders(baseModel: HeaderModel | null) {
}
const headers = next(parent);
- return [...headers, ...parent.headers];
+ const parentSource: HeaderSource = {
+ id: parent.id,
+ name: parent.name,
+ model: parent.model as 'workspace' | 'folder',
+ };
+ return [...headers, ...parent.headers.map((h) => ({ ...h, source: parentSource }))];
};
const allHeaders = next(baseModel);
// Deduplicate by header name (case-insensitive), keeping the latest (most specific) value
- const headersByName = new Map
();
+ const headersByName = new Map();
for (const header of allHeaders) {
headersByName.set(header.name.toLowerCase(), header);
}