This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "http/parser"
|
||||
|
||||
module Jekyll
|
||||
module Commands
|
||||
class Serve
|
||||
# The LiveReload protocol requires the server to serve livereload.js over HTTP
|
||||
# despite the fact that the protocol itself uses WebSockets. This custom connection
|
||||
# class addresses the dual protocols that the server needs to understand.
|
||||
class HttpAwareConnection < EventMachine::WebSocket::Connection
|
||||
attr_reader :reload_body, :reload_size
|
||||
|
||||
def initialize(_opts)
|
||||
# If EventMachine SSL support on Windows ever gets better, the code below will
|
||||
# set up the reactor to handle SSL
|
||||
#
|
||||
# @ssl_enabled = opts["ssl_cert"] && opts["ssl_key"]
|
||||
# if @ssl_enabled
|
||||
# em_opts[:tls_options] = {
|
||||
# :private_key_file => Jekyll.sanitized_path(opts["source"], opts["ssl_key"]),
|
||||
# :cert_chain_file => Jekyll.sanitized_path(opts["source"], opts["ssl_cert"])
|
||||
# }
|
||||
# em_opts[:secure] = true
|
||||
# end
|
||||
|
||||
# This is too noisy even for --verbose, but uncomment if you need it for
|
||||
# a specific WebSockets issue. Adding ?LR-verbose=true onto the URL will
|
||||
# enable logging on the client side.
|
||||
# em_opts[:debug] = true
|
||||
|
||||
em_opts = {}
|
||||
super(em_opts)
|
||||
|
||||
reload_file = File.join(Serve.singleton_class::LIVERELOAD_DIR, "livereload.js")
|
||||
|
||||
@reload_body = File.read(reload_file)
|
||||
@reload_size = @reload_body.bytesize
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def dispatch(data)
|
||||
parser = Http::Parser.new
|
||||
parser << data
|
||||
|
||||
# WebSockets requests will have a Connection: Upgrade header
|
||||
if parser.http_method != "GET" || parser.upgrade?
|
||||
super
|
||||
elsif parser.request_url.start_with?("/livereload.js")
|
||||
headers = [
|
||||
"HTTP/1.1 200 OK",
|
||||
"Content-Type: application/javascript",
|
||||
"Content-Length: #{reload_size}",
|
||||
"",
|
||||
"",
|
||||
].join("\r\n")
|
||||
send_data(headers)
|
||||
|
||||
# stream_file_data would free us from keeping livereload.js in memory
|
||||
# but JRuby blocks on that call and never returns
|
||||
send_data(reload_body)
|
||||
close_connection_after_writing
|
||||
else
|
||||
body = "This port only serves livereload.js over HTTP.\n"
|
||||
headers = [
|
||||
"HTTP/1.1 400 Bad Request",
|
||||
"Content-Type: text/plain",
|
||||
"Content-Length: #{body.bytesize}",
|
||||
"",
|
||||
"",
|
||||
].join("\r\n")
|
||||
send_data(headers)
|
||||
send_data(body)
|
||||
close_connection_after_writing
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user