Search code examples
ruby-on-railsgoogle-app-enginegoogle-cloud-platformgoogle-cloud-storageactionmailer

Google Cloud Storage setting an expiry date on requested assets despite explicitly setting infinite TTL


I have a Rails 5.2.3 app that's running on Google Cloud services, and I have some images that are user uploaded, such as staff images. These images are uploaded onto a GC Storage bucket set to be publicly accessible.

My current issue is that I'm trying to display these images inside of an email we send. In the email view, the image is being called as below. Note that employees are guaranteed to have an image present, we force users to upload employee photos, so there is no risk of one of these photos not existing.

<%= image_tag (employee.photo.service_url) if employee.photo.attached? %>

Now, the images actually show up fine in the emails... for 5 minutes, after which the images cease to be accessible, and visiting the image via the link present in the email takes us to a 404 with the file no longer existing. After taking a closer look at the image URL, I noticed a parameter, Expires= followed by a UNIX timestamp that translates to exactly 5 minutes after the email getting sent. I scoured every inch of our Google Cloud settings, and literally nowhere do I see anything about TTL or expiries or anything.

Here's an image of the url, as it's very long. I've redacted some project IDs and stuff like that, those aren't relevant

enter image description here

I think the issue is that I'm not accessing the public URL of the image in the bucket which would be permanent, as they say in the docs that you have to call the images with the BUCKET_NAME/FILE_NAME URL, but I can't use this because the images have randomized filenames once they're uploaded, and it's also not a very dynamic approach as we send these emails to every client, and every client has their own unique employees and employee images.

Here's a screenshot of the Storage bucket. As you can see, everything is Public, and manualy checking the images, I indeed see some of the staff images I've seen during testing.

enter image description here

Anything to point me in the right direction would be greatly appreciated.

My storage.yml file

google:
  service: GCS
  project: REDACTED
  credentials: <%= Rails.application.credentials.gcs_storage_credentials.to_json %>
  bucket: images-REDACTED

My production.rb environment file

config.active_storage.service = :google
config.action_mailer.asset_host = Rails.application.credentials.send(production_server_url)

My Gemfile

ruby '2.6.3'
gem 'rails', '~> 5.2.3'
gem 'pg', '>= 0.18', '< 2.0'
gem 'active_storage_base64'
gem 'google-cloud-storage', '~> 1.8', require: false

Solution

  • Looking at the url you attached, looks like you used a signed URL.

    If my guess is correct, You can specify expires on your parameter.

    Refer here to get detailed info about how to specify expire parameter.

    It describes sample python code but you can adapt it your owns.

    Below is some part of sample codes, I think this is what you want.

    if query_parameters is None:
        query_parameters = dict()
    query_parameters['X-Goog-Algorithm'] = 'GOOG4-RSA-SHA256'
    query_parameters['X-Goog-Credential'] = credential
    query_parameters['X-Goog-Date'] = request_timestamp
    query_parameters['X-Goog-Expires'] = expiration
    query_parameters['X-Goog-SignedHeaders'] = signed_headers
    if subresource:
        query_parameters[subresource] = ''