Make Middleman somewhat more threadsafe and switch back to webrick.

This commit is contained in:
Ben Hollis 2012-04-30 21:50:31 -07:00
parent 713350e294
commit 778626c6ec
3 changed files with 49 additions and 40 deletions

View file

@ -269,7 +269,7 @@ module Middleman
# Accessor for current path # Accessor for current path
# @return [String] # @return [String]
def current_path def current_path
@_current_path Thread.current[:current_path]
end end
# Set the current path # Set the current path
@ -277,7 +277,7 @@ module Middleman
# @param [String] path The new current path # @param [String] path The new current path
# @return [void] # @return [void]
def current_path=(path) def current_path=(path)
@_current_path = path Thread.current[:current_path] = path
@request = ::Thor::CoreExt::HashWithIndifferentAccess.new({ @request = ::Thor::CoreExt::HashWithIndifferentAccess.new({
:path => path, :path => path,
:params => req ? ::Thor::CoreExt::HashWithIndifferentAccess.new(req.params) : {} :params => req ? ::Thor::CoreExt::HashWithIndifferentAccess.new(req.params) : {}
@ -317,25 +317,40 @@ module Middleman
delegate :cache, :to => :"self.class" delegate :cache, :to => :"self.class"
# Rack env # Rack env
attr :env def env
Thread.current[:env]
end
def env=(value)
Thread.current[:env] = value
end
# Rack request # Rack request
# @return [Rack::Request] # @return [Rack::Request]
attr :req def req
Thread.current[:req]
end
def req=(value)
Thread.current[:req] = value
end
# Rack response # Rack response
# @return [Rack::Response] # @return [Rack::Response]
attr :res def res
Thread.current[:res]
end
def res=(value)
Thread.current[:res] = value
end
# Rack Interface # Rack Interface
# #
# @private # @private
# @param Rack environment # @param Rack environment
def call(env) def call(env)
self.env = env
# Store environment, request and response for later # Store environment, request and response for later
@env = env self.req = req = Rack::Request.new(env)
@req = Rack::Request.new(env) self.res = res = Rack::Response.new
@res = Rack::Response.new
if env["PATH_INFO"] == "/__middleman__" if env["PATH_INFO"] == "/__middleman__"
if env["REQUEST_METHOD"] == "POST" if env["REQUEST_METHOD"] == "POST"
@ -354,7 +369,7 @@ module Middleman
# Catch :halt exceptions and use that response if given # Catch :halt exceptions and use that response if given
catch(:halt) do catch(:halt) do
process_request process_request(env, req, res)
res.status = 404 res.status = 404
res.finish res.finish
@ -381,38 +396,38 @@ module Middleman
# and return the correct file, response or status message. # and return the correct file, response or status message.
# #
# @private # @private
def process_request def process_request(env, req, res)
start_time = Time.now start_time = Time.now
# Normalize the path and add index if we're looking at a directory # Normalize the path and add index if we're looking at a directory
@original_path = URI.decode(env["PATH_INFO"].dup) original_path = URI.decode(env["PATH_INFO"].dup)
if @original_path.respond_to? :force_encoding if original_path.respond_to? :force_encoding
@original_path.force_encoding('UTF-8') original_path.force_encoding('UTF-8')
end end
@request_path = full_path(@original_path) request_path = full_path(original_path)
# Run before callbacks # Run before callbacks
run_hook :before run_hook :before
if @original_path != @request_path if original_path != request_path
# Get the resource object for this path # Get the resource object for this path
resource = sitemap.find_resource_by_destination_path(@original_path) resource = sitemap.find_resource_by_destination_path(original_path)
end end
# Get the resource object for this full path # Get the resource object for this full path
resource ||= sitemap.find_resource_by_destination_path(@request_path) resource ||= sitemap.find_resource_by_destination_path(request_path)
# Return 404 if not in sitemap # Return 404 if not in sitemap
return not_found unless resource && !resource.ignored? return not_found(res) unless resource && !resource.ignored?
# If this path is a static file, send it immediately # If this path is a static file, send it immediately
return send_file(resource.source_file) unless resource.template? return send_file(resource.source_file, env, res) unless resource.template?
# Set the current path for use in helpers # Set the current path for use in helpers
self.current_path = @request_path.dup self.current_path = request_path.dup
# Set a HTTP content type based on the request's extensions # Set a HTTP content type based on the request's extensions
content_type resource.mime_type content_type(resource.mime_type, env)
begin begin
# Write out the contents of the page # Write out the contents of the page
@ -474,10 +489,10 @@ module Middleman
protected protected
# Halt request and return 404 # Halt request and return 404
def not_found def not_found(res)
@res.status == 404 res.status == 404
@res.write "<html><body><h1>File Not Found</h1><p>#{@request_path}</p></body>" res.write "<html><body><h1>File Not Found</h1><p>#{@request_path}</p></body>"
@res.finish res.finish
end end
delegate :helpers, :use, :map, :to => :"self.class" delegate :helpers, :use, :map, :to => :"self.class"
@ -485,11 +500,11 @@ module Middleman
# Immediately send static file # Immediately send static file
# #
# @param [String] path File to send # @param [String] path File to send
def send_file(path) def send_file(path, env, res)
extension = File.extname(path) extension = File.extname(path)
matched_mime = mime_type(extension) matched_mime = mime_type(extension)
matched_mime = "application/octet-stream" if matched_mime.nil? matched_mime = "application/octet-stream" if matched_mime.nil?
content_type matched_mime content_type matched_mime, res
file = ::Rack::File.new nil file = ::Rack::File.new nil
file.path = path file.path = path
@ -503,7 +518,7 @@ module Middleman
# @param [String] type Content type # @param [String] type Content type
# @param [Hash] params # @param [Hash] params
# @return [void] # @return [void]
def content_type(type = nil, params={}) def content_type(type = nil, params={}, res)
return res['Content-Type'] unless type return res['Content-Type'] unless type
default = params.delete :default default = params.delete :default
mime_type = mime_type(type) || default mime_type = mime_type(type) || default
@ -548,12 +563,9 @@ module Middleman
app_class = options[:app] ||= ::Middleman.server.inst app_class = options[:app] ||= ::Middleman.server.inst
opts[:app] = app_class opts[:app] = app_class
# Use Thin because Webrick gets confused and mixes require "webrick"
# up responses. opts[:Logger] = WEBrick::Log::new("/dev/null", 7) if !options[:logging]
# TODO: Figure that out and drop Thin dependency opts[:server] = 'webrick'
require "thin"
::Thin::Logging.silent = !options[:logging]
opts[:server] = 'thin'
server = ::Rack::Server.new(opts) server = ::Rack::Server.new(opts)
server.start server.start

View file

@ -36,9 +36,6 @@ Gem::Specification.new do |s|
# Watcher # Watcher
s.add_dependency("listen", ["~> 0.4.1"]) s.add_dependency("listen", ["~> 0.4.1"])
# Web Server
s.add_dependency("thin", ["~> 1.3.1"])
# i18n # i18n
s.add_dependency("i18n", ["~> 0.6.0"]) s.add_dependency("i18n", ["~> 0.6.0"])
end end

View file

@ -42,7 +42,7 @@ module Middleman
else else
path = File.join(prefix, path) if prefix.length > 0 path = File.join(prefix, path) if prefix.length > 0
request_path = @request_path.dup request_path = current_path.dup
request_path << index_file if path.match(%r{/$}) request_path << index_file if path.match(%r{/$})
parts = request_path.gsub(%r{^/}, '').split('/') parts = request_path.gsub(%r{^/}, '').split('/')
@ -60,4 +60,4 @@ module Middleman
end end
end end
end end
end end