Skip to content

Instantly share code, notes, and snippets.

@wobh
Last active December 13, 2015 23:29
Show Gist options
  • Save wobh/4991690 to your computer and use it in GitHub Desktop.
Save wobh/4991690 to your computer and use it in GitHub Desktop.
A simple rack app with response builder hack.
require 'pathname'
require 'pp'
class HTTPResponseBuilder
STATUS_CODES = {100 => "Continue",
101 => "Switching Protocols",
200 => "OK",
201 => "Created",
202 => "Accepted",
203 => "Non-Authoritative Information",
204 => "No Content",
205 => "Reset Content",
206 => "Partial Content",
300 => "Multiple Choices",
301 => "Moved Permanently",
302 => "Found",
303 => "See Other",
304 => "Not Modified",
305 => "Use Proxy",
307 => "Temporary Redirect",
400 => "Bad Request",
401 => "Unauthorized",
402 => "Payment Required",
403 => "Forbidden",
404 => "Not Found",
405 => "Method Not Allowed",
406 => "Not Acceptable",
407 => "Proxy Authentication Required",
408 => "Request Time-out",
409 => "Conflict",
410 => "Gone",
411 => "Length Required",
412 => "Precondition Failed",
413 => "Request Entity Too Large",
414 => "Request-URI Too Large",
415 => "Unsupported Media Type",
416 => "Requested range not satisfiable",
417 => "Expectation Failed",
500 => "Internal Server Error",
501 => "Not Implemented",
502 => "Bad Gateway",
503 => "Service Unavailable",
504 => "Gateway Time-out",
505 => "HTTP Version not supported"}
def valid_code? (code)
STATUS_CODES.has_key?(code)
end
def set_code (code)
if valid_code?(code) || code.nil?
@code = code
else
raise("Invalid HTTP status code input: #{code}")
end
end
def add_head (field_name, field_value)
@head[field_name] = field_value
end
def add_head_content_type (mime_type)
# TODO: check valid mime-types
add_head("Content-Type", mime_type)
end
def add_head_content_length (length)
add_head("Content-Length", length.to_s)
end
def date_rfc_1123 ()
datetime = Time.now
datetime.gmtime.strftime("%a, %d %b %Y %H:%M:%S GMT")
end
def add_head_date (date=date_rfc_1123)
add_head("Date", date)
end
def add_data (data)
@data.push(data)
end
def initialize (code=nil, head={}, data=[])
@code = set_code(code)
@head = head
@data = data
end
def to_rack_plain (status_code)
unless valid_code?(status_code)
raise("Invalid HTTP status code input: #{status_code}")
end
set_code(status_code)
text = STATUS_CODES[@code]
@data.push(text)
add_head_content_length(text.bytesize)
add_head_content_type("text/plain")
add_head_date()
return [@code, @head, @data]
end
def to_rack ()
unless valid_code?(@code)
raise("Invalid HTTP status code: #{@code}")
end
@data = @data.join
add_head_content_length(@data.bytesize)
add_head_date()
return [@code, @head, [@data]]
end
end
#FIXME: use Rack::Response
class App
@@mime_type_of_ext = {".ico" => "image/vnd.microsoft.icon",
".text" => "text/plain",
".txt" => "text/plain",
".html" => "text/html",
".htm" => "text/html"}
def get_file (reqs, resp)
pp "reqs.path = " + reqs.path
fp = Pathname.new("." + reqs.path)
case fp.to_s
when "./"
fp = Pathname.new("./index.html")
when "./favicon.ico"
fp = Pathname.new("./Images/favicon.ico")
end
# FIXME: use Rack::File
# dn = File.dirname(fp)
# fn = File.basename(fp)
# ex = File.extname(fp)
pp "filepath = " + fp.to_s
pp "dirname = " + fp.dirname.to_s
pp "basename = " + fp.basename.to_s
pp "extension = " + fp.extname.to_s
if fp.exist?
resp.set_code(200)
fp.open('r') do |fd|
resp.add_data(fd.read)
end
else
return resp.to_rack_plain(404)
end
resp.add_head_content_type(@@mime_type_of_ext[fp.extname.to_s])
# pp resp.to_rack
return resp.to_rack
end
def call (env)
resp = HTTPResponseBuilder.new()
reqs = Rack::Request.new(env)
get_file(reqs, resp)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment