#!/usr/bin/ruby # main.rb require 'socket' require 'fileutils' require 'pathname' require 'erb' Root = '.' Port = 8080 class HttpResponse def self.process_erb(resp) unless resp.ext === ".erb" resp.data = resp.lazy.read return end books = Dir["*"] template = ERB.new resp.lazy.read resp.data = template.result(binding) return end def self.connection(str) "Connection: #{str}" end def self.content_length(resp) "Content-Length: #{resp.length}" end def self.content_type(resp) ctype = { ".png" => "image/png", ".txt" => "text/plain", ".html" => "text/html", ".erb" => "text/html", ".css" => "text/css", ".mp3" => "audio/mpeg", ".ttf" => "font/ttf", ".mp4" => "video/mp4", ".pdf" => "application/pdf", ".webp" => "image/webp" } "Content-Type: #{ctype[resp.ext]}" end def self.build(resp) resp.route if resp.not_found? return "HTTP/1.1 404 NOT FOUND\r\n" end process_erb(resp) headers = [ content_length(resp), content_type(resp), ].join("\r\n") puts headers return "HTTP/1.1 200 OK\r\n#{headers}\r\n\r\n#{resp.data}" end end class HttpRouter attr_reader :ext attr_reader :length attr_accessor :data attr_reader :lazy def initialize(path) @path = Pathname.new(path) @ext = File.extname(path) @not_found = false @data end def route puts @path case @path when Pathname.new("/") @path = Pathname.new("/index.erb") return route else if File.exist? @path.basename @lazy = File.open(@path.basename) @length = File.size(@path.basename) @ext = File.extname(@path) else @not_found = true end end end def not_found? @not_found end end class HttpServer def initialize(port) @server = TCPServer.new port end def accept_connection while session = @server.accept request = session.gets verb, path, protocol = request.split(' ') if protocol === 'HTTP/1.1' resp = HttpRouter.new(path) session.puts HttpResponse.build(resp) else session.puts 'Connection Refused' end session.close end end end server = HttpServer.new Port server.accept_connection