class Apache::UploadMerger
Constants
- CREATE_MODE
- DEFAULT_MERGE_THRESHOLD
- VERSION
Public Class Methods
new(map = {}, strategy = DEFAULT_MERGE_THRESHOLD)
click to toggle source
Creates a new RubyHandler instance for the Apache
web server. It is to be installed as a custom 404 ErrorDocument handler.
The argument map
contains key/value pairs of URL prefixes and upload base directories.
strategy
determines how merging happens:
:symlink
-
Files are symlinked
:copy
-
Files are copied
Integer
-
Files whose size is below that threshold are copied, others are symlinked (default)
# File lib/apache/upload_merger.rb 55 def initialize(map = {}, strategy = DEFAULT_MERGE_THRESHOLD) 56 @map, @strategy = {}, strategy 57 58 define_merger 59 60 map.each { |prefix, dir| 61 @map[prefix] = [%r{\A#{prefix}/(.*)}, dir] 62 } 63 end
Public Instance Methods
handler(request)
click to toggle source
If the current request
asked for a resource that's not there, it will be merged from one of the appropriate upload directories, determined by its URL prefix. If no matching resource could be found, the original error will be thrown.
# File lib/apache/upload_merger.rb 69 def handler(request) 70 request.add_common_vars # REDIRECT_URL 71 72 if url = request.subprocess_env['REDIRECT_URL'] and 73 prefix = request.path_info.untaint and 74 map = @map[prefix] and 75 path = url[map[0], 1].untaint and 76 src = find(map[1], path) 77 78 merge(src, File.join(request.server.document_root, prefix, path)) 79 80 request.status = HTTP_OK 81 request.internal_redirect(url) 82 83 OK 84 else 85 DECLINED 86 end 87 end
Private Instance Methods
copy(src, dest, stat = File.stat(src))
click to toggle source
TODO: optimize?
# File lib/apache/upload_merger.rb 118 def copy(src, dest, stat = File.stat(src)) 119 File.open(src) { |src_| 120 File.open(dest, CREATE_MODE, stat.mode) { |dest_| 121 FileUtils.copy_stream(src_, dest_) 122 } 123 } 124 rescue Errno::EEXIST 125 end
copy_or_symlink(src, dest)
click to toggle source
# File lib/apache/upload_merger.rb 107 def copy_or_symlink(src, dest) 108 stat = File.stat(src) 109 stat.size > @strategy ? symlink(src, dest) : copy(src, dest, stat) 110 end
define_merger()
click to toggle source
# File lib/apache/upload_merger.rb 99 def define_merger 100 class << self; self; end.send :alias_method, :merge, case @strategy 101 when :symlink, :copy then @strategy 102 when Integer then :copy_or_symlink 103 else raise ArgumentError, "illegal strategy #{@strategy.inspect}" 104 end 105 end
find(dir, path)
click to toggle source
TODO: make it fast and secure
# File lib/apache/upload_merger.rb 92 def find(dir, path) 93 Dir["#{dir}/*/"].find { |subdir| 94 file = File.join(subdir, path).untaint 95 return file if File.exists?(file) 96 } 97 end
symlink(src, dest)
click to toggle source
# File lib/apache/upload_merger.rb 112 def symlink(src, dest) 113 File.symlink(src, dest) 114 rescue Errno::EEXIST 115 end