mirror of
https://github.com/aaif-goose/goose.git
synced 2026-07-03 14:10:03 +02:00
fix: preserve = characters in deeplink header values (#8434)
Signed-off-by: lawrence3699 <lawrence3699@users.noreply.github.com> Co-authored-by: lawrence3699 <lawrence3699@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { addExtensionFromDeepLink } from './deeplink';
|
||||
|
||||
vi.mock('../../../toasts', () => ({
|
||||
toastService: {
|
||||
handleError: vi.fn(),
|
||||
success: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('addExtensionFromDeepLink', () => {
|
||||
const mockAddExtension = vi.fn().mockResolvedValue(undefined);
|
||||
const mockSetView = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('header parsing', () => {
|
||||
it('should preserve = characters in header values', async () => {
|
||||
const url =
|
||||
'goose://extension?name=Remote&url=https%3A%2F%2Fexample.com%2Fmcp&header=Authorization%3DBasic%20abc%3D%3D';
|
||||
|
||||
await addExtensionFromDeepLink(url, mockAddExtension, mockSetView);
|
||||
|
||||
expect(mockSetView).toHaveBeenCalledWith(
|
||||
'extensions',
|
||||
expect.objectContaining({
|
||||
showEnvVars: true,
|
||||
deepLinkConfig: expect.objectContaining({
|
||||
headers: { Authorization: 'Basic abc==' },
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle header values without = characters', async () => {
|
||||
const url =
|
||||
'goose://extension?name=Remote&url=https%3A%2F%2Fexample.com%2Fmcp&header=X-Token%3Dabc123';
|
||||
|
||||
await addExtensionFromDeepLink(url, mockAddExtension, mockSetView);
|
||||
|
||||
expect(mockSetView).toHaveBeenCalledWith(
|
||||
'extensions',
|
||||
expect.objectContaining({
|
||||
deepLinkConfig: expect.objectContaining({
|
||||
headers: { 'X-Token': 'abc123' },
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle multiple headers', async () => {
|
||||
const url =
|
||||
'goose://extension?name=Remote&url=https%3A%2F%2Fexample.com%2Fmcp&header=Authorization%3DBearer%20tok%3D%3D&header=X-Key%3Dval';
|
||||
|
||||
await addExtensionFromDeepLink(url, mockAddExtension, mockSetView);
|
||||
|
||||
expect(mockSetView).toHaveBeenCalledWith(
|
||||
'extensions',
|
||||
expect.objectContaining({
|
||||
deepLinkConfig: expect.objectContaining({
|
||||
headers: {
|
||||
Authorization: 'Bearer tok==',
|
||||
'X-Key': 'val',
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle header with empty value', async () => {
|
||||
const url =
|
||||
'goose://extension?name=Remote&url=https%3A%2F%2Fexample.com%2Fmcp&header=X-Empty%3D';
|
||||
|
||||
await addExtensionFromDeepLink(url, mockAddExtension, mockSetView);
|
||||
|
||||
expect(mockSetView).toHaveBeenCalledWith(
|
||||
'extensions',
|
||||
expect.objectContaining({
|
||||
deepLinkConfig: expect.objectContaining({
|
||||
headers: { 'X-Empty': '' },
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -141,8 +141,8 @@ export async function addExtensionFromDeepLink(
|
||||
headerParams.length > 0
|
||||
? Object.fromEntries(
|
||||
headerParams.map((header) => {
|
||||
const [key, value] = header.split('=');
|
||||
return [key, decodeURIComponent(value || '')];
|
||||
const [key, ...rest] = header.split('=');
|
||||
return [key, decodeURIComponent(rest.join('=') || '')];
|
||||
})
|
||||
)
|
||||
: undefined;
|
||||
|
||||
Reference in New Issue
Block a user