Unable to get a working presigned image url from railway bucket
sonoalex
PROOP

3 months ago

Hi! I'm struggling with how to get the images that are on a bucket from my web service.

To sum up, I have the following services:
- web - Flask app
- worker: celery worker

- railway s3 bucket.

The current flow is:
user uploads a photo to the web service. The service upload to the bucket. The worker download the image, make some resizing and uploads the new resized versions. (I note the bucket size its being increased)
Then to serve the link images, I presign the url of the images in order to be shown on img tags.

But this link always end up on timeout in both path and virtual hosted style...

boto3.client(
            's3',
            endpoint_url=endpoint_to_use,
            aws_access_key_id=access_key,
            aws_secret_access_key=secret_key,
            region_name=self.region,
            use_ssl=use_ssl_for_client,
            config=Config(
                signature_version='s3v4',
                connect_timeout=30,
                read_timeout=60,
                retries={'max_attempts': 3},
                s3={
                    'addressing_style': 'path'
                }
            )
        )
        

Generates url like this:

https://storage.railway.app/uploads-rh2-af/1765466613.344429_caques_colom2_medium.jpeg?response-content-type=image%2Fjpeg&response-content-disposition=inline&X-Amz-Algorit.......

Whats happening? Is there something i'm missing?
Thank you!

$10 Bounty

1 Replies

jqcktalks
FREE

3 months ago

Instead of serving storage URLs directly to the browser, use Flask to route them. Here's an example:

from flask import Response
import boto3

@app.route("/images/<path:key>")
def serve_image(key):
    s3 = boto3.client(
        "s3",
        endpoint_url="https://storage.railway.app",
        aws_access_key_id=ACCESS_KEY,
        aws_secret_access_key=SECRET_KEY,
        region_name="auto",
    )

    obj = s3.get_object(Bucket=BUCKET, Key=key)

    return Response(
        obj["Body"].read(),
        mimetype=obj["ContentType"],
        headers={
            "Cache-Control": "public, max-age=86400"
        }
    )

Then your frontend can use:

<img src="/images/uploads-rh2-af/1765466613_medium.jpeg">

This should work reliably, without timeouts, should be cacheable and also secure.


Loading...