Skip to content

Commit ae0647e

Browse files
AbhiPrasadwmak
authored andcommitted
feat(loader): Add endpoint for dynamic SDK loader (#44346)
In this PR we add a new `JavaScriptSdkDynamicLoader` view that will render the new dynamic js sdk loader as a template. This view does nothing atm, but adding functionality will be the next step. Currently this is not gated by the feature flag introduced with #44228, but will be as soon as it has complicated logic. As a next step, we need to introduce a `JS_SDK_DYNAMIC_LOADER_SDK_VERSION` config value, and then move to adding project dsn settings for the dynamic loader.
1 parent a377704 commit ae0647e

File tree

7 files changed

+72
-1
lines changed

7 files changed

+72
-1
lines changed

src/sentry/api/endpoints/project_docs_platform.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ def replace_keys(html, project_key):
2424
"___RELAY_CDN_URL___",
2525
absolute_uri(reverse("sentry-js-sdk-loader", args=[project_key.public_key])),
2626
)
27+
html = html.replace(
28+
"___RELAY_DYNAMIC_CDN_URL___",
29+
absolute_uri(reverse("sentry-js-sdk-dynamic-loader", args=[project_key.public_key])),
30+
)
2731

2832
# If we actually render this in the main UI we can also provide
2933
# extra information about the project (org slug and project slug)

src/sentry/api/serializers/models/project_key.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def serialize(self, obj, attrs, user):
3030
"minidump": obj.minidump_endpoint,
3131
"unreal": obj.unreal_endpoint,
3232
"cdn": obj.js_sdk_loader_cdn_url,
33+
"dynamicCdn": obj.js_sdk_dynamic_loader_cdn_url,
3334
},
3435
"browserSdkVersion": get_selected_browser_sdk_version(obj),
3536
"browserSdk": {"choices": get_browser_sdk_version_choices()},

src/sentry/models/projectkey.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def unreal_endpoint(self):
227227
return f"{self.get_endpoint()}/api/{self.project_id}/unreal/{self.public_key}/"
228228

229229
@property
230-
def js_sdk_loader_cdn_url(self):
230+
def js_sdk_loader_cdn_url(self) -> str:
231231
if settings.JS_SDK_LOADER_CDN_URL:
232232
return f"{settings.JS_SDK_LOADER_CDN_URL}{self.public_key}.min.js"
233233
else:
@@ -237,6 +237,17 @@ def js_sdk_loader_cdn_url(self):
237237
reverse("sentry-js-sdk-loader", args=[self.public_key, ".min"]),
238238
)
239239

240+
@property
241+
def js_sdk_dynamic_loader_cdn_url(self) -> str:
242+
if settings.JS_SDK_LOADER_CDN_URL:
243+
return f"{settings.JS_SDK_LOADER_CDN_URL}dynamic/{self.public_key}.min.js"
244+
else:
245+
endpoint = self.get_endpoint()
246+
return "{}{}".format(
247+
endpoint,
248+
reverse("sentry-js-sdk-dynamic-loader", args=[self.public_key, ".min"]),
249+
)
250+
240251
def get_endpoint(self, public=True):
241252
if public:
242253
endpoint = settings.SENTRY_PUBLIC_ENDPOINT or settings.SENTRY_ENDPOINT
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from rest_framework.request import Request
2+
from rest_framework.response import Response
3+
4+
from sentry.web.frontend.base import BaseView
5+
6+
7+
class JavaScriptSdkDynamicLoader(BaseView):
8+
auth_required = False
9+
10+
# Do not let an organization load trigger session, breaking Vary header.
11+
# TODO: This view should probably not be a subclass of BaseView if it doesn't actually use the
12+
# large amount of organization related support utilities, but that ends up being a large refactor.
13+
def determine_active_organization(self, request: Request, organization_slug=None) -> None:
14+
pass
15+
16+
def get(self, request: Request, public_key: str, minified: str) -> Response:
17+
"""Returns a JS file that dynamically loads the SDK based on project settings"""
18+
return super().get(request)

src/sentry/web/urls.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from sentry.web.frontend.group_tag_export import GroupTagExportView
2424
from sentry.web.frontend.home import HomeView
2525
from sentry.web.frontend.idp_email_verification import AccountConfirmationView
26+
from sentry.web.frontend.js_sdk_dynamic_loader import JavaScriptSdkDynamicLoader
2627
from sentry.web.frontend.js_sdk_loader import JavaScriptSdkLoader
2728
from sentry.web.frontend.mailgun_inbound_webhook import MailgunInboundWebhookView
2829
from sentry.web.frontend.newest_performance_issue import NewestPerformanceIssueView
@@ -116,6 +117,12 @@
116117
JavaScriptSdkLoader.as_view(),
117118
name="sentry-js-sdk-loader",
118119
),
120+
# JavaScript SDK Dynamic Loader
121+
url(
122+
r"^js-sdk-loader/dynamic/(?P<public_key>[^/\.]+)(?:(?P<minified>\.min))?\.js$",
123+
JavaScriptSdkDynamicLoader.as_view(),
124+
name="sentry-js-sdk-dynamic-loader",
125+
),
119126
# Versioned API
120127
url(r"^api/0/", include("sentry.api.urls")),
121128
# Legacy unversioned endpoints

tests/sentry/models/test_projectkey.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ def test_get_dsn(self):
7575
assert key.csp_endpoint == "http://testserver/api/1/csp-report/?sentry_key=abc"
7676
assert key.minidump_endpoint == "http://testserver/api/1/minidump/?sentry_key=abc"
7777
assert key.unreal_endpoint == "http://testserver/api/1/unreal/abc/"
78+
assert key.js_sdk_loader_cdn_url == "http://testserver/js-sdk-loader/abc.min.js"
79+
assert (
80+
key.js_sdk_dynamic_loader_cdn_url
81+
== "http://testserver/js-sdk-loader/dynamic/abc.min.js"
82+
)
83+
84+
def test_get_js_sdk_dynamic_loader_cdn_url_from_settings(self):
85+
key = self.model(project_id=1, public_key="abc", secret_key="xyz")
86+
87+
with self.settings(JS_SDK_LOADER_CDN_URL="https://sentry-best-cdn.com/"):
88+
assert (
89+
key.js_sdk_dynamic_loader_cdn_url
90+
== "https://sentry-best-cdn.com/dynamic/abc.min.js"
91+
)
7892

7993
def test_get_dsn_org_subdomain(self):
8094
with self.feature("organizations:org-subdomains"):
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from django.conf import settings
2+
from django.urls import reverse
3+
4+
from sentry.testutils import TestCase
5+
6+
7+
class JavaScriptSdkLoaderTest(TestCase):
8+
def test_absolute_url(self):
9+
assert (
10+
reverse("sentry-js-sdk-dynamic-loader", args=[self.projectkey.public_key, ".min"])
11+
in self.projectkey.js_sdk_dynamic_loader_cdn_url
12+
)
13+
settings.JS_SDK_LOADER_CDN_URL = "https://js.sentry-cdn.com/"
14+
assert (
15+
"https://js.sentry-cdn.com/dynamic/%s.min.js" % self.projectkey.public_key
16+
) == self.projectkey.js_sdk_dynamic_loader_cdn_url

0 commit comments

Comments
 (0)