Skip to content

Instantly share code, notes, and snippets.

@nnabeyang
Created August 2, 2012 05:34
Show Gist options
  • Save nnabeyang/3234068 to your computer and use it in GitHub Desktop.
Save nnabeyang/3234068 to your computer and use it in GitHub Desktop.
静的ページのミドルウェア(Rack)
require './static'
class Application
class << self
def instance
@instance ||= new
end
def method_missing(*args, &block)
instance.send(*args, &block)
end
end
def app
@app ||= begin
stack = MiddlewareStack.new
stack.use Static, File.dirname(__FILE__)
stack.build(Hello.new)
end
end
def call(env)
app.call(env)
end
end
class Hello
def call(env)
[200, {'Content-type' => 'text/html'}, [<<-HTML
<html>
<title>hello</title>
<body>
<h1>hello</h1>
</body>
</html>
HTML
]]
end
end
require './application'
run Application
<html>
<title>INDEX</title>
<body>
<h1>INDEX PAGE</h1>
</body>
</html>
require 'rack/file'
class FileHandler
def initialize(root)
@root = root.chomp('/')
@file_server = ::Rack::File.new(@root)
end
def match?(path)
full_path = File.join(@root, path)
matches = Dir["#{full_path}{,.html,index.html}"]
match = matches.detect {|m| File.file?(m)}
match.sub!(/^#{@root}\//, '') if match
end
def call(env)
@file_server.call(env)
end
end
class Static
def initialize(app, root)
@app = app
@file_handler = FileHandler.new(root)
end
def call(env)
case env['REQUEST_METHOD']
when 'GET', 'HEAD'
if path = @file_handler.match?(env['PATH_INFO'])
env['PATH_INFO'] = path
return @file_handler.call(env)
end
end
@app.call(env)
end
end
class MiddlewareStack
class Middleware
def initialize(klass, opts)
@klass = klass
@opts = opts
end
def build(app)
@klass.new(app, *@opts)
end
end
def middlewares
@middlewares ||= []
end
def use klass, *opts
middlewares.unshift(self.class::Middleware.new(klass, opts))
end
def build app
middlewares.inject(app) {|a, m| m.build(a)}
end
end
#!/usr/bin/ruby1.9.1
require 'test/unit'
require 'rack/mock'
require './static'
require './application'
class Tests < Test::Unit::TestCase
def test_file_handler_match
original_dir = Dir.pwd
root = File.expand_path('../data', __FILE__)
Dir.chdir(root)
handler = FileHandler.new(root)
assert_equal 'index.html', handler.match?('')
assert_nil handler.match?('no_such_file')
assert_equal 'assets/application.css', handler.match?('assets/application.css')
ensure
Dir.chdir(original_dir)
end
def test_file_handler_get
root = File.expand_path('../data', __FILE__)
file_handler = FileHandler.new(root)
path = file_handler.match? 'assets/application.css'
res = ::Rack::MockRequest.new(FileHandler.new(root)).get(path)
assert res.ok?
end
def test_static
root = File.expand_path('../data', __FILE__)
stack = MiddlewareStack.new
stack.use ::Rack::MockRequest
stack.use Static, root
ran = false
req = stack.build(proc {ran = true; [200, {}, []]})
assert_match /div/, req.get('assets/application.css').body
assert !ran
req.get('no_such_file')
assert ran
end
def test_application
req = ::Rack::MockRequest.new(Application)
assert_match /div/, req.get('data/assets/application.css').body
assert_match /INDEX/, req.get('data/').body
assert_match /INDEX/, req.get('data/index').body
assert_match /INDEX/, req.get('data/index.html').body
assert_match /hello/, req.get('no_such_file').body
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment