Просмотр исходного кода

feat: add support for url joining of unknown schemes (#15182)

Armin Ronacher 5 лет назад
Родитель
Сommit
84a7b5fda2

+ 5 - 4
src/sentry/lang/javascript/processor.py

@@ -12,7 +12,7 @@ import zlib
 from django.conf import settings
 from os.path import splitext
 from requests.utils import get_encoding_from_headers
-from six.moves.urllib.parse import urljoin, urlsplit
+from six.moves.urllib.parse import urlsplit
 from symbolic import SourceMapView
 
 # In case SSL is unavailable (light builds) we can't import this here.
@@ -33,6 +33,7 @@ from sentry.utils.hashlib import md5_text
 from sentry.utils.http import is_valid_origin
 from sentry.utils.safe import get_path
 from sentry.utils import metrics
+from sentry.utils.urls import non_standard_url_join
 from sentry.stacktraces.processing import StacktraceProcessor
 
 from .cache import SourceCache, SourceMapCache
@@ -195,7 +196,7 @@ def discover_sourcemap(result):
                 )
             sourcemap = sourcemap[:index]
         # fix url so its absolute
-        sourcemap = urljoin(result.url, sourcemap)
+        sourcemap = non_standard_url_join(result.url, sourcemap)
 
     return sourcemap
 
@@ -603,7 +604,7 @@ class JavaScriptStacktraceProcessor(StacktraceProcessor):
             sourcemap_applied = True
 
             if token is not None:
-                abs_path = urljoin(sourcemap_url, token.src)
+                abs_path = non_standard_url_join(sourcemap_url, token.src)
 
                 logger.debug(
                     "Mapping compressed source %r to mapping in %r", frame["abs_path"], abs_path
@@ -798,7 +799,7 @@ class JavaScriptStacktraceProcessor(StacktraceProcessor):
         for src_id, source_name in sourcemap_view.iter_sources():
             source_view = sourcemap_view.get_sourceview(src_id)
             if source_view is not None:
-                self.cache.add(urljoin(sourcemap_url, source_name), source_view)
+                self.cache.add(non_standard_url_join(sourcemap_url, source_name), source_view)
 
     def populate_source_cache(self, frames):
         """

+ 33 - 0
src/sentry/utils/urls.py

@@ -0,0 +1,33 @@
+from __future__ import absolute_import
+
+from six.moves.urllib.parse import urljoin
+import re
+
+
+_scheme_re = re.compile(r"^([a-zA-Z0-9-+]+://)(.*)$")
+
+
+def non_standard_url_join(base, to_join):
+    """A version of url join that can deal with unknown protocols."""
+    # joins to an absolute url are willing by default
+    if not to_join:
+        return base
+
+    match = _scheme_re.match(to_join)
+    if match is not None:
+        return to_join
+
+    match = _scheme_re.match(base)
+    if match is not None:
+        original_base_scheme, rest = match.groups()
+        base = "http://" + rest
+    else:
+        original_base_scheme = None
+
+    rv = urljoin(base, to_join)
+    if original_base_scheme is not None:
+        match = _scheme_re.match(rv)
+        if match is not None:
+            return original_base_scheme + match.group(2)
+
+    return rv

+ 1 - 0
tests/sentry/lang/javascript/test_plugin.py

@@ -170,6 +170,7 @@ class JavascriptIntegrationTest(TestCase, SnubaTestCase):
 
         mock_fetch_file.return_value.body = "\n".join("hello world")
         mock_fetch_file.return_value.encoding = None
+        mock_fetch_file.return_value.headers = {}
 
         resp = self._postWithHeader(data)
         assert resp.status_code, 200

+ 20 - 0
tests/sentry/utils/test_urls.py

@@ -0,0 +1,20 @@
+from __future__ import absolute_import
+
+import pytest
+
+from sentry.utils.urls import non_standard_url_join
+
+
+@pytest.mark.parametrize(
+    "base,to_join,expected",
+    [
+        ("http://example.com/foo", "bar", "http://example.com/bar"),
+        ("http://example.com/foo", "/bar", "http://example.com/bar"),
+        ("https://example.com/foo", "/bar", "https://example.com/bar"),
+        ("aps://example.com/foo", "/bar", "aps://example.com/bar"),
+        ("apsunknown://example.com/foo", "/bar", "apsunknown://example.com/bar"),
+        ("apsunknown://example.com/foo", "//aha/uhu", "apsunknown://aha/uhu"),
+    ],
+)
+def test_non_standard_url_join(base, to_join, expected):
+    assert non_standard_url_join(base, to_join) == expected