module Slinky::Server

Constants

ERROR_CSS
ERROR_HAML
ERROR_JS
INJECT_CSS

Public Class Methods

config() click to toggle source
# File lib/slinky/server.rb, line 16
def self.config; @config || ConfigReader.empty; end
config=(_config;) click to toggle source
# File lib/slinky/server.rb, line 15
def self.config= _config; @config = _config; end
dir() click to toggle source

Gets the root directory from which files should be served

# File lib/slinky/server.rb, line 13
def self.dir; @dir || "."; end
dir=(_dir;) click to toggle source

Sets the root directory from which files should be served

# File lib/slinky/server.rb, line 11
def self.dir= _dir; @dir = _dir; end
format_error_output(resp, mf, error) click to toggle source

Produces nice error output for various kinds of formats

# File lib/slinky/server.rb, line 74
def self.format_error_output resp, mf, error
  resp.content =
    case Pathname.new(mf.output_path).extname
    when ".html"
      Haml::Engine.new(ERROR_HAML).
        render(Object.new, errors: error.messages, css: ERROR_CSS)
    when ".css"
      resp.status = 200 # browsers ignore 500'd css
      INJECT_CSS.gsub("{REPLACE_ERRORS}",
                      error.messages.join("\n").gsub("'", "\""))
    when ".js"
      resp.status = 200 # browsers ignore 500'd js
      ERROR_JS
        .gsub("{REPLACE_CSS}",
              JSON.dump({css: ERROR_CSS.gsub("\n", "")}))
        .gsub("{REPLACE_ERRORS}", JSON.dump(error.messages))
    else
      error.message
    end
end
handle_file(resp, mf, compile = true) click to toggle source

Takes a manifest file and produces a response for it

# File lib/slinky/server.rb, line 96
def self.handle_file resp, mf, compile = true
  begin
    path = mf.process(nil, compile)
    serve_file resp, path.to_s
  rescue SlinkyError => e
    resp.status = 500
    if self.config.enable_browser_errors
      format_error_output(resp, mf, e)
    else
      resp.content = e.message
    end
    e.messages.each{|m|
      $stderr.puts(m.foreground(:red))
    }
  rescue => e
    resp.status = 500
    format_error_output(resp, mf, SlinkyError.new(
                          "Unknown error handling #{mf.source}: #{$!}\n"))
    $stderr.puts("Unknown error handling #{mf.source}: #{$!}".foreground(:red))
  end
  resp
end
manifest() click to toggle source
# File lib/slinky/server.rb, line 19
def self.manifest; @manifest; end
manifest=(_manifest;) click to toggle source
# File lib/slinky/server.rb, line 18
def self.manifest= _manifest; @manifest = _manifest; end
not_found(resp) click to toggle source

Returns the proper response for files that do not exist

# File lib/slinky/server.rb, line 140
def self.not_found resp
  resp.status = 404
  resp.content = "File not found\n"
end
path_for_uri(uri) click to toggle source

Splits a uri into its components, returning only the path sans initial forward slash.

# File lib/slinky/server.rb, line 23
def self.path_for_uri uri
  _, _, _, _, _, path, _, _  = URI.split uri
  path[1..-1] #get rid of the leading /
end
process_path(resp, path, pushstate = false) click to toggle source
# File lib/slinky/server.rb, line 43
def self.process_path resp, path, pushstate = false
  file = manifest.find_by_path(path).first

  if file.is_a? ManifestDir
    file = manifest.find_by_path(path + "/index.html").first
    path += "/index.html"
  end

  if file
    # They're requesting the source file and we should not
    # compile it (but still process directives)
    compile = !(file.source.end_with?(path) && file.source)
    handle_file(resp, file, compile)
  elsif !pushstate && p = config.pushstate_for_path("/" + path)
    path = p[0] == "/" ? p[1..-1] : p
    self.process_path(resp, path, true)
  else
    not_found resp
  end

  type = MIME::Types.type_for(path).first.to_s
  if resp.content.encoding.to_s == "UTF-8"
    type += "; charset=utf-8"
  end

  resp.content_type type

  resp
end
serve_file(resp, path) click to toggle source

Serves a file from the file system

# File lib/slinky/server.rb, line 120
def self.serve_file resp, path
  if File.exists?(path) && !File.directory?(path)
    size = File.size(path)
    _, _, extension = path.match(EXTENSION_REGEX).to_a
    # File reading code from rack/file.rb
    File.open(path, "rb") do |file|
      resp.content = ""
      while size > 0
        part = file.read([8192, size].min)
        break unless part
        size -= part.length
        resp.content << part
      end
    end
  else
    not_found resp
  end
end

Public Instance Methods

process_http_request() click to toggle source

Method called for every HTTP request made

# File lib/slinky/server.rb, line 29
def process_http_request
  resp = EventMachine::DelegatedHttpResponse.new(self)

  begin
    path = Server.path_for_uri(@http_request_uri)
  rescue
    resp.status = 500
    resp.content = "Invalid request"
    return
  end

  Server.process_path(resp, path).send_response
end