MCPcopy Create free account
hub / github.com/Dispatcharr/Dispatcharr / validate_stream_url

Function validate_stream_url

apps/proxy/live_proxy/url_utils.py:433–557  ·  view source on GitHub ↗

Validate if a stream URL is accessible without downloading the full content. Note: UDP/RTP/RTSP streams are automatically considered valid as they cannot be validated via HTTP methods. Args: url (str): The URL to validate user_agent (str): User agent to use for the

(url, user_agent=None, timeout=(5, 5))

Source from the content-addressed store, hash-verified

431 close_old_connections()
432
433def validate_stream_url(url, user_agent=None, timeout=(5, 5)):
434 """
435 Validate if a stream URL is accessible without downloading the full content.
436
437 Note: UDP/RTP/RTSP streams are automatically considered valid as they cannot
438 be validated via HTTP methods.
439
440 Args:
441 url (str): The URL to validate
442 user_agent (str): User agent to use for the request
443 timeout (tuple): Connection and read timeout in seconds
444
445 Returns:
446 tuple: (is_valid, final_url, status_code, message)
447 """
448 # Check if URL uses non-HTTP protocols (UDP/RTP/RTSP)
449 # These cannot be validated via HTTP methods, so we skip validation
450 if url.startswith(('udp://', 'rtp://', 'rtsp://')):
451 logger.info(f"Skipping HTTP validation for non-HTTP protocol: {url}")
452 return True, url, 200, "Non-HTTP protocol (UDP/RTP/RTSP) - validation skipped"
453
454 try:
455 # Create session with proper headers
456 session = requests.Session()
457 headers = {
458 'User-Agent': user_agent,
459 'Connection': 'close' # Don't keep connection alive
460 }
461 session.headers.update(headers)
462
463 # Make HEAD request first as it's faster and doesn't download content
464 head_request_success = True
465 try:
466 head_response = session.head(
467 url,
468 timeout=timeout,
469 allow_redirects=True
470 )
471 except requests.exceptions.RequestException as e:
472 head_request_success = False
473 logger.warning(f"Request error (HEAD), assuming HEAD not supported: {str(e)}")
474
475 # If HEAD not supported, server will return 405 or other error
476 if head_request_success and (200 <= head_response.status_code < 300):
477 # HEAD request successful
478 return True, url, head_response.status_code, "Valid (HEAD request)"
479
480 # Try a GET request with stream=True to avoid downloading all content
481 get_response = session.get(
482 url,
483 stream=True,
484 timeout=timeout,
485 allow_redirects=True
486 )
487
488 # IMPORTANT: Check status code first before checking content
489 if not (200 <= get_response.status_code < 300):
490 logger.warning(f"Stream validation failed with HTTP status {get_response.status_code}")

Callers 1

stream_tsFunction · 0.85

Calls 3

updateMethod · 0.45
getMethod · 0.45
closeMethod · 0.45

Tested by

no test coverage detected