class SmallVictories::Server
Constants
- DEFAULT_CONTENT_TYPE
Treat as binary data if content type cannot be found
- TEMP_FILE
- WEB_ROOT
Files will be served from this directory
Attributes
config[RW]
server[RW]
socket[RW]
Public Class Methods
new(attributes={})
click to toggle source
This helper function parses the extension of the requested file and then looks up its content type.
# File lib/smallvictories/server.rb, line 22 def initialize attributes={} self.config = attributes[:config] end
Public Instance Methods
content_type(path)
click to toggle source
# File lib/smallvictories/server.rb, line 26 def content_type(path) if ext = File.extname(path).split(".").last MIME::Types.type_for(ext).first.to_s else 'text/html' end end
render_file(file, content_type=nil)
click to toggle source
This helper function saves the string to a temp file and streams it
# File lib/smallvictories/server.rb, line 62 def render_file file, content_type=nil socket.print "HTTP/1.1 200 OK\r\n" + "Content-Type: #{content_type || content_type(file)}\r\n" + "Content-Length: #{file.size}\r\n" + "Connection: close\r\n" socket.print "\r\n" # write the contents of the file to the socket IO.copy_stream(file, socket) end
render_string(string, content_type=nil)
click to toggle source
# File lib/smallvictories/server.rb, line 74 def render_string string, content_type=nil File.open(TEMP_FILE, "w") do |f| f.write(string) f.close end File.open(TEMP_FILE, "rb") { |f| render_file(f, content_type) } end
render_stylesheet()
click to toggle source
# File lib/smallvictories/server.rb, line 83 def render_stylesheet if File.exist?(File.join(WEB_ROOT, '_sv_custom.scss')) begin engine = Sass::Engine.new(File.open(File.join(WEB_ROOT, '_sv_custom.scss')).read, syntax: :scss) render_string(engine.render, 'text/css') rescue => e socket.print e end elsif File.exist?(File.join(WEB_ROOT, '_sv_custom.sass')) begin engine = Sass::Engine.new(File.open(File.join(WEB_ROOT, '_sv_custom.sass')).read, syntax: :sass) render_string(engine.render, 'text/css') rescue => e socket.print e end elsif File.exist?(File.join(WEB_ROOT, '_sv_custom.css')) # Open _sv_custom.css File.open(File.join(WEB_ROOT, '_sv_custom.css'), "rb") do |file| render_file(file) end end end
requested_file(request_line)
click to toggle source
This helper function parses the Request-Line and generates a path to a file on the server.
# File lib/smallvictories/server.rb, line 37 def requested_file(request_line) request_uri = request_line.split(" ")[1] path = URI.unescape(URI(request_uri).path) clean = [] # Split the path into components parts = path.split("/") parts.each do |part| # skip any empty or current directory (".") path components next if part.empty? || part == '.' # If the path component goes up one directory level (".."), # remove the last clean component. # Otherwise, add the component to the Array of clean components part == '..' ? clean.pop : clean << part end # return the web root joined to the clean path File.join(WEB_ROOT, *clean) end
run()
click to toggle source
# File lib/smallvictories/server.rb, line 106 def run # Except where noted below, the general approach of # handling requests and generating responses is # similar to that of the "Hello World" example # shown earlier. @server = TCPServer.new('localhost', 2345) loop do @socket = @server.accept request_line = socket.gets STDERR.puts request_line begin path = requested_file(request_line) path = File.join(path, 'index.html') if File.directory?(path) if path == File.join(WEB_ROOT, '_sv_custom.css') render_stylesheet elsif File.exist?(path) && !File.directory?(path) File.open(path, "rb") do |file| if File.extname(path) == '.html' # parse liquid template = Liquid::Template.parse(file.read, error_mode: :warn) render_string(template.render(SiteFile.files_hash)) else render_file(file) end end else message = "File not found\n" # respond with a 404 error code to indicate the file does not exist socket.print "HTTP/1.1 404 Not Found\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: #{message.size}\r\n" + "Connection: close\r\n" socket.print "\r\n" socket.print message end rescue => e socket.print "\r\n" end socket.close end end