class RDoc::Server

A minimal HTTP server for live-reloading RDoc documentation.

Uses Ruby’s built-in TCPServer (no external dependencies).

Used by rdoc --server to let developers preview documentation while editing source files. Parses sources once on startup, watches for file changes, re-parses only the changed files, and auto-refreshes the browser via a simple polling script.

Constants

CONTENT_TYPES
STATUS_TEXTS

Public Class Methods

Returns a live-reload polling script with the given last_change_time embedded so the browser knows the exact timestamp of the content it received. This avoids a race where a change that occurs between page generation and the first poll would be silently skipped.

# File lib/rdoc/server.rb, line 28
    def self.live_reload_script(last_change_time)
      <<~JS
      <script>
      (function() {
        var lastChange = #{last_change_time.to_json};
        setInterval(function() {
          fetch('/__status').then(function(r) { return r.json(); }).then(function(data) {
            if (data.last_change > lastChange) location.reload();
            lastChange = data.last_change;
          }).catch(function() {});
        }, 1000);
      })();
      </script>
    JS
    end

Creates a new server.

rdoc is the RDoc::RDoc instance that has already parsed the source files. port is the TCP port to listen on.

# File lib/rdoc/server.rb, line 101
def initialize(rdoc, port)
  @rdoc = rdoc
  @options = rdoc.options
  @store = rdoc.store
  @port = port

  # Silence stats output — the server prints its own timing.
  @rdoc.stats.verbosity = 0
  @generator = create_generator
  @template_dir = File.expand_path(@generator.template_dir)
  @page_cache = {}
  @last_change_time = Time.now.to_f
  @mutex = Mutex.new
  @running = false
end

Public Instance Methods

Starts the server. Blocks until interrupted.

# File lib/rdoc/server.rb, line 120
def start
  @tcp_server = TCPServer.new('127.0.0.1', @port)
  @running = true

  @watcher_thread = start_watcher(@rdoc.watch_files)

  url = "http://localhost:#{@port}"
  $stderr.puts "\nServing documentation at: \e]8;;#{url}\e\\#{url}\e]8;;\e\\"
  $stderr.puts "Press Ctrl+C to stop.\n\n"

  loop do
    client = @tcp_server.accept
    Thread.new(client) { |c| handle_client(c) }
  end
rescue Interrupt
  # Ctrl+C
ensure
  @running = false
  @tcp_server&.close
  @watcher_thread&.join(2)
end