Skip to content

feat(playground): Open Sentry in desktop browser from Expo apps#5947

Merged
antonis merged 7 commits intomainfrom
feat/playground-open-url-expo
Apr 2, 2026
Merged

feat(playground): Open Sentry in desktop browser from Expo apps#5947
antonis merged 7 commits intomainfrom
feat/playground-open-url-expo

Conversation

@antonis
Copy link
Copy Markdown
Contributor

@antonis antonis commented Apr 1, 2026

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Previously, the "Open Sentry" button in the Sentry Playground was hidden for Expo-based apps because it relied on the React Native CLI's open-url endpoint, which is not available in Expo's Metro setup.

This PR adds a custom /__sentry/open-url endpoint to the Sentry Metro Middleware. The Playground now sends a POST request to this endpoint, and the middleware uses the open npm package (available transitively via @react-native-community/cli-server-api and @expo/cli) to open the URL in the desktop browser.

Changes

New files in packages/core/src/js/metro/:

  • constants.ts — shared path constants (__sentry/context, __sentry/open-url) extracted from metroMiddleware.ts
  • getRawBody.ts — request body reader extracted from metroMiddleware.ts
  • openUrlMiddleware.ts — new middleware handler for /__sentry/open-url
  • openUrlInBrowser.ts — client-side helper that sends the open-url request to the Metro dev server

Modified files:

  • metroMiddleware.ts — routes /__sentry/open-url to the new middleware, uses extracted constants and getRawBody
  • playground/modal.tsx — removes the isExpo() gate on the "Open Sentry" button, uses the new openUrlInBrowser helper instead of the inline function that hit the RN CLI endpoint

Security hardening

  • Only http:// and https:// URL schemes are allowed (rejects file://, ssh://, etc.)
  • Returns 405 for non-POST requests
  • Descriptive error messages when the open package is unavailable

💡 Motivation and Context

Continues the work from #4918 by @krystofwoldrich. The original commit is cherry-picked to preserve attribution.

The Sentry Playground's "Open Sentry" button is useful for verifying SDK setup, but it was only functional in bare React Native apps. Expo users — a large portion of the RN community — couldn't use this feature because Expo doesn't expose the RN CLI's open-url middleware.

💚 How did you test it?

  • Added unit tests for openURLMiddleware (7 tests covering all paths: 405, 400, scheme validation, success, failure)
  • Added routing test for /__sentry/open-url in createSentryMetroMiddleware
  • Existing snapshot tests for the Playground modal pass unchanged
  • All 22 middleware tests pass, full test suite and lint clean
  • Manually tested with the Expo sample app: started Metro, sent curl -X POST http://localhost:8081/__sentry/open-url -d '{"url":"https://sentry-sdks.sentry.io/issues/"}' — URL opened in desktop browser
Screen.Recording.2026-04-01.at.14.03.59.mov

📝 Checklist

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed. (look accurate)
  • I updated the wizard if needed.
  • All tests passing
  • No breaking changes

🔮 Next steps

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • feat(playground): Open Sentry in desktop browser from Expo apps by antonis in #5947
  • chore(core): Bump sample app to React Native 0.84.1 by antonis in #5941
  • Size analysis for React Native SDK by alwx in #5949
  • chore(deps): bump lodash from 4.17.23 to 4.18.1 by dependabot in #5953
  • chore(deps): bump yauzl to ^3.2.1 by antonis in #5950
  • chore(deps): bump brace-expansion to ^2.0.3 by antonis in #5951
  • chore(deps): bump @xmldom/xmldom to fix XML injection by antonis in #5952

🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 9063607

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@antonis antonis marked this pull request as ready for review April 1, 2026 12:31
@lucas-zimerman
Copy link
Copy Markdown
Collaborator

lucas-zimerman commented Apr 2, 2026

Thank you for the PR! and for the video reproduction!

I only have one concern in regard to the security of the feature.

return;
}

if (!url.startsWith('https://') && !url.startsWith('http://')) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd only allow requests that has the host sentry.io to avoid any malicious code invoking any kind of url with this method.
This impact self-hosted users, but it's worth the risk,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what's the best way to approach that. Technically we shouldn't exclude those using self-hosted Sentry.

Copy link
Copy Markdown
Contributor

@alwx alwx Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An idea: if the host is not sentry.io then instead of automatically opening the link gets printed to the console with the note that you should only open it if you trust the host (so we basically jump to what's on lines 58-61)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch @lucas-zimerman and thank you for the suggestion @alwx 🙇
Applied it with ec8663b

@antonis antonis requested a review from lucas-zimerman April 2, 2026 11:44
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

krystofwoldrich and others added 6 commits April 2, 2026 13:58
- Return 405 for non-POST requests instead of hanging
- Validate URL scheme (http/https only)
- Improve error messages when `open` package is unavailable
- Fix inconsistent oxlint disable comments
- Add tests for openURLMiddleware and open-url routing

Co-Authored-By: Krystof Woldrich <krystofwoldrich@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only the derived constants are used externally.
For non-sentry.io hosts, the URL is printed to the Metro console
instead of being opened automatically, so users can decide whether
to trust it. This prevents the middleware from being used to open
arbitrary URLs while still supporting all *.sentry.io subdomains.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Handle both CJS and ESM exports from the `open` package (v8+ is
  ESM-only and `require` returns `{ default: fn }` instead of `fn`)
- Sanitize URLs before logging to prevent terminal escape sequence
  injection via control characters

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@antonis antonis force-pushed the feat/playground-open-url-expo branch from 5e430de to c4514ee Compare April 2, 2026 12:00
Copy link
Copy Markdown
Contributor

@alwx alwx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@antonis antonis added the ready-to-merge Triggers the full CI test suite label Apr 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 409.86 ms 425.82 ms 15.96 ms
Size 43.75 MiB 48.08 MiB 4.33 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
4953e94+dirty 442.02 ms 456.52 ms 14.50 ms
df5d108+dirty 527.06 ms 603.58 ms 76.52 ms
a50b33d+dirty 500.81 ms 532.11 ms 31.30 ms

App size

Revision Plain With Sentry Diff
4953e94+dirty 43.75 MiB 48.08 MiB 4.33 MiB
df5d108+dirty 43.75 MiB 48.08 MiB 4.33 MiB
a50b33d+dirty 43.75 MiB 48.08 MiB 4.33 MiB

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1208.15 ms 1208.62 ms 0.47 ms
Size 3.38 MiB 4.73 MiB 1.35 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
df5d108+dirty 1225.90 ms 1220.14 ms -5.76 ms
4953e94+dirty 1212.06 ms 1214.83 ms 2.77 ms
a50b33d+dirty 1197.74 ms 1197.17 ms -0.57 ms

App size

Revision Plain With Sentry Diff
df5d108+dirty 3.38 MiB 4.73 MiB 1.35 MiB
4953e94+dirty 3.38 MiB 4.73 MiB 1.35 MiB
a50b33d+dirty 3.38 MiB 4.73 MiB 1.35 MiB

@antonis antonis merged commit 96c52f0 into main Apr 2, 2026
82 of 109 checks passed
@antonis antonis deleted the feat/playground-open-url-expo branch April 2, 2026 13:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants