diff --git a/mopidy/stream/actor.py b/mopidy/stream/actor.py index 4561bb63..b3bf0b30 100644 --- a/mopidy/stream/actor.py +++ b/mopidy/stream/actor.py @@ -97,9 +97,18 @@ def _unwrap_stream(uri, timeout, scanner, requests_session): """ original_uri = uri + seen_uris = set() deadline = time.time() + timeout while time.time() < deadline: + if uri in seen_uris: + logger.info( + 'Unwrapping stream from URI (%s) failed: ' + 'playlist referenced itself', uri) + return None + else: + seen_uris.add(uri) + logger.debug('Unwrapping stream from URI: %s', uri) try: @@ -107,8 +116,7 @@ def _unwrap_stream(uri, timeout, scanner, requests_session): if scan_timeout < 0: logger.info( 'Unwrapping stream from URI (%s) failed: ' - 'timed out in %sms', - uri, timeout) + 'timed out in %sms', uri, timeout) return None scan_result = scanner.scan(uri, timeout=scan_timeout) except exceptions.ScannerError as exc: diff --git a/tests/stream/test_playback.py b/tests/stream/test_playback.py index ba7c2c92..4c42b1cd 100644 --- a/tests/stream/test_playback.py +++ b/tests/stream/test_playback.py @@ -166,3 +166,22 @@ class TestTranslateURI(object): result = provider.translate_uri(PLAYLIST_URI) assert result is None + + @responses.activate + def test_playlist_references_itself(self, scanner, provider, caplog): + scanner.scan.return_value.mime = 'text/foo' + responses.add( + responses.GET, PLAYLIST_URI, + body=BODY.replace(STREAM_URI, PLAYLIST_URI), + content_type='audio/x-mpegurl') + + result = provider.translate_uri(PLAYLIST_URI) + + assert 'Unwrapping stream from URI: %s' % PLAYLIST_URI in caplog.text() + assert ( + 'Parsed playlist (%s) and found new URI: %s' + % (PLAYLIST_URI, PLAYLIST_URI)) in caplog.text() + assert ( + 'Unwrapping stream from URI (%s) failed: ' + 'playlist referenced itself' % PLAYLIST_URI) in caplog.text() + assert result is None