birdofpreyru / react-native-static-server

Embedded HTTP server for React Native
https://dr.pogodin.studio/docs/react-native-static-server
Other
154 stars 22 forks source link

Warning when opening a URL #63

Closed qwertynik closed 1 year ago

qwertynik commented 1 year ago

When opening a URL of a HTML file stored on the device, a warning is printed

 WARN  Error opening URL:  [Error: Unable to open URL: file:///Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Bundle/Application/A44D9AFF-AFC6-4925-8859-199116E60074/LocalRender.app/null/local.html]

This is coming from WebViewShared.js:42. Did not find a JS variant in the repo. Looks like this is a compile time file. Warning image:

Screenshot 2023-08-09 at 6 02 27 PM

Although the HTML on device loads, and the warning does not break any feature, wanted to know how this warning can be eliminated. The message points to a linking problem, however, since the suggested steps in the README were taken, not sure where the error is coming from.

Local setup info: Device: Mac M1 Node package.json:

  "dependencies": {
    "@dr.pogodin/react-native-static-server": "^0.7.13",
    "@react-native-community/cli-doctor": "^11.3.5",
    "react": "18.2.0",
    "react-native": "0.72.1",
    "react-native-fs": "^2.20.0",
    "react-native-webview": "^13.2.2"
  }
birdofpreyru commented 1 year ago

In the warning message you have null as one part of the path. I guess, you did some mistake, and trying to load the page before the server / path are ready?

qwertynik commented 1 year ago

That's right. Had noticed the null in the path myself, however, for other cases as well had noticed this warning. Is there anything to check to see if the server is ready other than waiting for .start() function call?

Can you elaborate on what is meant by path being ready?

birdofpreyru commented 1 year ago

Had noticed the null in the path myself, however, for other cases as well had noticed this warning.

There is no similar warning in the Example app included into this repo, thus it is some mistake in your code.

Is there anything to check to see if the server is ready other than waiting for .start() function call?

Yes, you can connect event listeners to a server instance, to get notified about its state changes — see .addStateListener() method.

Can you elaborate on what is meant by path being ready?

I just meant, your inserted into the path some variable (server origin?) which was still null at that moment.

qwertynik commented 1 year ago

Had gone through the example app and similar pattern has been used to build the interaction between the static-server app. Not quite certain on how the server is being used incorrectly:

import { useRef, useState, useEffect } from "react";
import { Alert, Button, View } from 'react-native';
import { WebView } from 'react-native-webview';
import Server, { getActiveServer, STATES } from '@dr.pogodin/react-native-static-server';
import RNFS from "react-native-fs";

function ViewDeviceHtml() {
    const serverRef = useRef(null);
    const [origin, setOrigin] = useState(null);
    const edetailWebView = useRef(null);

    useEffect(() => {
        let fileDir = getLocalHtmlDir();
        let activeServer = getActiveServer();

        console.log(`Within ViewDeviceHtml. fileDir: ${fileDir}, activeServer: ${activeServer?._id}`);

        if (activeServer) {
            activeServer.stop();
        }

        // Init the server
        if (!serverRef.current) {
            serverRef.current = new Server({ fileDir });
        }

        let server = serverRef.current;
        let serverId = server.id;

        (async () => {
            server?.addStateListener((newState, details, error) => {
                const state = STATES[newState];

                //If the server state is CRASHED, print the active server info to console.
                if (state === 'CRASHED') {
                    console.log('Active server:', getActiveServer());
                }

                console.log(
                    `Server #${serverId}.\n`,
                    `Origin: ${server?.origin} \n`,
                    `New state: "${state}".\n`,
                    `File dir: "${server?.fileDir}".\n`,
                    `Details: "${details}".\n`,
                );

                if (error) console.error(error);
            });

            if (server) {
                setOrigin(await server.start());
            }
        })();

        return () => {
            // No harm to trigger .stop() even if server has not been launched yet.
            (async () => {
                await server.stop();

                server = undefined;
            })();
        }
    }, []);

    return (
        <View style={{ flex: 1 }}>
            <View style={{ flex: 1 }}>
                {origin !== ''
                    &&
                    <WebView ref={edetailWebView} source={{ uri: `${origin}/local.html` }}
                        onError={(syntheticEvent) => {
                            const { nativeEvent } = syntheticEvent;
                            console.warn('WebView error: ', nativeEvent);
                        }}
                        onHttpError={(syntheticEvent) => {
                            const { nativeEvent } = syntheticEvent;
                            console.warn('WebView http error: ', nativeEvent);
                        }}
                        onLoadEnd={(syntheticEvent) => {
                            const { nativeEvent } = syntheticEvent;
                            console.log('WebView load end: ', nativeEvent);
                        }}
                    />
                }
                {
                    origin === '' && <View><Button title={"Loading..."} /></View>
                }

            </View>
        </View>
    );

    function getLocalHtmlDir() {
        const documentDir = RNFS.DocumentDirectoryPath;
        console.log(`document: ${documentDir}`);

        const htmlDir = `${documentDir}/localTest`;

        return htmlDir;
    }
}

export default ViewDeviceHtml;

I just meant, your inserted into the path some variable (server origin?) which was still null at that moment.

The path for the fileDir is set in useEffect(). And it takes the path from RNFS constant and appends the directory where the HTML is stored. So, there's no null there.

Logs printed:

 LOG  Within ViewDeviceHtml. fileDir: /Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Data/Application/91D63B5C-87C1-4217-A7D1-0172C5A1CD79/Documents/localTest, activeServer: undefined
 LOG  Server #49919.
 Origin:
 New state: "STARTING".
 File dir: "/Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Data/Application/91D63B5C-87C1-4217-A7D1-0172C5A1CD79/Documents/localTest".
 Details: "".
 LOG  Server #49919.
 Origin: http://127.0.0.1:56408
 New state: "ACTIVE".
 File dir: "/Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Data/Application/91D63B5C-87C1-4217-A7D1-0172C5A1CD79/Documents/localTest".
 Details: "".
 WARN  Error opening URL:  [Error: Unable to open URL: file:///Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Bundle/Application/C59E0A2F-142F-488E-A99F-8E9730956DED/LocalRender.app/null/local.html]
 LOG  WebView load end:  {"canGoBack": false, "canGoForward": false, "loading": false, "target": 205, "title": "", "url": "http://127.0.0.1:56408/local.html"}

From the logs, it can be seen that the fileDir is set as "/Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Data/Application/91D63B5C-87C1-4217-A7D1-0172C5A1CD79/Documents/localTest" but the path in the warning is this: file:///Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Bundle/Application/C59E0A2F-142F-488E-A99F-8E9730956DED/LocalRender.app/null/local.html

The initial portion of the path is same file:///Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/. However, after this, the path shown in the warning is Bundle/Application/C59E0A2F-142F-488E-A99F-8E9730956DED/LocalRender.app/null/local.html whereas the path in the fileDir variable (set when instantiating the server) is Data/Application/91D63B5C-87C1-4217-A7D1-0172C5A1CD79/Documents/localTest. So, there is a change/translation happening. Most likely the bug is here. Wondering if there is an issue in the app build/compilation phase.

qwertynik commented 1 year ago

@birdofpreyru Found the source of the problem. The issue is with whitelisting. Is there a section in README.md listing common errors? Will create a PR for the same.

qwertynik commented 1 year ago

Of course, in case you managed to solve the problem differently, can you share the steps?

birdofpreyru commented 1 year ago

I'll repeat — I don't see any problem with the library here; I only see you are trying to engage me into a free work on your project.

qwertynik commented 1 year ago

I'll repeat — I don't see any problem with the library here;

I had not concluded that the library had an issue. On encountering the issue, reported it to find ways to resolve it. This could have either led to finding an issue in the library, or, the code. On further debugging realized that the warning can be resolved by using whitelisting - which might be a hack, but sufficient for now. However, still uncertain about the source of the warning. In this case, an HTML is downloaded and rendered from the storage, a use-case different from what's present in the Example app, so looking into this issue might lead to finding problems.

I only see you are trying to engage me into a free work on your project.

Not certain why you felt this way. However, your responses earlier on other issues and the library itself has certainly been useful.

qwertynik commented 1 year ago

In case attaching the code made you feel as if free dev service for the project is being sought, it can be ignored. It was attached to make understanding logs simpler - had thought about removing the code after attaching it first, but let it remain for clarity. Looking at the logs alone might point to issues, if any.

Reattaching here: From the logs, it can be seen that the fileDir is set as "/Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Data/Application/91D63B5C-87C1-4217-A7D1-0172C5A1CD79/Documents/localTest" but the path in the warning is this: file:///Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/Bundle/Application/C59E0A2F-142F-488E-A99F-8E9730956DED/LocalRender.app/null/local.html

The initial portion of the path is same file:///Users/inqutec/Library/Developer/CoreSimulator/Devices/FCF07C4B-7AAA-48B2-9A39-6C4ADA268813/data/Containers/. However, after this, the path shown in the warning is Bundle/Application/C59E0A2F-142F-488E-A99F-8E9730956DED/LocalRender.app/null/local.html whereas the path in the fileDir variable (set when instantiating the server) is Data/Application/91D63B5C-87C1-4217-A7D1-0172C5A1CD79/Documents/localTest.

This change of path is mostly happening in an interaction between the WebView and the static-server.