Admin panel breaking presigned S3 URLs due to adding query parameters #10494
Replies: 3 comments 1 reply
-
A sub-discussion to add to this; modifying the images without changing the url causes them to be in browser cache when used in places without this trick, right? So if one builds a front-end using the Payload API, they manually need to make sure the edited image is fetched, and not the one from browser cache. |
Beta Was this translation helpful? Give feedback.
-
You're correct! If you serve images with a static URL and modify the images without updating the URL (or appending a cache-busting query string), browsers will often serve the cached version of the image. This is because browsers rely on the URL to determine whether they should re-fetch a resource. This issue becomes relevant when you're:
Why This Happens
When using presigned URLs, appending a cache-busting query string like Mitigation StrategiesHere’s how you can ensure the correct (updated) images are fetched: 1. Use Cache-Busting Query Strings IntelligentlyFor non-presigned URLs, append a cache-busting query string whenever the image changes. A common practice is to use a versioning system: const generateImageUrl = (doc, version = null) => {
if (!doc.filename) {
return null;
}
if (doc.url) {
return `${doc.url}${version ? `?v=${version}` : ''}`;
}
};
For example: generateImageUrl(imageDoc, imageDoc.version); 2. Control Caching with HTTP HeadersIf query strings are not an option (e.g., with presigned URLs), configure caching policies at the server level. AWS S3 allows you to control cache behavior via headers such as:
Set these headers when uploading images to S3: const params = {
Bucket: bucketName,
Key: objectKey,
Body: imageBuffer,
ContentType: 'image/jpeg',
CacheControl: 'no-cache', // or 'max-age=3600'
};
s3.upload(params, (err, data) => { /* handle response */ }); 3. Generate Unique URLs for Modified ImagesWhen an image is updated, give it a new URL by changing the filename or key. This ensures the browser fetches the updated image. For example:
You can automate this by appending a timestamp or version number to the filename during updates. 4. Use a Proxy for Image ManagementIf you’re using Payload’s API to serve images, implement a backend proxy that:
Example:
5. Manage Client-Side Caching for Specific ScenariosOn the client side, you can programmatically bypass the browser cache if needed: const loadUpdatedImage = (url) => {
const cacheBustingQuery = `?_=${new Date().getTime()}`;
return `${url}${url.includes('?') ? '&' : '?'}${cacheBustingQuery}`;
}; Use this approach only if you need to bypass caching for certain cases (e.g., during updates or previews). Best Approach for Your Use CaseIf you are using a Payload API front-end:
|
Beta Was this translation helpful? Give feedback.
-
Woah! I just didn't pay enough attention - this was currently being solved coincidentally. #10319 should resolve this, disabling the cache tags allows for signed urls to work. |
Beta Was this translation helpful? Give feedback.
-
When using presigned S3 URLs for secure image access, the admin panel automatically appends a date query string to image requests (e.g.,
?2025-01-10
). This breaks the presigned URLs since they are cryptographically signed for the exact URL, and any modification invalidates the signature. See the following excerpt from the codebase (ui package,src/elements/PreviewSizes/index.tsx
):Setup
Expected behavior
Admin panel should display images using the exact presigned URLs, image requests should succeed with the valid signatures
Actual Behavior
?[date]
to image URLsI've only come up with submitting a PR to remove the image caching situation; though this would cause issues for those serving images with a constant url. So we probably want a way to circumvent this selectively, as to not re-introduce caching issues.
Any insights or suggestions would be greatly appreciated!
Beta Was this translation helpful? Give feedback.
All reactions