Google Storage Image Serving Cache - google-app-engine

Using the GoogleStorageTools class's CloudStorageTools::getImageServingUrl and then replacing the storage object of the image with another image of the same name, the old image is still displayed upon subsequent calls of getImageServingUrl
I tried using CloudStorageTools::deleteImageServingUrl and then CloudStorageTools::getImageServingUrl again, but this doesn't work.
Is there any way to interact with Cloud Storage and tell it to refresh the image or the image URL? I'm guessing not, and am going to ensure the filenames are unique, instead, but it feels like there ought to be a way.

If you refresh the image, does the new image show up? It's possible there's a cache-control policy set on the image. Google Cloud Storage allows users to specify what cache-control headers should be sent to browsers, but I'm not sure whether app engine's getImageServingUrl respects that value.
As an experiment, could you try going to console.developers.google.com, heading over to "storage > cloud storage > storage browser", choosing the appropriate object, choosing "edit metadata," and then seeing whether there's a Cache-Control policy on the object? Try changing the cache-control section to "max-age=0,no-cache".

Related

Set headers on file upload to Google Cloud Storage

According to the documentation, one should be able to set objects headers on upload to GoogleCloudStorage.
Implementation Details
You should specify cache-control only for objects that are accessible
to all anonymous users. To be anonymously accessible, an object's ACL
must grant READ or FULL_CONTROL permission to AllUsers. If an object
is accessible to all anonymous users and you do not specify a
cache-control setting, Cloud Storage applies a cache-control setting
of 3600 seconds. When serving via XML, Cloud Storage respects the
cache-control of the object as set by its metadata.
However, adding headers through the Google API doesn't seem to work, when fetching the image back with google.appengine.api.images.get_serving_url .
Changing Cache-Control headers from gsutil console has its effects, but takes several days for changes to be visible on the object (when checking from the gsutil console, again, no effect when fetching the image back with the API.
After 2 months of going back and forth with Google's support, we found out that file is sent to the Google Cloud Storage with the proper headers (can be checked via gsutil command).
However get_serving_url function does not respect Blob's headers (confirmed by Google's engineers).
As of 17th of August 2017, there are no future plans to fix that.
Thought someone may encounter the similar problem as there's nothing about it in the documentation.

Google Cloud Storage public link does not become invalid when unchecking

I am using Google Cloud Storage to upload images. I am now testing it from the cloud console.
After I upload a picture if I check the Share publicly checkbox to obtain a public link, I get (obviously) a publicly accessible url, which is: https://storage.googleapis.com/bucket_name/pictureName .
Then, if I uncheck the Share Publicly checkbox, it makes a request
Request URL:https://clients6.google.com/storage/v1_internal/b/bucketName/o/pictureName.jpg/acl/allUsers?key=AIzaSyCI-yuie5UVOi0DjtiCwWBwQ1djkiuo1g
Request Method:DELETE
The request goes well, but the public url remains publicly accessible. I thought it is valid for some time, but after one hour is still available.
So, what is the right way to remove the public url? How do I restrict access to a stored file after I made it public?
See the documentation on cache control and consistency. In particular:
Note: If you do not specify a cache lifetime, a publicly accessible
object can be cached for up to 60 minutes.
So I'm guessing this is working as intended and your object is cached. Have you tried waiting a little longer?
In Sharing your data publicly, it's shown that there are 2 ways to stop sharing an object publicly.
Deselect the checkbox under Shared Publicly as you've mentioned already.
Edit the object permissions and remove the entry with ID allUsers.
The reason you are still able to access the object publicly is indeed because of caching as mentioned by #jterrace. The Cache control and consistency article referenced explains the effect of this eventual consistency.
One can test this behavior by sharing an object publicly and unsharing immediately after. In most cases, the object will be publicly accessible for the cache duration. One can shorten this duration by specifying the Cache-Control headers such as max-age.
When Your sharing Publicly Url is like https://storage.googleapis.com/bucket_name/pictureName.
If you delete the file or uncheck the Share Publicly checkbox
It is available up to 60 minutes it is default cache time in Google cloud,
To avoid the Issue Need to pass Query parameter like
https://storage.googleapis.com/bucket_name/pictureName?avoidCache=1
Every time passes random number in a query string.

