#!/usr/bin/env ruby require "webrick" require "time" # Needed for Time.parse and iso8601 class ExcludingFileHandler < WEBrick::HTTPServlet::FileHandler def initialize(server, root, excluded) super(server, root, :FancyIndexing => true) @excluded = excluded @root = root end def service(req, res) if @excluded.any? { |path| req.path.include?(path) } res.status = 404 res.body = "Not Found" else super # Only decorate HTML files if res['Content-Type']&.include?("text/html") current = File.basename(req.path) articles = Dir.glob(File.join(@root, "*.html")) .map { |f| File.basename(f) } .reject { |f| f == current } unless articles.empty? links = articles.map { |f| "
  • #{f}
  • " }.join("\n") footer = <<~HTML

    Other Articles

    HTML res.body << footer end end end end end root = Dir.pwd require "mime/types" module WEBrick module HTTPUtils alias original_mime_type mime_type def self.mime_type(filename, mime_tab = DefaultMimeTypes) ext = File.extname(filename).sub(/^\./, "") mime_tab[ext] || (defined?(MIME::Types) && MIME::Types.type_for(ext).first&.to_s) || "application/octet-stream" end end end server = WEBrick::HTTPServer.new( :Port => 4567, :DocumentRoot => root, :DirectoryIndex => ["index.html", "index.htm"], :FancyIndexing => true ) # --- Mount /feed.xml FIRST (so it takes priority) --- server.mount_proc "/feed.xml" do |req, res| res['Content-Type'] = 'application/rss+xml' html_files = Dir.glob(File.join(root, "*.html")).sort_by { |f| File.mtime(f) }.reverse rss_items = html_files.map do |f| fname = File.basename(f) title = File.basename(fname, ".html").gsub("-", " ").capitalize date = File.mtime(f).utc.iso8601 <<~ITEM #{title} http://localhost:4567/#{fname} http://localhost:4567/#{fname} #{Time.parse(date).rfc2822} ITEM end.join("\n") res.body = <<~RSS Boundless Blue http://localhost:4567/ Recent posts from Boundless Blue en-us #{rss_items} RSS end # --- Mount everything else AFTER --- server.mount("/", ExcludingFileHandler, root, [".stfolder"]) trap("INT") { server.shutdown } server.start