Created
August 7, 2012 11:42
-
-
Save melborne/3284736 to your computer and use it in GitHub Desktop.
Lack is a minified Rack just for study.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Lack is a minified Rack just for study. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Lack::Builder | |
def self.parse_file(config) #8 | |
cfgfile = ::File.read(config) | |
app = eval "Lack::Builder.new {\n" + cfgfile + "\n}.to_app", TOPLEVEL_BINDING, config | |
return app | |
end | |
def initialize(&block) #9 | |
@use = [] | |
instance_eval(&block) | |
end | |
def use(middleware, *args, &block) #10 | |
@use << proc { |app| middleware.new(app, *args, &block) } | |
end | |
def run(app) #11 | |
@run = app | |
end | |
def to_app #12 | |
app = @run | |
@use.reverse.inject(app) { |a,e| e[a] } | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Lack::Handler | |
def self.default(options = {}) #17 | |
Lack::Handler::Thin | |
rescue LoadError | |
Lack::Handler::WEBrick | |
end | |
autoload :WEBrick, "lack/handler/webrick" | |
autoload :Thin, "lack/handler/thin" | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$:.unshift File.expand_path(File.join(*%w(.. lib)), File.dirname(__FILE__)) | |
module Lack | |
autoload :Builder, "lack/builder" | |
autoload :Handler, "lack/handler" | |
autoload :Server, "lack/server" | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require_relative "../lib/lack" | |
Lack::Server.start #0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Lack::Server | |
def self.start #1 | |
new.start | |
end | |
def start #2 | |
server.run wrapped_app, options | |
end | |
def options #3 | |
@options ||= parse_options(ARGV) | |
end | |
def parse_options(args) #4 | |
default_options | |
end | |
def default_options #5 | |
{ | |
:environment => ENV['RACK_ENV'] || "development", | |
:pid => nil, | |
:Port => 9292, | |
:Host => "0.0.0.0", | |
:AccessLog => [], | |
:config => "config.ru" | |
} | |
end | |
def wrapped_app #6 | |
@wrapped_app ||= build_app app | |
end | |
def app #7 | |
@app = Lack::Builder.parse_file(self.options[:config]) | |
end | |
def build_app(app) #13 | |
middleware[options[:environment]].reverse.inject(app) { |a, mid| mid.new(a) } | |
end | |
def middleware #14 | |
self.class.middleware | |
end | |
def self.middleware | |
@middleware ||= begin | |
m = Hash.new {|h,k| h[k] = []} | |
# m["deployment"].concat [ | |
# [Rack::ContentLength], | |
# [Rack::Chunked], | |
# logging_middleware | |
# ] | |
# m["development"].concat m["deployment"] + [[Rack::ShowExceptions], [Rack::Lint]] | |
m | |
end | |
end | |
def server #16 | |
@_server ||= Lack::Handler.default(options) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "thin" | |
module Lack::Handler | |
class Thin | |
def self.run(app, options={}) | |
server = ::Thin::Server.new(options[:Host] || '0.0.0.0', | |
options[:Port] || 8080, | |
app) | |
yield server if block_given? | |
server.start | |
end | |
def self.valid_options | |
{ | |
"Host=HOST" => "Hostname to listen on (default: localhost)", | |
"Port=PORT" => "Port to listen on (default: 8080)", | |
} | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'webrick' | |
require 'stringio' | |
module Lack::Handler | |
class WEBrick < ::WEBrick::HTTPServlet::AbstractServlet | |
def self.run(app, options={}) | |
options[:BindAddress] = options.delete(:Host) if options[:Host] | |
@server = ::WEBrick::HTTPServer.new(options) | |
@server.mount "/", Lack::Handler::WEBrick, app | |
yield @server if block_given? | |
@server.start | |
end | |
def self.valid_options | |
{ | |
"Host=HOST" => "Hostname to listen on (default: localhost)", | |
"Port=PORT" => "Port to listen on (default: 8080)", | |
} | |
end | |
def self.shutdown | |
@server.shutdown | |
@server = nil | |
end | |
def initialize(server, app) | |
super server | |
@app = app | |
end | |
def service(req, res) | |
env = req.meta_vars | |
env.delete_if { |k, v| v.nil? } | |
rack_input = StringIO.new(req.body.to_s) | |
rack_input.set_encoding(Encoding::BINARY) if rack_input.respond_to?(:set_encoding) | |
env.update({#"rack.version" => Lack::VERSION, | |
"rack.input" => rack_input, | |
"rack.errors" => $stderr, | |
"rack.multithread" => true, | |
"rack.multiprocess" => false, | |
"rack.run_once" => false, | |
"rack.url_scheme" => ["yes", "on", "1"].include?(ENV["HTTPS"]) ? "https" : "http" | |
}) | |
env["HTTP_VERSION"] ||= env["SERVER_PROTOCOL"] | |
env["QUERY_STRING"] ||= "" | |
unless env["PATH_INFO"] == "" | |
path, n = req.request_uri.path, env["SCRIPT_NAME"].length | |
env["PATH_INFO"] = path[n, path.length-n] | |
end | |
env["REQUEST_PATH"] ||= [env["SCRIPT_NAME"], env["PATH_INFO"]].join | |
status, headers, body = @app.call(env) | |
begin | |
res.status = status.to_i | |
headers.each { |k, vs| | |
if k.downcase == "set-cookie" | |
res.cookies.concat vs.split("\n") | |
else | |
# Since WEBrick won't accept repeated headers, | |
# merge the values per RFC 1945 section 4.2. | |
res[k] = vs.split("\n").join(", ") | |
end | |
} | |
body.each { |part| | |
res.body << part | |
} | |
ensure | |
body.close if body.respond_to? :close | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment