jekyll/jekyll

[Bug]: LiveReload websocket crashes over HTTPS/WSS

robmiller opened this issue · 1 comments

Operating System

MacOS

Ruby Version

ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22]

Jekyll Version

jekyll 4.3.2

GitHub Pages Version

Latest

Expected Behavior

I have several Jekyll sites, some of which I develop locally at the same time. Having to remember ports bugs me, so I use Caddy to reverse proxy to them so I can just type foo.localhost, bar.localhost, etc. into my browser, rather than localhost:4000, localhost:4321, etc.

I do this by running jekyll serve --livereload and specifying both the port and LiveReload ports, so that LiveReload can be running on separate sites at separate times.

I then use Caddy to reverse proxy the *.localhost URLs to the appropriate ports on localhost.

This has always worked fine.

Current Behavior

I recently upgraded from Jekyll 4.2.2 to 4.3.2, in order to get some new Sass features that I wanted, at which point it broke. Every time I load the page, the Jekyll serve process crashes with the following error:

LiveReload experienced an error. Run with --trace for more information.
LiveReload experienced an error. Run with --trace for more information.
#<Thread:0x000000010905e178 /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/jekyll-4.3.2/lib/jekyll/commands/serve/live_reload_reactor.rb:39 run> terminated with exception (report_on_exception is true):
/Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/jekyll-4.3.2/lib/jekyll/commands/serve/websockets.rb:46:in `<<': Could not parse data entirely (0 != 169) (HTTP::Parser::Error)
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/jekyll-4.3.2/lib/jekyll/commands/serve/websockets.rb:46:in `dispatch'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/em-websocket-0.5.3/lib/em-websocket/connection.rb:79:in `receive_data'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run_machine'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/jekyll-4.3.2/lib/jekyll/commands/serve/live_reload_reactor.rb:42:in `block in start'
/Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/jekyll-4.3.2/lib/jekyll/commands/serve/websockets.rb:46:in `<<': Could not parse data entirely (0 != 169) (HTTP::Parser::Error)
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/jekyll-4.3.2/lib/jekyll/commands/serve/websockets.rb:46:in `dispatch'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/em-websocket-0.5.3/lib/em-websocket/connection.rb:79:in `receive_data'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run_machine'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/eventmachine-1.2.7/lib/eventmachine.rb:195:in `run'
	from /Users/rob/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/jekyll-4.3.2/lib/jekyll/commands/serve/live_reload_reactor.rb:42:in `block in start'

I can seemingly trace the problem to the change introduced in #8718, although websockets aren't my forté so I'm not sure if I'm barking up the wrong tree. But that isolated it enough for me to reproduce the crash:

  1. If I start the jekyll serve process and don't request anything in my browser, it remains running indefinitely
  2. If I then request LiveReload over ws://, i.e. non-encrypted, everything works as expected (the command I use for this is websocat -v ws://localhost:8696/livereload
  3. But if I request LiveReload over ws://, i.e. encrypted, it crashes (the command I use for this is websocat -v wss://localhost:8696/livereload)

My assumption is:

  1. LiveReload.js is requesting wss://, because the page is served via https and therefore LiveReload is being requested via https too (after the change in #8718)
  2. The Jekyll LiveReload barfs when it receives the encrypted data, because it can't parse it.

This might be something I need to fix myself at the level of my reverse proxy, although I've tried lots of things and can't seem to make it work, but it seems strange that everything was working okay until the change in #8718.

Hope that's enough information to figure things out – let me know if there are any other logs I can provide.

(Also, I think running jekyll serve behind a reverse proxy is a supported use-case, but let me know if it isn't.)

Relevant log output

No response

Code Sample

No response

I realise that I didn't do the obvious thing to check whether this problem was introduced in #8718, which was to manually revert the change made in that commit in my local version.

I can confirm that doing that fixes this issue; LiveReload works as expected even over reverse-proxied HTTPS URLs.