Skip to content
This repository has been archived by the owner on Sep 2, 2021. It is now read-only.

[PROTOTYPE] Local HTTP-served static files, vs. file: protocol #475

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jasonsanjose
Copy link
Member

Proof of concept to serve brackets core www files over a static file HTTP node server.

After running into various issues with the security model (or lack of) in CEF combined with the issues when using the file: protocol, I thought it would be fun to see what it would take to serve Brackets over HTTP within brackets-shell using the built-in node server.

Overall, this is not required for any current/planned features. However, I think it would help Brackets get closer to moving into the browser if we could transition away from file: first within brackets-shell.

Changes:

  • appshell/node-core/Server.js
    • We already had an HTTP server in place for NodeConnection to read the /api JSON (i.e. http://localhost:[node_port]/api)
    • Changed the request handler to support static file serving from either the "hacked" location /dev/src or installed /www
  • appshell/node-core/thirdparty/conenct
    • Use static middleware to serve files
  • Force Brackets to load a page that redirects to the HTTP URL as soon as node setup is complete:
brackets.app.getNodeState(function (err, port) {
  if (err) {
    console.log("Failed to create local HTTP server");
  } else {
    window.location.href = "http://localhost:" + port + "/index.html";
  }
});

There's still more to do on the www side. We wouldn't need to shift to a node-based FS since we're in brackets-shell and can still access brackets.fs. However, a lot of www code (particularly extension loading) assumes a file: URL. Here's the console log on init:

Download the React DevTools for a better development experience: http://fb.me/react-devtools /thirdparty/react.js:4356
[Extension] Error -- could not read native directory: /extensions/default /utils/ExtensionLoader.js:331
[Extension] Error -- could not read native directory: /extensions/dev /utils/ExtensionLoader.js:331
[NodeDomain] Error loading domain "fileWatcher": Unable to load one of the modules: /./filesystem/impls/appshell/node/FileWatcherDomain, reason: Cannot find module '/./filesystem/impls/appshell/node/FileWatcherDomain' /utils/NodeDomain.js:146
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:51518/Users/jasonsj/Library/Application%20Support/Brackets/extensions/user/brackets-beautify/main.js
[Extension] failed to load /Users/jasonsj/Library/Application Support/Brackets/extensions/user/brackets-beautify Error: Script error for: main
http://requirejs.org/docs/errors.html#scripterror /utils/ExtensionLoader.js:214
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:51518/Users/jasonsj/Library/Application%20Support/Brackets/extensions/user/brackets-bower/main.js
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:51518/Users/jasonsj/Library/Application%20Support/Brackets/extensions/user/brackets-parfait-extension/main.js
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:51518/Users/jasonsj/Library/Application%20Support/Brackets/extensions/user/brackets-sass/main.js
[Extension] failed to load /Users/jasonsj/Library/Application Support/Brackets/extensions/user/brackets-bower Error: Script error for: main
http://requirejs.org/docs/errors.html#scripterror /utils/ExtensionLoader.js:214
[Extension] failed to load /Users/jasonsj/Library/Application Support/Brackets/extensions/user/brackets-parfait-extension Error: Script error for: main
http://requirejs.org/docs/errors.html#scripterror /utils/ExtensionLoader.js:214
[Extension] failed to load /Users/jasonsj/Library/Application Support/Brackets/extensions/user/brackets-sass Error: Script error for: main
http://requirejs.org/docs/errors.html#scripterror /utils/ExtensionLoader.js:214
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:51518/Users/jasonsj/Library/Application%20Support/Brackets/extensions/user/gruehle.markdown-preview/main.js
[Extension] failed to load /Users/jasonsj/Library/Application Support/Brackets/extensions/user/gruehle.markdown-preview Error: Script error for: main
http://requirejs.org/docs/errors.html#scripterror /utils/ExtensionLoader.js:214
Failed to watch root:  /Users/jasonsj/Github/brackets/ Unable to load one of the modules: /./filesystem/impls/appshell/node/FileWatcherDomain, reason: Cannot find module '/./filesystem/impls/appshell/node/FileWatcherDomain' /filesystem/FileSystem.js:869
Error watching project root:  /Users/jasonsj/Github/brackets/ Unable to load one of the modules: /./filesystem/impls/appshell/node/FileWatcherDomain, reason: Cannot find module '/./filesystem/impls/appshell/node/FileWatcherDomain' /project/ProjectManager.js:753
[Extensions] Failed to connect to node 
Arguments[1]

@jasonsanjose
Copy link
Member Author

A few notes on the security issues we ran into:

  • CEF won't set cookies on file: URLs (we have shims in place for libraries that require cookies)
  • More notes soon...

@peterflynn
Copy link
Member

Initial thoughts.... There's some risk in making Node a more critical part of Brackets, specifically:

  • Buggy extensions can much more easily bring down all of Brackets -- one solution would be to run extensions in a separate Node process
  • Aggressive firewalls that block Node's local sockets currently interfere with Live Preview, file watchers, and extension installation. But with this PR, they would brick Brackets entirely. Since the symptoms are much more subtle today, we don't really know yet what percentage of our users would be subject to that. The Brackets Health Report might help us learn more about that.
  • Do we know what the impact on loading time is? Experiments with Node-based file IO suggested it is measurably slower than doing IO directly through brackets-shell.

I wonder if there are other alternatives that might avoid some of those risks, e.g.:

  • Use the mini-HTTP server that is already built into brackets-shell (used to serve up the dev tools UI). Could be fairly easy to implement.
  • Use a fake http: URL, and have a shim layer in brackets-shell (via a CEF hook) detect URLs of this form and proxy over to the file: protocol handler so that the content is still loaded off disk directly, reusing the existing code that does that reliably today. May be trickier to implement.
    • Edit: Maybe not so tricky afterall. Looks like you could just hook ClientHandler::HandleBeforeResourceLoad() to return a LoadStream for a file on disk, which would veto CEF going out to the network to try to resolve the URL. CEF can even create the stream for you, using CefStreamReader::CreateForFile(). See this and this for some info.
    • We could also define a custom URL scheme, e.g. similar to this example/testcase.

@peterflynn
Copy link
Member

Added some more notes on alternatives to my list in the previous comment

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
2 participants