Google Cloud Storage Force Download

I am storing my files in Google Cloud Storage. I would like to provide downloadable links. For example https://yeketakclub.storage.googleapis.com/audios/yeketak.club-dm7aEYv7R53JRlti3HHn.mp3 one of audio files stored in google cloud storage. But when it is clicked browser tries to open it. Is it possible to force download?
The correct answer is neither of these! (if you don't want to edit a file's metadata) Add this on the end of any signed url:
&response-content-disposition=attachment;
This will make all storage links force a download instead of opening.
You can signal browsers to download the object while still retaining an accurate content type by setting the content disposition to attachment. For, example using gsutil you can do this like so:
gsutil setmeta -h 'Content-Disposition:attachment' gs://yeketakclub/audios/yeketak.club-dm7aEYv7R53JRlti3HHn.mp3
Now your object can still have the correct content type of "audio/mpeg3" (or whatever happens to match the object's content).
I'm not sure if this is necessarily a Google Cloud Storage issue (I might be wrong). The link provided there is downloadable. It just happens to be that your browser "prefers" to play it most probably because it recognises the MIME Type as one that can be handled.
In Chrome for instance, you can force download of the file by using alt + click.
Or you can right click and save link as...
In the Google Console bucket area you can click the menu and edit metadata on the object and set the Content-Disposition to attachment
edit metadata -> set Content-Disposition = attachment
image

ndb.BlobProperty vs BlobStore: which is more private and more secure

I have been reading all over stackoverflow concerning datastore vs blobstore for storing and retrieving image files. Everything is pointing towards blobstore except one: privacy and security.
In the datastore, the photos of my users are private: I have full control on who gets a blob. In the blobstore, however, anyone who knows the url can conceivable access my users photos? Is that true?
Here is a quote that is supposed to give me peace of mind, but it's still not clear. So anyone with the blob key can still access the photos? (from Store Photos in Blobstore or as Blobs in Datastore - Which is better/more efficient /cheaper?)
the way you serve a value out of the Blobstore is to accept a request
to the app, then respond with the X-AppEngine-BlobKey header with the
key. App Engine intercepts the outgoing response and replaces the body
with the Blobstore value streamed directly from the service. Because
app logic sets the header in the first place, the app can implement
any access control it wants. There is no default URL that serves
values directly out of the Blobstore without app intervention.
All of this is to ask: Which is more private and more secure for trafficking images, and why: datastore or blobstore? Or, hey, google-cloud-storage (which I know nothing about presently)
If you use google.appengine.api.images.get_serving_url then yes, the url returned is public. However the url returned is not guessable from a blob's key, nor does the url even exist before calling get_serving_url. (Or after calling delete_serving_url).
If you need access control on top of the data in the blobstore you can write your own handlers and add the access control there.
BlobProperty is just as private and secure as BlobStore, all depends on your application which serves the requests. your application can implement any permission checking before sending the contents to the user, so I don't see any difference as long as you serve all the images yourself and don't intentionally create publicly available URLs.
Actually, I would not even thinlk about storing photos in the BlobProperty, because this way the data ends up in the database instead of the BlobStore and it costs significantly more to store data in the database. BlobStore, on the other hand, is cheap and convenient.

How long to blob urls served by the app engine remain valid?

I was wondering if anyone knew how long image urls served back from the google app engine blob store remain valid for?
I have been tracking on url that i served an image from the blob store on 1/3/13 and its still there.
I am ask specifically so i can cache the image url instead of attempting to serve it repeatedly. If i did this i would still check if the image is there, but how often would i need to check that
thanks!
They remain valid until either you
a. call delete_serving_url, or
b. delete the underling blob.

Resources