Chuyện là mình có tham gia event "Là IT thì mình cứ viết đi" của bên ITviec tổ chức, nội dung chính là mình sẽ viết 1 câu chuyện theo chủ đề đã đưa ra (mọi người có thể vào xem và cho mình xin 1 vote nếu thấy hay nhé link ở đây!). Sau đó vô tình mình có thấy cái tình trạng này, đó là hình ảnh mà mình chèn vào chỉ hiển thị ở lần đầu tiên
còn sau đó tầm hơn 5 phút, khi vào lại page thì nó sẽ bị lỗi không hiển thị được.
Vậy chúng ta hãy cùng mổ xẻ thử vì sao lại có con bug này để phòng tránh nhé
1. Kiểm tra tình trạng
Đầu tiên, chúng ta cùng xem thử tình trạng hiển thị ở chỗ này là như thế nào nhé. Khi kiểm tra đường dẫn hình ảnh, mình thấy rằng nó đang được quản lý bởi active_storage và lưu trữ lên AWS S3
Khi load page, nó sẽ gọi đến URL của active_storage (hình 1) và chuyển hướng đến URL của thư mục trên S3 (hình 2). Từ những lần sau, khi chúng ta truy cập lại vào page này, thì hình ảnh lấy từ S3 đã được lưu trữ trên bộ nhớ cache của browser (hình 3)
- Hình 1
- Hình 2
- Hình 3
2. Tái hiện bug và tìm hiểu lí do
Sau khoảng tầm hơn 5 phút, mình vào lại page này, thì lúc này những bức hình sẽ bị lỗi không hiển thị được, kiểm tra đường dẫn hình ảnh chúng ta sẽ thấy nó báo URL đã hết hạn.
Tiếp theo mình sẽ clear cache + reload page, hình ảnh sẽ được hiển thị lại như cũ. Vậy chúng ta có thể phán đoán rằng, bởi vì browser đã cache hình ảnh có đường dẫn S3 bị hết hạn. Vậy tại sao đường dẫn S3 lại bị hết hạn nhanh như vậy ? 🤐
Presigned URL
Theo như mình tìm hiểu, thì đó là cơ chế Presigned URL của AWS S3. Hiểu nôm na thì tài nguyên của 1 Bucket S3 có status là Private, nếu bên ngoài muốn tương tác thì phải thông qua 1 URL tạm thời, và URL này sẽ có các thông số về Signature, Date, Expires. Trong trường hợp hình ảnh trên page ITviec mình kiểm tra thì nó đang có expires là 300s, tức 5 phút, vậy nên nếu qua 5 phút kể từ khi cái URL này được sinh ra, thì chúng ta không thể xem được cái hình này nữa.
Trong trường hợp trang blog của ITviec nêu trên, hình ảnh này đang được quản lý bởi active_Storage, bản thân nó sẽ có 1 URL từ active_storage là cố định, sau đó mỗi lần mình gọi đến URL này, nó sẽ trỏ lên S3, sinh ra 1 URL s3 tạm thời, có expire là 5 phút để hiển thị lên. Tuy nhiên chúng ta sẽ bị vấn đề bỏi vì browser đang thực hiện cache lại tấm hình từ S3 đó (chứ không thực hiện gọi lại URL từ active_storage), dẫn đến hành động sinh ra URL S3 mới không được thực hiện. Và thế là hình ảnh không hiển thị được.
Sau đó mình thử disabled cache của browser, thì hình ảnh luôn được hiển thị bình thường, vì lúc này chúng ta luôn thực hiện việc gọi đến active_storage URL
Kết luận
Trước đây mình đã từng gặp phải 1 issue tương tự về expire hình S3, lần này thấy vấn đề này mình thấy khá thú vị nên muốn chia sẻ lại với mọi người để chúng ta cùng thảo luận. Còn về giải pháp thì chúng ta có thể kéo dài thời hạn expires, hoặc ngăn chặn việc browser cache page. Cảm ơn các bạn đã đọc !!!
Tài liệu tham khảo
https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-presigned-url.html
https://viblo.asia/p/securing-aws-s3-uploads-using-presigned-urls-924lJmNmZPM
https://edgeguides.rubyonrails.org/active_storage_overview.html