class Attache::Tus::Upload
Public Class Methods
new(app)
click to toggle source
# File lib/attache/tus/upload.rb, line 2 def initialize(app) @app = app end
Public Instance Methods
_call(env, config)
click to toggle source
# File lib/attache/tus/upload.rb, line 6 def _call(env, config) case env['PATH_INFO'] when '/tus/files' tus = ::Attache::Tus.new(env, config) params = params_of(env) # avoid unnecessary `invalid byte sequence in UTF-8` on `request.params` return config.unauthorized unless config.authorized?(params) case env['REQUEST_METHOD'] when 'POST' if positive_number?(tus.upload_length) relpath = generate_relpath(Attache::Upload.sanitize(tus.upload_metadata['filename'] || params['file'])) cachekey = File.join(request_hostname(env), relpath) bytes_wrote = Attache.cache.write(cachekey, StringIO.new) uri = URI.parse(Rack::Request.new(env).url) uri.query = (uri.query ? "#{uri.query}&" : '') + "relpath=#{CGI.escape relpath}" [201, tus.headers_with_cors('Location' => uri.to_s), []] else [400, tus.headers_with_cors('X-Exception' => "Bad upload length"), []] end when 'PATCH' relpath = params['relpath'] cachekey = File.join(request_hostname(env), relpath) http_offset = tus.upload_offset if positive_number?(env['CONTENT_LENGTH']) && positive_number?(http_offset) && (env['CONTENT_TYPE'] == 'application/offset+octet-stream') && tus.resumable_version.to_s == '1.0.0' && current_offset(cachekey, relpath, config) >= http_offset.to_i append_to(cachekey, http_offset, env['rack.input']) config.storage_create(relpath: relpath, cachekey: cachekey) if config.storage && config.bucket [200, tus.headers_with_cors({'Content-Type' => 'text/json'}, offset: current_offset(cachekey, relpath, config)), [json_of(relpath, cachekey, config)], ] else [400, tus.headers_with_cors('X-Exception' => 'Bad headers'), []] end when 'OPTIONS' [201, tus.headers_with_cors, []] when 'HEAD' relpath = params['relpath'] cachekey = File.join(request_hostname(env), relpath) [200, tus.headers_with_cors({'Content-Type' => 'text/json'}, offset: current_offset(cachekey, relpath, config)), [json_of(relpath, cachekey, config)], ] when 'GET' relpath = params['relpath'] uri = URI.parse(Rack::Request.new(env).url) uri.query = nil uri.path = File.join('/view', File.dirname(relpath), 'original', CGI.escape(File.basename(relpath))) [302, tus.headers_with_cors('Location' => uri.to_s), []] end else @app.call(env) end end
Private Instance Methods
append_to(cachekey, offset, io)
click to toggle source
# File lib/attache/tus/upload.rb, line 84 def append_to(cachekey, offset, io) f = File.open(path_of(cachekey), 'r+b') f.sync = true f.seek(offset.to_i) f.write(io.read) ensure f.close end
current_offset(cachekey, relpath, config)
click to toggle source
# File lib/attache/tus/upload.rb, line 73 def current_offset(cachekey, relpath, config) file = Attache.cache.fetch(cachekey) do config.storage_get(relpath: relpath) if config.storage && config.bucket end file.size rescue Attache.cache.write(cachekey, StringIO.new) ensure file.tap(&:close) end
positive_number?(value)
click to toggle source
# File lib/attache/tus/upload.rb, line 93 def positive_number?(value) (value.to_s == "0" || value.to_i > 0) end