Description
The problem
For some people, our cheatsheet will open the raw HTML in an editor if they have that set as their default for HTML. The problem is that Python's webbrowser
module doesn't handle file://
urls well; it basically calls open
, which causes the OS to use the default app for opening HTML, rather than opening it in the user's default browser, as it does for http://
urls.
The solution
We need to roll our own default browser detector using 3 different routes, one for each of mac, linux and windows:
And then just fallback to using webbrowser.open
if the detection method fails.
We could think about upstreaming this solution to Python's webbrowser
module.
Alternative solution: local HTTP server
One possibility is to switch to using a local HTTP server.
The HTTP server code would look something like the following:
import http from "http";
const requestListener = function (req, res) {
fs.readFile("~/.cursorless/cheatsheet/index.html")
.then(contents => {
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end(contents);
})
};
const server = http.createServer(requestListener);
server.listen(0, "localhost");
We'd probably want to have a port file in ~/.cursorless/port
that indicates which port the cheatsheet is being served on.
Note that we'd want to make sure that the various VSCode windows coordinate with one another so that we don't have each one running an HTTP server. We could do so as follows, in response to the user requesting a cheatsheet. First update the index.html
. Then,
- If focused window has a server running, just do nothing
- Otherwise, check to see if there is already a port file
- If no port file, spawn a server at a new port and create a port file
- If there is a port file, make a HEAD request to the port, with a timeout. Note that we don't want to use the regular HTTP timeout, as that's just for connections; instead we should just use
setTimeout
and then cancel the request if it hasn't completed. Instead of a HEAD request, we could consider making a request for a particular path, and expect a specific response, just to make sure something else isn't running on that port- If request succeeds, update the
index.html
and continue - If it fails, spawn a server at a new port and update the port file
- If request succeeds, update the
I don't think a server this simple should present a security risk, but maybe there's issues with the whole port file thing / the fact that something else might be running at that port?
This approach would also address #911, if we added VSCode port forwarding (via asExternalUri
)
Some random links related to this approach, that may or may not be helpful 🤷:
- https://nodejs.dev/en/learn/making-http-requests-with-nodejs/
- https://stackoverflow.com/questions/24625620/how-should-http-server-respond-to-head-request-for-chunked-encoding
- https://nodejs.org/docs/latest/api/net.html#serverlisten
- https://gist.github.com/mikeal/1840641
- https://github.com/cloudhead/node-static
- https://www.digitalocean.com/community/tutorials/how-to-create-a-web-server-in-node-js-with-the-http-module