Skip to content

Commit c352eec

Browse files
committed
fix(missingModelDownload): validate mirror URL and localize setting name
- Validate mirror is an absolute http(s) URL; warn and skip otherwise.
1 parent cebead0 commit c352eec

3 files changed

Lines changed: 39 additions & 1 deletion

File tree

src/locales/en/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@
230230
"title": "title"
231231
}
232232
},
233+
"Comfy_ModelLibrary_HuggingFaceMirror": {
234+
"name": "HuggingFace mirror URL",
235+
"tooltip": "Optional mirror for Hugging Face model downloads. Leave empty to use the official huggingface.co (e.g. https://hf-mirror.com). Applies to the \"Download All missing models\" workflow button and the file-size probe shown in the UI."
236+
},
233237
"Comfy_Node_AllowImageSizeDraw": {
234238
"name": "Show width × height below the image preview"
235239
},

src/platform/missingModel/missingModelDownload.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,24 @@ describe('resolveHuggingFaceUrl', () => {
770770
).toBe('https://hf-mirror.com/org/model/resolve/main/x')
771771
})
772772

773+
it('ignores a mirror without a scheme', () => {
774+
mockHuggingFaceMirror.value = 'hf-mirror.com'
775+
const consoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {})
776+
expect(
777+
resolveHuggingFaceUrl('https://huggingface.co/org/model/resolve/main/x')
778+
).toBe('https://huggingface.co/org/model/resolve/main/x')
779+
expect(consoleWarn).toHaveBeenCalled()
780+
})
781+
782+
it('ignores a mirror with a non-http(s) scheme', () => {
783+
mockHuggingFaceMirror.value = 'javascript:alert(1)'
784+
const consoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {})
785+
expect(
786+
resolveHuggingFaceUrl('https://huggingface.co/org/model/resolve/main/x')
787+
).toBe('https://huggingface.co/org/model/resolve/main/x')
788+
expect(consoleWarn).toHaveBeenCalled()
789+
})
790+
773791
it('leaves non-HuggingFace URLs untouched', () => {
774792
mockHuggingFaceMirror.value = 'https://hf-mirror.com'
775793
expect(

src/platform/missingModel/missingModelDownload.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export const HUGGINGFACE_MIRROR_SETTING_ID =
4646
* users behind networks blocking `huggingface.co` can still use the
4747
* "Download All missing models" button. Empty/missing setting returns
4848
* the URL unchanged. Non-HuggingFace URLs are returned unchanged.
49+
* Mirrors that are not absolute http(s) URLs are ignored and warned
50+
* about, to avoid producing broken download URLs.
4951
*/
5052
export function resolveHuggingFaceUrl(url: string): string {
5153
const mirror = useSettingStore()
@@ -54,7 +56,21 @@ export function resolveHuggingFaceUrl(url: string): string {
5456
.replace(/\/+$/, '')
5557
if (!mirror) return url
5658
if (!hasHuggingFaceHost(url)) return url
57-
return url.replace('https://huggingface.co', mirror)
59+
try {
60+
const parsed = new URL(mirror)
61+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
62+
console.warn(
63+
`[missingModelDownload] Ignoring ${HUGGINGFACE_MIRROR_SETTING_ID}: mirror must use http or https, got ${parsed.protocol}`
64+
)
65+
return url
66+
}
67+
return url.replace('https://huggingface.co', mirror)
68+
} catch {
69+
console.warn(
70+
`[missingModelDownload] Ignoring ${HUGGINGFACE_MIRROR_SETTING_ID}: mirror is not a valid URL`
71+
)
72+
return url
73+
}
5874
}
5975

6076
export interface ModelWithUrl {

0 commit comments

Comments
 (0)