1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Mongrel gets some hooks to help with upload progress.

git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@260 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
zedshaw 2006-06-25 14:49:46 +00:00
parent 49856e52b0
commit f26ffd1a91
6 changed files with 66 additions and 40 deletions

View file

@ -85,6 +85,7 @@ task :install do
sh %{rake package}
sh %{gem install pkg/mongrel-#{version}}
sub_project("mongrel_status", :install)
sub_project("mongrel_upload_progress", :install)
sub_project("mongrel_console", :install)
if RUBY_PLATFORM =~ /mswin/
sub_project("mongrel_service", :install)
@ -93,6 +94,7 @@ end
task :uninstall => [:clean] do
sub_project("mongrel_status", :uninstall)
sub_project("mongrel_upload_progress", :uninstall)
sub_project("mongrel_console", :uninstall)
sh %{gem uninstall mongrel}
sub_project("gem_plugin", :uninstall)

View file

@ -46,6 +46,15 @@
<h4>NEWS</h4>
<dl>
<dt>Jun-25-2006</dt>
<dd>
<h5><a href="{relocatable: news.html}">Mongrel 0.3.13.2 -- RailsConf 2006 Release</a></h5>
<p>Release from RailsConf that does Upload Progress and defending better.</p>
<a href="{relocatable: news.html}" title="Read About It">Read About It</a>
<a href="{relocatable: news.html}"><img src="{relocatable: images/li4.gif}" alt="more" /><br /></a></p>
</dd>
<dt>Jun-20-2006</dt>
<dd>
<h5><a href="{relocatable: news.html}">Mongrel 0.3.13.1 Small Bug Fixes</a></h5>

View file

@ -7,7 +7,35 @@ ordering: 2
h1. Latest News
h2. Jun 20: Mongrel 0.3.13.2 -- Small Fixes
h2. Jun 25: Mongrel 0.3.13.2 -- RailsConf 2006 Release
This is the release that came out of RailsConf hacking with folks like Rick
Olsen, Why The Luck Stiff and other incredibly cool folks. The conference
was great, so lets hope this release is good too. The big thing it adds
is *upload progress in Mongrel*. That's right, Why and Rick pinned me down
and made me put it in Mongrel. They worked up the mongrel_upload_progress
plugin and are now working on Rails and Camping code to make it happen.
Install from the gem servers with your usual commands:
gem update
*or*
gem update mongrel
*or*
gem install mongrel
But if you can't wait for the gem mirrors to update, then you can also do:
gem install mongrel --source=http://mongrel.rubyforge.org/releases
To get around it all.
h2. Jun 20: Mongrel 0.3.13.2 Pre-Release -- Small Fixes
This is a small release that fixes a little bug, some of the documentation,
and adds the new RedirectHandler code and a @redirect@ call for the mongrel.conf

View file

@ -184,7 +184,12 @@ module Mongrel
#
# The HttpRequest.initialize method will convert any request that is larger than
# Const::MAX_BODY into a Tempfile and use that as the body. Otherwise it uses
# a StringIO object. To be safe, you should assume it works like a file.
# a StringIO object. To be safe, you should assume it works like a file.
#
# The HttpHandler.request_notify system is implemented by having HttpRequest call
# HttpHandler.request_begins, HttpHandler.request_progress, HttpHandler.process during
# the IO processing. This adds a small amount of overhead but lets you implement
# finer controlled handlers and filters.
class HttpRequest
attr_reader :body, :params
@ -209,9 +214,11 @@ module Mongrel
begin
@body.write(initial_body)
notifier.request_begins(params) if notifier
# write the odd sized chunk first
clen -= @body.write(@socket.read(clen % Const::CHUNK_SIZE))
notifier.request_progress(params, clen, total) if notifier
# then stream out nothing but perfectly sized chunks
while clen > 0 and !@socket.closed?
@ -227,7 +234,6 @@ module Mongrel
@body.rewind
rescue Object
# any errors means we should delete the file, including if the file is dumped
STDERR.puts "ERROR: #$!"
@socket.close unless @socket.closed?
@body.delete if @body.class == Tempfile
@body = nil # signals that there was a problem
@ -539,17 +545,11 @@ module Mongrel
params[Const::PATH_INFO] = path_info
params[Const::SCRIPT_NAME] = script_name
params[Const::REMOTE_ADDR] = params[Const::HTTP_X_FORWARDED_FOR] || client.peeraddr.last
notifier = nil
notifier = handlers[0].request_notify ? handlers[0] : nil
# TODO: Find a faster/better way to carve out the range, preferably without copying.
data = data[nparsed ... data.length] || ""
if handlers[0].request_notify
# this first handler wants to be notified when the process starts
notifier = handlers[0]
notifier.request_begins(params)
end
request = HttpRequest.new(params, data, client, notifier)
# in the case of large file uploads the user could close the socket, so skip those requests

View file

@ -41,6 +41,12 @@ module Mongrel
def request_begins(params)
end
# Called by Mongrel for each IO chunk that is received on the request socket
# from the client, allowing you to track the progress of the IO and monitor
# the input.
def request_progress(params, clen, total)
end
def process(request, response)
end
@ -59,6 +65,9 @@ module Mongrel
def request_begins(params)
end
def request_progress(params, clen, total)
end
def initialize(options={})
@options = options
@header_only = false

View file

@ -1,8 +1,7 @@
require 'mongrel'
require 'gem_plugin'
require File.join(File.dirname(__FILE__), 'progress')
class Uploads
class Mongrel::Uploads
include Singleton
def initialize
@ -38,52 +37,31 @@ class Uploads
end
end
class Progress < GemPlugin::Plugin "/handlers"
include Mongrel::HttpHandlerPlugin
def initialize(options)
end
def process(request, response)
qs = Mongrel::HttpRequest.query_parse(request.params['QUERY_STRING'])
status = Mongrel::Uploads.instance.check(qs['upload_id'])
response.start 200 do |head, out|
out.write write_status(status, qs['upload_id'])
end
end
protected
def write_status(status, upload_id)
status ? ([status['size'], status['received']] * ',') : "no status for #{upload_id}"
end
end
class Upload < GemPlugin::Plugin "/handlers"
include Mongrel::HttpHandlerPlugin
def initialize(options = {})
@upload_path = options[:upload_path] || 'tmp/uploads'
@redirect_url = options[:redirect_url]
@path_info = options[:path_info]
@request_notify = true
end
def request_begins(params)
upload_notify(:add, params, params[Const::CONTENT_LENGTH].to_i)
upload_notify(:add, params, params[Mongrel::Const::CONTENT_LENGTH].to_i) if params['PATH_INFO'] == @path_info
end
def request_progress(params, clen, total)
upload_notify(:mark, params, clen)
upload_notify(:mark, params, clen) if params['PATH_INFO'] == @path_info
end
def process(request, response)
upload_notify(:finish, request.params)
upload_notify(:finish, request.params) if request.params['PATH_INFO'] == @path_info
end
private
def upload_notify(action, params, *args)
upload_id = params['upload_id']
if params[Const::REQUEST_METHOD] == 'POST' && upload_id
Uploads.instance.send(action, upload_id, *args) if upload_id
upload_id = Mongrel::HttpRequest.query_parse(params['QUERY_STRING'])['upload_id']
if params[Mongrel::Const::REQUEST_METHOD] == 'POST' && upload_id
Mongrel::Uploads.instance.send(action, upload_id, *args) if upload_id
end
end
end