rack-large-uploads 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gemset ADDED
@@ -0,0 +1 @@
1
+ RVM_GEMSET="ruby-1.9.3@rack-large-uploads"
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.rvmrc ADDED
@@ -0,0 +1,11 @@
1
+ source .gemset
2
+ export USE_BUNDLER=force
3
+
4
+ rvm use --create --install $RVM_GEMSET
5
+
6
+ if [[ -s "./bootstrap.gems" ]]; then
7
+ if ! rvm gemset import bootstrap.gems > /dev/null 2>&1; then
8
+ echo "ERROR: Unable to bootstrap the gems" >&2
9
+ fi
10
+ fi
11
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rack-large-uploads.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Corey Innis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # Rack::LargeUploads
2
+
3
+ Rack middleware for handling large file uploads.Integrates nicely with the
4
+ Nginx upload module: http://www.grid.net.ru/nginx/upload.en.html
5
+
6
+ Includes `Rack::LargeUploads::UploadedFile`, which matches the definition of
7
+ `ActionDispatch::Http::UploadedFile`. So, little-to-no change should be
8
+ required when using, e.g., Rails.
9
+
10
+ Based largely on the [`Rack::Uploads` middleware](https://github.com/mutle/rack-uploads),
11
+ but with greater expectations regarding conventions, and specific support for
12
+ large files (dealing with memory issues).
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'rack-large-uploads'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install rack-large-uploads
27
+
28
+ ## Usage
29
+
30
+ example middleware configuration:
31
+
32
+ use Rack::LargeUploads do
33
+ before do |files|
34
+ # process uploaded files *before* application handling
35
+ end
36
+
37
+ after do |files|
38
+ # process uploaded files *after* application handling
39
+ end
40
+ end
41
+
42
+ example nginx configuration:
43
+
44
+ location / {
45
+ try_files $document_root/system/maintenance.html $uri $uri/index.html $uri.html @application;
46
+ }
47
+
48
+ location = /uploads {
49
+ # depends on the nginx upload module (http://www.grid.net.ru/nginx/upload.en.html)
50
+ upload_pass @application;
51
+
52
+ # NOTE: if there is no upload file in the request, nginx generates a 405.
53
+ # use that to pass the request on to the endpoint, instead of try_files
54
+ # which fails to play nicely with upload_pass.
55
+ #
56
+ # credit:
57
+ # http://www.nickager.com/blog/File-upload-using-Nginx-and-Seaside---step-1
58
+ error_page 405 415 = @application;
59
+
60
+ upload_store /path/to/app/tmp/uploads 1;
61
+ upload_store_access user:rw group:rw all:rw;
62
+
63
+ upload_pass_args on; # NOTE: handles URI params, not form content.
64
+ upload_pass_form_field "^[a-z_].*"; # ...and here is how we resolve that last.
65
+
66
+ # match the request params expected by ActionDispatch
67
+ upload_set_form_field "$upload_field_name[filename]" "$upload_file_name";
68
+ upload_set_form_field "$upload_field_name[type]" "$upload_content_type";
69
+ upload_set_form_field "$upload_field_name[tempfile]" "$upload_tmp_path";
70
+
71
+ upload_aggregate_form_field "$upload_field_name[md5]" "$upload_file_md5";
72
+ upload_aggregate_form_field "$upload_field_name[size]" "$upload_file_size";
73
+ }
74
+
75
+ location @application {
76
+ proxy_pass http://upstream_application;
77
+
78
+ # more config...
79
+ }
80
+
81
+ ## Contributing
82
+
83
+ 1. Fork it
84
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
85
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
86
+ 4. Push to the branch (`git push origin my-new-feature`)
87
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ begin
5
+ Bundler.setup
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts 'run `bundle install` to install missing gems'
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'rake'
13
+ require 'rspec/core/rake_task'
14
+
15
+ RSpec::Core::RakeTask.new(:spec) do |spec|
16
+ spec.rspec_opts = '-Ispec'
17
+ end
18
+
19
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
20
+ spec.rspec_opts = '-Ispec'
21
+ spec.rcov = true
22
+ end
23
+
24
+ task :default => :spec
data/bootstrap.gems ADDED
@@ -0,0 +1,2 @@
1
+ bundler -v 1.1.3
2
+
@@ -0,0 +1 @@
1
+ require 'rack/large-uploads'
@@ -0,0 +1,103 @@
1
+ require "rack/large-uploads/version"
2
+
3
+ # TODO: remove these dependencies:
4
+ require "action_dispatch"
5
+ require "active_support/core_ext"
6
+
7
+ module Rack
8
+ class LargeUploads
9
+ autoload :UploadedFile, 'rack/large-uploads/uploaded_file'
10
+
11
+ def initialize(app, options = {}, &block)
12
+ @app = app
13
+ @filters = {}
14
+
15
+ if block
16
+ if block.arity == 1
17
+ block.call(self)
18
+ else
19
+ instance_eval(&block)
20
+ end
21
+ end
22
+ end
23
+
24
+ def call(env)
25
+ request = Rack::Request.new(env)
26
+
27
+ if request.post? && request.form_data?
28
+ files = extract_files(request, request.params)
29
+ end
30
+
31
+ filter(:before, files) if files.present?
32
+ response = @app.call(env)
33
+ filter(:after, files) if files.present?
34
+
35
+ response
36
+ end
37
+
38
+ def before(&block)
39
+ @filters[:before] = block
40
+ end
41
+
42
+ def after(&block)
43
+ @filters[:after] = block
44
+ end
45
+
46
+ private
47
+
48
+ def filter(position, files)
49
+ @filters[position] && @filters[position].call(files)
50
+ end
51
+
52
+ def extract_files(request, params, files = [])
53
+ params.each do |key, value|
54
+ if file = file_from(request, key, value)
55
+ files << replace_param(params, key, file)
56
+ elsif value.is_a?(Hash)
57
+ files = extract_files(request, value, files)
58
+ end
59
+ end
60
+
61
+ files
62
+ end
63
+
64
+ def file_from(request, key, value)
65
+ # direct to rails...
66
+ # ----->
67
+ # key: file,
68
+ # value: {
69
+ # :filename =>"file.mov",
70
+ # :type =>"video/quicktime",
71
+ # :tempfile =>#<File:/var/folders/xn/x665dh2j6qx_t7w5bqcsfgcr0000gn/T/RackMultipart20120330-11052-1ysyd0c>,
72
+ # :name =>"video[file]",
73
+ # :head =>"Content-Disposition: form-data; name=\"video[file]\"; filename=\"file.mov\"\r\nContent-Type: video/quicktime\r\n"
74
+ # }
75
+
76
+ # with nginx upload (configured per README)...
77
+ # ----->
78
+ # key: file,
79
+ # value: {
80
+ # "filename"=>"file.mov",
81
+ # "type" =>"video/quicktime",
82
+ # "tempfile"=>"/path/to/app/tmp/uploads/1/0000000001",
83
+ # "md5" =>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
84
+ # "size" =>"5242880000"
85
+ # }
86
+ if value.is_a?(Hash)
87
+ attributes = HashWithIndifferentAccess.new(value)
88
+ tempfile = attributes[:tempfile]
89
+
90
+ if tempfile.present?
91
+ tempfile = ::File.new(tempfile) if tempfile.is_a?(String)
92
+ return Rack::LargeUploads::UploadedFile.new(attributes.merge({ :tempfile => tempfile }))
93
+ end
94
+ end
95
+
96
+ nil
97
+ end
98
+
99
+ def replace_param(params, key, file)
100
+ params[key] = file
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,31 @@
1
+ module Rack
2
+ class LargeUploads
3
+ class UploadedFile < ActionDispatch::Http::UploadedFile
4
+ def initialize(hash)
5
+ @uploaded_md5 = hash.delete(:md5)
6
+ @uploaded_size = hash.delete(:size)
7
+ super(hash)
8
+ @uploaded_path = path
9
+ end
10
+
11
+ def clean!(nilify = true)
12
+ raise "No such file or directory - #{@uploaded_path}" unless present?
13
+ ::File.delete(@tempfile.path)
14
+
15
+ # NOTE: it appears that an open file descriptor (or similar) remains
16
+ # after the file is removed on the filesystem. in most cases, we
17
+ # should expect to be unable to interact with the file after cleaning,
18
+ # but we make it optionally allowed.
19
+ if nilify
20
+ @tempfile = nil
21
+ end
22
+
23
+ self
24
+ end
25
+
26
+ def present?
27
+ @tempfile != nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ class LargeUploads
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rack/large-uploads/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Corey Innis"]
6
+ gem.email = ["corey@coolerator.net"]
7
+ gem.description = %q{Rack middleware for handling large file uploads. Integrates nicely with the Nginx upload module: http://www.grid.net.ru/nginx/upload.en.html}
8
+ gem.summary = %q{Rack middleware for handling large file uploads}
9
+ gem.homepage = "https://github.com/coreyti/rack-large-uploads"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "rack-large-uploads"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Rack::LargeUploads::VERSION
17
+
18
+ gem.required_ruby_version = ">= 1.9"
19
+ gem.add_development_dependency "bundler"
20
+ gem.add_development_dependency "rake"
21
+ gem.add_development_dependency "rspec"
22
+ gem.add_development_dependency "rr"
23
+ gem.add_development_dependency "simplecov"
24
+
25
+ # TODO: remove dependencies on these:
26
+ gem.add_runtime_dependency "actionpack"
27
+ gem.add_runtime_dependency "activesupport"
28
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::LargeUploads do
4
+ it "is defined" do
5
+ Rack::LargeUploads.should be_a(Class)
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ require 'bundler'
2
+
3
+ begin
4
+ Bundler.setup
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+
11
+ require 'rack/large-uploads'
12
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each do
13
+ |f| require f
14
+ end
15
+
16
+ RSpec.configure do |config|
17
+ config.mock_with :rr
18
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-large-uploads
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Corey Innis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &70180264879460 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70180264879460
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70180264895180 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70180264895180
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70180264894620 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70180264894620
47
+ - !ruby/object:Gem::Dependency
48
+ name: rr
49
+ requirement: &70180264894040 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70180264894040
58
+ - !ruby/object:Gem::Dependency
59
+ name: simplecov
60
+ requirement: &70180264893460 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70180264893460
69
+ - !ruby/object:Gem::Dependency
70
+ name: actionpack
71
+ requirement: &70180264892740 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70180264892740
80
+ - !ruby/object:Gem::Dependency
81
+ name: activesupport
82
+ requirement: &70180264892100 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :runtime
89
+ prerelease: false
90
+ version_requirements: *70180264892100
91
+ description: ! 'Rack middleware for handling large file uploads. Integrates nicely
92
+ with the Nginx upload module: http://www.grid.net.ru/nginx/upload.en.html'
93
+ email:
94
+ - corey@coolerator.net
95
+ executables: []
96
+ extensions: []
97
+ extra_rdoc_files: []
98
+ files:
99
+ - .gemset
100
+ - .gitignore
101
+ - .rspec
102
+ - .rvmrc
103
+ - Gemfile
104
+ - LICENSE
105
+ - README.md
106
+ - Rakefile
107
+ - bootstrap.gems
108
+ - lib/rack-large-uploads.rb
109
+ - lib/rack/large-uploads.rb
110
+ - lib/rack/large-uploads/uploaded_file.rb
111
+ - lib/rack/large-uploads/version.rb
112
+ - rack-large-uploads.gemspec
113
+ - spec/rack/large-uploads_spec.rb
114
+ - spec/spec_helper.rb
115
+ homepage: https://github.com/coreyti/rack-large-uploads
116
+ licenses: []
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '1.9'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ segments:
134
+ - 0
135
+ hash: -1884482723306409026
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 1.8.11
139
+ signing_key:
140
+ specification_version: 3
141
+ summary: Rack middleware for handling large file uploads
142
+ test_files:
143
+ - spec/rack/large-uploads_spec.rb
144
+ - spec/spec_helper.rb