# Robust HTTP file upload server in Ruby?

**URL:** <https://www.ruby-forum.com/t/robust-http-file-upload-server-in-ruby/188613>\
**Category:** Ruby\
**Created:** [May 14, 2010, 6:45pm UTC](https://www.ruby-forum.com/t/robust-http-file-upload-server-in-ruby/188613 "2010-05-14T18:45:52Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![murfhy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/d26b3c/32.png) [@murfhy](https://www.ruby-forum.com/u/murfhy)\
**Post date:** [May 14, 2010, 6:45pm UTC](https://www.ruby-forum.com/t/robust-http-file-upload-server-in-ruby/188613/1 "2010-05-14T18:45:52Z")

</div>

I’m looking for a server-side HTTP file upload solution in Ruby which  
would  
allow a partially completed uploads to be resumed with an HTTP PUT (+  
Range?) request.

Does anything like this already exist, or is it something I’d have to  
build  
myself?

---

<div class="post-metadata">

**Author:** ![murfhy](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/d26b3c/32.png) [@murfhy](https://www.ruby-forum.com/u/murfhy)\
**Post date:** [May 15, 2010, 12:44am UTC](https://www.ruby-forum.com/t/robust-http-file-upload-server-in-ruby/188613/2 "2010-05-15T00:44:34Z")

</div>

Tony A. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’m looking for a server-side HTTP file upload solution in Ruby which would  
> allow a partially completed uploads to be resumed with an HTTP PUT (+  
> Range?) request.
> 
> Does anything like this already exist, or is it something I’d have to build  
> myself?

Hi Tony,

You could probably build a simple Rack handler (like below, just  
with actual parsing and safety checking) and run it with any Rack  
server.

While I’ve never needed Range: support for uploads, Rainbows! (and  
Unicorn) is heavily tested with PUT file uploads, and supports rare  
things like chunked request bodies and HTTP trailers.

Rainbows! even supports Revactor / Rev 🙂

## ---------- [config.ru](http://config.ru) --------- use Rack::ContentLength use Rack::ContentType require ‘put\_resume’ run PutResume.new # see below

---------- put\_resume.rb ---------

# totally untested, but based on working code I have

# There’s nothing Rainbows!-specific here, at all

class PutResume  
def call(env)  
# FIXME: path validation here  
File.open(File.basename(env[“PATH\_INFO”], ‘wb’)) do |fp|  
if range = env[“HTTP\_RANGE”]  
# implement parse\_range yourself, the spec allows for multiple  
# ranges in a multipart request, but I consider those rare  
enough  
# to ignore for now…  
start, count = parse\_range(range)

```
    # not doing anything with count in this example, we'll just
    # assume the client won't send more than (count - start) bytes
    # but beware of malicious clients
    fp.sysseek(start)
  end

  input = env["rack.input"]
  if buf = input.read(0x4000)
    begin
      fp.syswrite(buf)
    end while input.read(0x4000, buf)
  end
end

[201, {}, [ "Created\n"] ]

```

end  
end

— rainbows.conf.rb —  
Rainbows! do  
use :Revactor # or :Rev, or anything else Rainbows! supports

# client\_max\_body\_size is new in Rainbows! 0.92.0, the default is

# only 1M (same as nginx, but you can override it to anything you

# want (in bytes))

client\_max\_body\_size 100 \* 1024 \* 1024  
end

# optional, but you probably want these in a production environment

## stderr\_path “/path/to/stderr.log” stdout\_path “/path/to/stdout.log” pid “/path/to/rainbows.pid” worker\_processes 2 # or however many you want to run

# to run it all:

$ rainbows -c rainbows.conf.rb [config.ru](http://config.ru)
