4444from .config import PrivacyConfig
4545from .parser import FragmentParser
4646
47+ DEFAULT_TIMEOUT_IN_SECS = 5
48+
4749# -----------------------------------------------------------------------------
4850# Classes
4951# -----------------------------------------------------------------------------
@@ -310,21 +312,24 @@ def replace(match: Match):
310312 # Replace external favicon, preload hint or style sheet
311313 if rel in ("icon" , "preload" , "stylesheet" ):
312314 file = self ._queue (url , config )
313- el .set ("href" , resolve (file ))
315+ if file :
316+ el .set ("href" , resolve (file ))
314317
315318 # Handle external script or image
316319 if el .tag == "script" or el .tag == "img" :
317320 url = urlparse (el .get ("src" ))
318321 if not self ._is_excluded (url , initiator ):
319322 file = self ._queue (url , config )
320- el .set ("src" , resolve (file ))
323+ if file :
324+ el .set ("src" , resolve (file ))
321325
322326 # Handle external image in SVG
323327 if el .tag == "image" :
324328 url = urlparse (el .get ("href" ))
325329 if not self ._is_excluded (url , initiator ):
326330 file = self ._queue (url , config )
327- el .set ("href" , resolve (file ))
331+ if file :
332+ el .set ("href" , resolve (file ))
328333
329334 # Return element as string
330335 return self ._print (el )
@@ -380,7 +385,8 @@ def _queue(self, url: URL, config: MkDocsConfig, concurrent = False):
380385 # Fetch external asset synchronously, as it either has no extension
381386 # or is fetched from a context in which replacements are done
382387 else :
383- self ._fetch (file , config )
388+ if not self ._fetch (file , config ):
389+ return None
384390
385391 # Register external asset as file - it might have already been
386392 # registered, and since MkDocs 1.6, trigger a deprecation warning
@@ -404,18 +410,28 @@ def _fetch(self, file: File, config: MkDocsConfig):
404410
405411 # Download external asset
406412 log .info (f"Downloading external file: { file .url } " )
407- res = requests .get (file .url , headers = {
408-
409- # Set user agent explicitly, so Google Fonts gives us *.woff2
410- # files, which according to caniuse.com is the only format we
411- # need to download as it covers the entire range of browsers
412- # we're officially supporting.
413- "User-Agent" : " " .join ([
414- "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" ,
415- "AppleWebKit/537.36 (KHTML, like Gecko)" ,
416- "Chrome/98.0.4758.102 Safari/537.36"
417- ])
418- })
413+ try :
414+ res = requests .get (
415+ file .url ,
416+ headers = {
417+ # Set user agent explicitly, so Google Fonts gives us *.woff2
418+ # files, which according to caniuse.com is the only format we
419+ # need to download as it covers the entire range of browsers
420+ # we're officially supporting.
421+ "User-Agent" : " " .join (
422+ [
423+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" ,
424+ "AppleWebKit/537.36 (KHTML, like Gecko)" ,
425+ "Chrome/98.0.4758.102 Safari/537.36" ,
426+ ]
427+ )
428+ },
429+ timeout = DEFAULT_TIMEOUT_IN_SECS ,
430+ )
431+ res .raise_for_status ()
432+ except Exception as error : # this could be a ConnectionError or an HTTPError
433+ log .warning (f"Could not retrieve { file .url } : { error } " )
434+ return False
419435
420436 # Compute expected file extension and append if missing
421437 mime = res .headers ["content-type" ].split (";" )[0 ]
0 commit comments