Skip to content

Commit f29076e

Browse files
committed
refactor: improve URL handling and simplify types
- Add error handling for URL parameter parsing in App.vue - Improve extension detection in openUriStream.ts - Use basename() and lastIndexOf('.') for robust extension check - Prevents false positives from hidden files and URL domains
1 parent 52bc306 commit f29076e

File tree

4 files changed

+23
-17
lines changed

4 files changed

+23
-17
lines changed

src/components/App.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,15 @@ export default defineComponent({
147147
populateAuthorizationToken();
148148
stripTokenFromUrl();
149149
150-
const urlParams = normalizeUrlParams(
151-
vtkURLExtract.extractURLParameters() as UrlParams
152-
);
150+
let urlParams: ReturnType<typeof normalizeUrlParams>;
151+
try {
152+
urlParams = normalizeUrlParams(
153+
vtkURLExtract.extractURLParameters() as UrlParams
154+
);
155+
} catch (error) {
156+
console.error('Failed to parse URL parameters:', error);
157+
urlParams = {};
158+
}
153159
154160
onMounted(() => {
155161
loadUrls(urlParams);

src/io/import/processors/openUriStream.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { getRequestPool } from '@/src/core/streaming/requestPool';
44
import { ImportHandler, asIntermediateResult } from '@/src/io/import/common';
55
import { canFetchUrl } from '@/src/utils/fetch';
66
import { extractFilenameFromContentDisposition } from '@/src/utils/parseContentDispositionHeader';
7+
import { basename } from '@/src/utils/path';
78

89
const openUriStream: ImportHandler = async (dataSource, context) => {
910
if (dataSource.type !== 'uri' || !canFetchUrl(dataSource.uri)) {
@@ -26,7 +27,7 @@ const openUriStream: ImportHandler = async (dataSource, context) => {
2627

2728
// Only use Content-Disposition if current name lacks an extension
2829
// (indicating it's likely auto-derived from URL like "download" or "getImage")
29-
const hasExtension = dataSource.name.includes('.');
30+
const hasExtension = basename(dataSource.name).lastIndexOf('.') > 0;
3031
const finalName =
3132
!hasExtension && filenameFromHeader ? filenameFromHeader : dataSource.name;
3233

src/utils/parseContentDispositionHeader.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
const CONTENT_DISPOSITION_FILENAME_REGEXP =
22
/filename\s*=\s*(?:"([^"]*)"|([^;\s]*))/i;
33

4-
export type ContentDisposition =
5-
| { type: 'invalid'; filename: null }
6-
| { type: 'inline'; filename: string | null }
7-
| { type: 'attachment'; filename: string | null };
4+
export type ContentDisposition = {
5+
type: 'inline' | 'attachment' | 'invalid';
6+
filename: string | null;
7+
};
88

99
export function parseContentDispositionHeader(
1010
headerValue: string | null

src/utils/urlParams.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ const isValidUrl = (str: string) => {
1818
}
1919
};
2020

21+
const splitAndClean = (str: string) =>
22+
str
23+
.split(',')
24+
.map((url) => url.trim())
25+
.filter(Boolean);
26+
2127
const parseUrlArray = (value: string | string[]): string[] => {
2228
if (Array.isArray(value)) {
2329
return value.flatMap((v) => parseUrlArray(v));
@@ -28,18 +34,11 @@ const parseUrlArray = (value: string | string[]): string[] => {
2834
if (!trimmed) return [];
2935

3036
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
31-
const inner = trimmed.slice(1, -1);
32-
return inner
33-
.split(',')
34-
.map((url) => url.trim())
35-
.filter(Boolean);
37+
return splitAndClean(trimmed.slice(1, -1));
3638
}
3739

3840
if (trimmed.includes(',')) {
39-
return trimmed
40-
.split(',')
41-
.map((url) => url.trim())
42-
.filter(Boolean);
41+
return splitAndClean(trimmed);
4342
}
4443

4544
return [trimmed];

0 commit comments

Comments
 (0)