class Tus::Server
Constants
- HOOKS
- RESUMABLE_CONTENT_TYPE
- SUPPORTED_CHECKSUM_ALGORITHMS
- SUPPORTED_EXTENSIONS
- SUPPORTED_VERSIONS
Public Instance Methods
created!(location)
click to toggle source
# File lib/tus/server.rb, line 411 def created!(location) response.status = 201 response.headers["Location"] = location request.halt end
error!(status, message)
click to toggle source
# File lib/tus/server.rb, line 417 def error!(status, message) response.status = status response.write(message) unless request.head? response.headers["Content-Type"] = "text/plain" request.halt end
expiration_interval()
click to toggle source
# File lib/tus/server.rb, line 436 def expiration_interval opts[:expiration_interval] end
expiration_time()
click to toggle source
# File lib/tus/server.rb, line 432 def expiration_time opts[:expiration_time] end
get_input(info)
click to toggle source
Wraps the Rack input (request body) into a Tus::Input
object, applying a size limit if one exists.
# File lib/tus/server.rb, line 221 def get_input(info) offset = info.offset total = info.length || max_size limit = total - offset if total Tus::Input.new(request.body, limit: limit) end
handle_cors!()
click to toggle source
# File lib/tus/server.rb, line 390 def handle_cors! origin = request.headers["Origin"] return if origin.to_s == "" response.headers["Access-Control-Allow-Origin"] = origin if request.options? response.headers["Access-Control-Allow-Methods"] = "POST, GET, HEAD, PATCH, DELETE, OPTIONS" response.headers["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Upload-Length, Upload-Offset, Tus-Resumable, Upload-Metadata, Upload-Defer-Length, Upload-Concat" response.headers["Access-Control-Max-Age"] = "86400" else response.headers["Access-Control-Expose-Headers"] = "Upload-Offset, Location, Upload-Length, Tus-Version, Tus-Resumable, Tus-Max-Size, Tus-Extension, Upload-Metadata, Upload-Defer-Length, Upload-Concat" end end
handle_range_request!(length)
click to toggle source
Handles partial responses requested in the “Range” header. Implementation is mostly copied from Rack::File.
# File lib/tus/server.rb, line 348 def handle_range_request!(length) if Rack.release >= "2.0" ranges = Rack::Utils.get_byte_ranges(request.headers["Range"], length) else ranges = Rack::Utils.byte_ranges(request.env, length) end # we support ranged requests response.headers["Accept-Ranges"] = "bytes" if ranges.nil? || ranges.length > 1 # no ranges, or multiple ranges (which we don't support) response.status = 200 range = 0..length-1 elsif ranges.empty? # unsatisfiable range response.headers["Content-Range"] = "bytes */#{length}" error!(416, "Byte range unsatisfiable") else range = ranges[0] response.status = 206 response.headers["Content-Range"] = "bytes #{range.begin}-#{range.end}/#{length}" end response.headers["Content-Length"] = range.size.to_s range end
max_size()
click to toggle source
# File lib/tus/server.rb, line 428 def max_size opts[:max_size] end
no_content!()
click to toggle source
# File lib/tus/server.rb, line 406 def no_content! response.status = 204 request.halt end
redirect_download()
click to toggle source
# File lib/tus/server.rb, line 377 def redirect_download value = opts[:redirect_download] if opts[:download_url] value ||= opts[:download_url] warn "[TUS-RUBY-SERVER DEPRECATION] The :download_url option has been renamed to :redirect_download." end value = storage.method(:file_url) if value == true value end
storage()
click to toggle source
# File lib/tus/server.rb, line 424 def storage opts[:storage] || Tus::Storage::Filesystem.new("data") end
validate_content_length!(size, info)
click to toggle source
# File lib/tus/server.rb, line 266 def validate_content_length!(size, info) if info.length error!(403, "Cannot modify completed upload") if info.offset == info.length error!(413, "Size of this chunk surpasses Upload-Length") if info.offset + size > info.length elsif max_size error!(413, "Size of this chunk surpasses Tus-Max-Size") if info.offset + size > max_size end end
validate_content_type!()
click to toggle source
# File lib/tus/server.rb, line 229 def validate_content_type! error!(415, "Invalid Content-Type header") if request.content_type != RESUMABLE_CONTENT_TYPE end
validate_partial_uploads!(part_uids)
click to toggle source
Validates that each partial upload exists and is marked as one, and at the same time calculates the sum of part lengths.
# File lib/tus/server.rb, line 308 def validate_partial_uploads!(part_uids) length = 0 part_uids.each do |part_uid| begin part_info = storage.read_info(part_uid) rescue Tus::NotFound error!(400, "Partial upload not found") end part_info = Tus::Info.new(part_info) error!(400, "Upload is not partial") unless part_info.partial? unless part_info.length == part_info.offset error!(400, "Partial upload is not finished") end length += part_info.length end if max_size && length > max_size error!(400, "The sum of partial upload lengths exceeds Tus-Max-Size") end length end
validate_tus_resumable!()
click to toggle source
# File lib/tus/server.rb, line 233 def validate_tus_resumable! client_version = request.headers["Tus-Resumable"] unless SUPPORTED_VERSIONS.include?(client_version) response.headers["Tus-Version"] = SUPPORTED_VERSIONS.join(",") error!(412, "Unsupported version") end end
validate_upload_checksum!(input)
click to toggle source
# File lib/tus/server.rb, line 336 def validate_upload_checksum!(input) algorithm, checksum = request.headers["Upload-Checksum"].split(" ") error!(400, "Invalid Upload-Checksum header") if algorithm.nil? || checksum.nil? error!(400, "Invalid Upload-Checksum header") unless SUPPORTED_CHECKSUM_ALGORITHMS.include?(algorithm) generated_checksum = Tus::Checksum.generate(algorithm, input) error!(460, "Upload-Checksum value doesn't match generated checksum") if generated_checksum != checksum end
validate_upload_concat!()
click to toggle source
# File lib/tus/server.rb, line 293 def validate_upload_concat! upload_concat = request.headers["Upload-Concat"] error!(400, "Invalid Upload-Concat header") if upload_concat !~ /^(partial|final)/ if upload_concat.start_with?("final") string = upload_concat.split(";").last string.split(" ").each do |url| error!(400, "Invalid Upload-Concat header") if url !~ /#{request.script_name}\/\w+$/ end end end
validate_upload_finished!(info)
click to toggle source
# File lib/tus/server.rb, line 275 def validate_upload_finished!(info) error!(403, "Cannot download unfinished upload") unless info.length == info.offset end
validate_upload_length!()
click to toggle source
# File lib/tus/server.rb, line 242 def validate_upload_length! upload_length = request.headers["Upload-Length"] error!(400, "Missing Upload-Length header") if upload_length.to_s == "" error!(400, "Invalid Upload-Length header") if upload_length =~ /\D/ error!(400, "Invalid Upload-Length header") if upload_length.to_i < 0 if max_size && upload_length.to_i > max_size error!(413, "Upload-Length header too large") end end
validate_upload_metadata!()
click to toggle source
# File lib/tus/server.rb, line 279 def validate_upload_metadata! upload_metadata = request.headers["Upload-Metadata"] upload_metadata.split(",").each do |string| key, value = string.split(" ", 2) error!(400, "Invalid Upload-Metadata header") if key.nil? error!(400, "Invalid Upload-Metadata header") if key.ord > 127 error!(400, "Invalid Upload-Metadata header") if key =~ /,| / error!(400, "Invalid Upload-Metadata header") if value =~ /[^a-zA-Z0-9+\/=]/ end end
validate_upload_offset!(info)
click to toggle source
# File lib/tus/server.rb, line 254 def validate_upload_offset!(info) upload_offset = request.headers["Upload-Offset"] error!(400, "Missing Upload-Offset header") if upload_offset.to_s == "" error!(400, "Invalid Upload-Offset header") if upload_offset =~ /\D/ error!(400, "Invalid Upload-Offset header") if upload_offset.to_i < 0 if upload_offset.to_i != info.offset error!(409, "Upload-Offset header doesn't match current offset") end end