Open manganapathy opened 3 months ago
Hi @manganapathy- these issues can be a little tricky for us to troubleshoot since we can't replicate your network environment. Being able to connect a computer to a device over the network is a pretty critical workflow for mobile development, so you may want to engage your network security team to come up with a better solution than blocking everything. For instance, could they assign static IP's to the mobile devices and then allowlist those IP's?
I was wondering if you could clarify how resolving to localhost
would cover this. As I understand, this would work for iOS simulators, but it wouldn't work for Android emulators (which use 10.10.2.2 I believe as a proxy for localhost) or devices, since localhost relative to your device would be itself, and not the dev server.
Speaking of your current workaround, I was wondering if REACT_NATIVE_PACKAGER_HOSTNAME
environment variable might work for you. That should output a different URL on the command line and isn't deprecated.
Thanks @keith-kurak. I have initiated conversation with my network security team.
Regarding workaround, would be happy to try using REACT_NATIVE_PACKAGER_HOSTNAME. But again double checking with you on this line 148 on UrlCreator.ts that has TODO comment to drop this env variable too. Hope I can ignore it for now.
My intention for filing this issue is to have expo run:ios resolve to Host Machine IP only if all below conditions are true .i.e user is running on a device instead of simulator. iOS simulators with Debug mostly points to localhost
React Native already does this in Xcode build script(packages/react-native/scripts/react-native-xcode.sh) but I guess it's overwritten inside expo cli in UrlCreator.ts There could be a valid use case but curious to know about it
Running expo run:ios with REACT_NATIVE_PACKAGER_HOSTNAME fixes the issue with localhost + simulator issue. But I still have issue with device flow + Tunnel + opening Chrome Dev Tools https://github.com/expo/expo/issues/31287
I got similar problem after recent OS/Xcode updates:
"
There was a problem loading the requested app.
The network connection was lost. It looks like you may be using a LAN URL. Make sure your device is on the same network as the server, and that you have granted Expo Go the Local Network permission in the Settings app, or try using the tunnel connection type.
"
If you use simulator from Xcode to debug, then disabling the connection on Mac solves the issue.
However the same network setup and connected Mac works in a tunnel mode with no issues. (expo@51.0.36)
Summary
Issue: Expo App with expo-dev-client resulting in error "There was a problem loading the project"[Firewall Related]
Repro Steps: Note: This issue happens only in machines which has firewall rules blocking incoming requests from unknown host[NetworkAdapter/Router assigned IP to Macbook) [Certain enterprises have this rule as part of security policy]
Expected: App should build and run fine with dev-client
Actual: App throws "There was a problem loading the project. Network connection was lost"
Managed or bare workflow?
managed
What platform(s) does this occur on?
iOS
Package versions
"expo": "~51.0.24", "expo-dev-client": "~4.0.21", "expo-constants": "~16.0.2", "expo-font": "~12.0.9", "expo-linking": "~6.3.1", "expo-router": "~3.5.20", "expo-splash-screen": "~0.27.5", "expo-status-bar": "~1.12.1", "expo-system-ui": "~3.0.7"
Environment
System: OS: macOS 14.5 Shell: 5.9 - /bin/zsh Binaries: Node: 20.15.0 - ~/.nvm/versions/node/v20.15.0/bin/node Yarn: 1.22.22 - /opt/homebrew/bin/yarn npm: 10.7.0 - ~/.nvm/versions/node/v20.15.0/bin/npm Watchman: 2024.07.15.00 - /opt/homebrew/bin/watchman Managers: CocoaPods: 1.15.2 - ~/.rvm/gems/ruby-3.1.4/bin/pod SDKs: iOS SDK: Platforms: DriverKit 23.2, iOS 17.2, macOS 14.2, tvOS 17.2, visionOS 1.0, watchOS 10.2 IDEs: Android Studio: 2024.1 AI-241.15989.150.2411.11948838 Xcode: 15.2/15C500b - /usr/bin/xcodebuild Expo Workflow: managed
Reproducible demo
Well, It's tough to produce a reproducible demo for this issue because this issue happens only in Macbooks with Firewall rules enabled to block unknown IPs. I am not able to use Tunnel because ngrok is also not allowed per corporate policies.
Though it's hard to repro this issue with firewall, I have analyzed the expo run:ios command flow and found out why cli is failing with firewall enabled where it could actually work smooth like other scenarios(expo --start)
Root Cause: npx expo run:ios command after pre-building and installing native dependencies, start the metro server Issue is while starting from run command, it passes only the "scheme" property in options object to create URL in below line startBundler.ts
Whereas two functions in 'start' command from file UrlCreator.tsdepends on either 'hostname' or 'hostType' to determine the hostname of dev server URL.
getUrlComponents(options: CreateURLOptions) getDefaultHostname(options: Pick<CreateURLOptions, 'hostname'>)
Unfortunately, since 'hostname' & 'hostType' is not passed in expo run:ios command and also only scheme is passed into start flow, expo cli always resolves to IP Address as 'hostname' & 'hostType' is undefined. This results in expo cli always resolving to exp+xxxxxxxxxx://expo-development-client/?url=http%3A%2F%2FXX.XX.X.XXX%3A8081 instead of localhost. As it's resolving to host machine IP, it's get blocked by Firewall.
Possible solutions: Solution 1 Well, Tunneling could solve this problem by exposing this IP public and access it. But as I mentioned earlier, if Tunneling is not allowed as per above reasons, I am proposing below solution.
Provide --host as a optional flag to expo run command like expo run:ios --host localhost
Proposed solution is similar to what expo --start -m, --host already has which makes it explicit to select the host for running the app.
This solution can help use cases where expo run:ios is blocked with firewall issues and avoid using 2 commands start with tunnel and again run to start the app.
Solution 2 Downside of above solution is that it deviates away from react-native-cli run-ios command which doesn't have --host option.To mitigate that we can opt for Solution2
In getDefaultHostname(options: Pick<CreateURLOptions, 'hostname'>) before we fallback to assign IP Address of the current device, we can choose to do one more additional check of is localhost currently running in the current machine(Which will be likely true if running from computer) and if the device is simulator. This also safe because even if developer want to choose a different host, it can be still done from dev-client launcher screen.
This similar to what react-native-community-cli already has https://github.com/react-native-community/cli/blob/6a61d5dcc99c6430b74c1095e05ffb315909b078/packages/cli-tools/src/isPackagerRunning.ts#L18
Solution 3(Recommended) EXDevLauncherErrorViewController currently displays full screen error message in case of any error with loading app with given URL.
I suggest we can change the full screen error to a snack bar message and displays it in dev-launcher home screen because it already has lot of fallback options
It is safe to fallback to snack bar instead of full screen so that users can choose from the given options to connect to desired host
Current Workaround: There is another workaround I found to be working is setting EXPO_PACKAGER_PROXY_URL. But I saw a comment that is deprecated and I am little skeptical to use.
Stacktrace (if a crash is involved)
No response