Module: ServerSide::Static

Includes:
HTTP::Caching
Included in:
HTTP::Request
Defined in:
lib/serverside/static.rb

Overview

This module provides functionality for serving files and directory listings over HTTP.

Constant Summary collapse

ETAG_FORMAT =
'%x:%x:%x'.inspect.freeze
TEXT_PLAIN =
'text/plain'.freeze
TEXT_HTML =
'text/html'.freeze
MAX_CACHE_FILE_SIZE =

100KB for the moment

100000.freeze
DIR_LISTING_START =
'<html><head><title>Directory Listing for %s</title></head><body><h2>Directory listing for %s:</h2>'.freeze
DIR_LISTING =
'<a href="%s">%s</a><br/>'.freeze
DIR_LISTING_STOP =
'</body></html>'.freeze
FILE_NOT_FOUND =
'File not found.'.freeze
RHTML =
/\.rhtml$/.freeze
@@mime_types =
Hash.new {|h, k| TEXT_PLAIN}
@@static_files =
{}

Constants included from HTTP::Caching

HTTP::Caching::CACHE_CONTROL, HTTP::Caching::DEFAULT_MAX_AGE, HTTP::Caching::ETAG, HTTP::Caching::ETAG_WILDCARD, HTTP::Caching::IF_MODIFIED_SINCE, HTTP::Caching::IF_NONE_MATCH, HTTP::Caching::LAST_MODIFIED, HTTP::Caching::MAX_AGE, HTTP::Caching::NOT_MODIFIED_CLOSE, HTTP::Caching::NOT_MODIFIED_PERSIST

Instance Method Summary collapse

Methods included from HTTP::Caching

#send_not_modified, #valid_client_cache?, #validate_cache

Instance Method Details

#serve_dir(dir) ⇒ Object

Serves a directory listing over HTTP in the form of an HTML page.



56
57
58
59
60
61
62
63
64
# File 'lib/serverside/static.rb', line 56

def serve_dir(dir)
  entries = Dir.entries(dir)
  entries.reject! {|fn| fn =~ /^\./}
  entries.unshift('..') if dir != './'
  html = (DIR_LISTING_START % [@path, @path]) +
    entries.inject('') {|m, fn| m << DIR_LISTING % [@path/fn, fn]} +
    DIR_LISTING_STOP
  send_response(200, 'text/html', html)
end

#serve_file(fn) ⇒ Object

Serves a file over HTTP. The file is cached in memory for later retrieval. If the If-None-Match header is included with an ETag, it is checked against the file’s current ETag. If there’s a match, a 304 response is rendered.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/serverside/static.rb', line 38

def serve_file(fn)
  stat = File.stat(fn)
  etag = (ETAG_FORMAT % [stat.mtime.to_i, stat.size, stat.ino]).freeze
  validate_cache(etag, stat.mtime) do
    if @@static_files[fn] && (@@static_files[fn][0] == etag)
      content = @@static_files[fn][1]
    else
      content = IO.read(fn).freeze
      @@static_files[fn] = [etag.freeze, content]
    end
    send_response(200, @@mime_types[File.extname(fn)], content, stat.size)
  end
rescue => e
  puts e.message
  send_response(404, TEXT_PLAIN, 'Error reading file.')
end

#serve_static(path) ⇒ Object

Serves static files and directory listings.



73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/serverside/static.rb', line 73

def serve_static(path)
  if File.file?(path)
    serve_file(path)
  elsif serve_template(path)
    return
  elsif File.directory?(path)
    serve_dir(path)
  else
    send_response(404, 'text', FILE_NOT_FOUND)
  end
rescue => e
  send_response(500, 'text', e.message)
end

#serve_template(fn, b = nil) ⇒ Object



66
67
68
69
70
# File 'lib/serverside/static.rb', line 66

def serve_template(fn, b = nil)
  if (fn =~ RHTML) || (File.file?(fn = fn + '.rhtml'))
    send_response(200, TEXT_HTML, Template.render(fn, b || binding))
  end
end