Class: ActiveStorage::Service::GCSService
- Inherits:
-
ActiveStorage::Service
- Object
- ActiveStorage::Service
- ActiveStorage::Service::GCSService
- Defined in:
- lib/active_storage/service/gcs_service.rb
Overview
Active Storage GCS Service
Wraps the Google Cloud Storage as an Active Storage service. See ActiveStorage::Service for the generic API documentation that applies to all services.
Defined Under Namespace
Classes: MetadataServerError, MetadataServerNotFoundError
Instance Attribute Summary
Attributes inherited from ActiveStorage::Service
Instance Method Summary collapse
- #compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) ⇒ Object
- #delete(key) ⇒ Object
- #delete_prefixed(prefix) ⇒ Object
- #download(key, &block) ⇒ Object
- #download_chunk(key, range) ⇒ Object
- #exist?(key) ⇒ Boolean
- #headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, custom_metadata: {}) ⇒ Object
-
#initialize(public: false, **config) ⇒ GCSService
constructor
A new instance of GCSService.
- #update_metadata(key, content_type:, disposition: nil, filename: nil, custom_metadata: {}) ⇒ Object
- #upload(key, io, checksum: nil, content_type: nil, disposition: nil, filename: nil, custom_metadata: {}) ⇒ Object
- #url_for_direct_upload(key, expires_in:, checksum:, custom_metadata: {}) ⇒ Object
Methods inherited from ActiveStorage::Service
build, configure, #open, #public?, #url
Constructor Details
#initialize(public: false, **config) ⇒ GCSService
16 17 18 19 |
# File 'lib/active_storage/service/gcs_service.rb', line 16 def initialize(public: false, **config) @config = config @public = public end |
Instance Method Details
#compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) ⇒ Object
139 140 141 142 143 144 145 |
# File 'lib/active_storage/service/gcs_service.rb', line 139 def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) bucket.compose(source_keys, destination_key).update do |file| file.content_type = content_type file.content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename file. = end end |
#delete(key) ⇒ Object
66 67 68 69 70 71 72 |
# File 'lib/active_storage/service/gcs_service.rb', line 66 def delete(key) instrument :delete, key: key do file_for(key).delete rescue Google::Cloud::NotFoundError # Ignore files already deleted end end |
#delete_prefixed(prefix) ⇒ Object
74 75 76 77 78 79 80 81 82 |
# File 'lib/active_storage/service/gcs_service.rb', line 74 def delete_prefixed(prefix) instrument :delete_prefixed, prefix: prefix do bucket.files(prefix: prefix).all do |file| file.delete rescue Google::Cloud::NotFoundError # Ignore concurrently-deleted files end end end |
#download(key, &block) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/active_storage/service/gcs_service.rb', line 34 def download(key, &block) if block_given? instrument :streaming_download, key: key do stream(key, &block) end else instrument :download, key: key do file_for(key).download.string rescue Google::Cloud::NotFoundError raise ActiveStorage::FileNotFoundError end end end |
#download_chunk(key, range) ⇒ Object
58 59 60 61 62 63 64 |
# File 'lib/active_storage/service/gcs_service.rb', line 58 def download_chunk(key, range) instrument :download_chunk, key: key, range: range do file_for(key).download(range: range).string rescue Google::Cloud::NotFoundError raise ActiveStorage::FileNotFoundError end end |
#exist?(key) ⇒ Boolean
84 85 86 87 88 89 90 |
# File 'lib/active_storage/service/gcs_service.rb', line 84 def exist?(key) instrument :exist, key: key do |payload| answer = file_for(key).exists? payload[:exist] = answer answer end end |
#headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, custom_metadata: {}) ⇒ Object
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/active_storage/service/gcs_service.rb', line 128 def headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, custom_metadata: {}, **) content_disposition = content_disposition_with(type: disposition, filename: filename) if filename headers = { "Content-MD5" => checksum, "Content-Disposition" => content_disposition, **() } if @config[:cache_control].present? headers["Cache-Control"] = @config[:cache_control] end headers end |
#update_metadata(key, content_type:, disposition: nil, filename: nil, custom_metadata: {}) ⇒ Object
48 49 50 51 52 53 54 55 56 |
# File 'lib/active_storage/service/gcs_service.rb', line 48 def (key, content_type:, disposition: nil, filename: nil, custom_metadata: {}) instrument :update_metadata, key: key, content_type: content_type, disposition: disposition do file_for(key).update do |file| file.content_type = content_type file.content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename file. = end end end |
#upload(key, io, checksum: nil, content_type: nil, disposition: nil, filename: nil, custom_metadata: {}) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/active_storage/service/gcs_service.rb', line 21 def upload(key, io, checksum: nil, content_type: nil, disposition: nil, filename: nil, custom_metadata: {}) instrument :upload, key: key, checksum: checksum do # GCS's signed URLs don't include params such as response-content-type response-content_disposition # in the signature, which means an attacker can modify them and bypass our effort to force these to # binary and attachment when the file's content type requires it. The only way to force them is to # store them as object's metadata. content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename bucket.create_file(io, key, md5: checksum, cache_control: @config[:cache_control], content_type: content_type, content_disposition: content_disposition, metadata: ) rescue Google::Cloud::InvalidArgumentError raise ActiveStorage::IntegrityError end end |
#url_for_direct_upload(key, expires_in:, checksum:, custom_metadata: {}) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/active_storage/service/gcs_service.rb', line 92 def url_for_direct_upload(key, expires_in:, checksum:, custom_metadata: {}, **) instrument :url, key: key do |payload| headers = {} version = :v2 if @config[:cache_control].present? headers["Cache-Control"] = @config[:cache_control] # v2 signing doesn't support non `x-goog-` headers. Only switch to v4 signing # if necessary for back-compat; v4 limits the expiration of the URL to 7 days # whereas v2 has no limit version = :v4 end headers.merge!(()) args = { content_md5: checksum, expires: expires_in, headers: headers, method: "PUT", version: version, } if @config[:iam] args[:issuer] = issuer args[:signer] = signer end generated_url = bucket.signed_url(key, **args) payload[:url] = generated_url generated_url end end |