diff options
Diffstat (limited to 'activestorage/app/controllers/active_storage/disk_controller.rb')
-rw-r--r-- | activestorage/app/controllers/active_storage/disk_controller.rb | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/activestorage/app/controllers/active_storage/disk_controller.rb b/activestorage/app/controllers/active_storage/disk_controller.rb new file mode 100644 index 0000000000..7bd641ab9a --- /dev/null +++ b/activestorage/app/controllers/active_storage/disk_controller.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +# Serves files stored with the disk service in the same way that the cloud services do. +# This means using expiring, signed URLs that are meant for immediate access, not permanent linking. +# Always go through the BlobsController, or your own authenticated controller, rather than directly +# to the service url. +class ActiveStorage::DiskController < ActiveStorage::BaseController + skip_forgery_protection + + def show + if key = decode_verified_key + serve_file disk_service.path_for(key), content_type: params[:content_type], disposition: params[:disposition] + else + head :not_found + end + rescue Errno::ENOENT + head :not_found + end + + def update + if token = decode_verified_token + if acceptable_content?(token) + disk_service.upload token[:key], request.body, checksum: token[:checksum] + else + head :unprocessable_entity + end + else + head :not_found + end + rescue ActiveStorage::IntegrityError + head :unprocessable_entity + end + + private + def disk_service + ActiveStorage::Blob.service + end + + + def decode_verified_key + ActiveStorage.verifier.verified(params[:encoded_key], purpose: :blob_key) + end + + def serve_file(path, content_type:, disposition:) + Rack::File.new(nil).serving(request, path).tap do |(status, headers, body)| + self.status = status + self.response_body = body + + headers.each do |name, value| + response.headers[name] = value + end + + response.headers["Content-Type"] = content_type || DEFAULT_SEND_FILE_TYPE + response.headers["Content-Disposition"] = disposition || DEFAULT_SEND_FILE_DISPOSITION + end + end + + + def decode_verified_token + ActiveStorage.verifier.verified(params[:encoded_token], purpose: :blob_token) + end + + def acceptable_content?(token) + token[:content_type] == request.content_type && token[:content_length] == request.content_length + end +end |