Use presigned urls when statically pre-rendering
This commit is contained in:
parent
44550824e7
commit
d11cf6f62d
@ -1,5 +1,5 @@
|
|||||||
import { auth } from '@/auth/server';
|
import { auth } from '@/auth/server';
|
||||||
import { getSignedUrl } from '@/platforms/storage';
|
import { getSignedUrlForKey } from '@/platforms/storage';
|
||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
_: Request,
|
_: Request,
|
||||||
@ -10,7 +10,7 @@ export async function GET(
|
|||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|
||||||
if (session?.user && key) {
|
if (session?.user && key) {
|
||||||
const url = await getSignedUrl(key, 'PUT');
|
const url = await getSignedUrlForKey(key, 'PUT');
|
||||||
return new Response(
|
return new Response(
|
||||||
url,
|
url,
|
||||||
{ headers: { 'content-type': 'text/plain' } },
|
{ headers: { 'content-type': 'text/plain' } },
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import {
|
|||||||
doAllPhotosHaveOptimizedFiles,
|
doAllPhotosHaveOptimizedFiles,
|
||||||
getOptimizedPhotoUrl,
|
getOptimizedPhotoUrl,
|
||||||
} from '@/photo/storage';
|
} from '@/photo/storage';
|
||||||
|
import { fetchBase64ImageFromUrl } from '@/utility/image';
|
||||||
|
import { getSignedUrlForUrl } from '@/platforms/storage';
|
||||||
|
|
||||||
export default async function ImagePhotoGrid({
|
export default async function ImagePhotoGrid({
|
||||||
photos,
|
photos,
|
||||||
@ -53,7 +55,23 @@ export default async function ImagePhotoGrid({
|
|||||||
|
|
||||||
const doOptimizedFilesExist = await doAllPhotosHaveOptimizedFiles(photos);
|
const doOptimizedFilesExist = await doAllPhotosHaveOptimizedFiles(photos);
|
||||||
|
|
||||||
const renderPhoto = ({ id, url }: Photo, width: number, height: number) =>
|
const photoDataUrls = await Promise.all(photos.map(async({ id, url }) => {
|
||||||
|
const optimizedUrl = getOptimizedPhotoUrl({
|
||||||
|
imageUrl: url,
|
||||||
|
size: nextImageWidth,
|
||||||
|
addBypassSecret: IS_PREVIEW,
|
||||||
|
compatibilityMode: !doOptimizedFilesExist,
|
||||||
|
});
|
||||||
|
const presignedUrl = await getSignedUrlForUrl(optimizedUrl, 'GET');
|
||||||
|
const data = await fetchBase64ImageFromUrl(presignedUrl);
|
||||||
|
return { id, data };
|
||||||
|
}));
|
||||||
|
|
||||||
|
const renderPhoto = (
|
||||||
|
{ id, data }: typeof photoDataUrls[number],
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
) =>
|
||||||
<div
|
<div
|
||||||
key={id}
|
key={id}
|
||||||
style={{
|
style={{
|
||||||
@ -65,12 +83,7 @@ export default async function ImagePhotoGrid({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img {...{
|
<img {...{
|
||||||
src: getOptimizedPhotoUrl({
|
src: data,
|
||||||
imageUrl: url,
|
|
||||||
size: nextImageWidth,
|
|
||||||
addBypassSecret: IS_PREVIEW,
|
|
||||||
compatibilityMode: !doOptimizedFilesExist,
|
|
||||||
}),
|
|
||||||
style: {
|
style: {
|
||||||
...imageStyle,
|
...imageStyle,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@ -100,7 +113,7 @@ export default async function ImagePhotoGrid({
|
|||||||
width: cellWidth,
|
width: cellWidth,
|
||||||
height: cellHeight * 2,
|
height: cellHeight * 2,
|
||||||
}}>
|
}}>
|
||||||
{renderPhoto(photos[0], cellWidth, cellHeight * 2)}
|
{renderPhoto(photoDataUrls[0], cellWidth, cellHeight * 2)}
|
||||||
</div>
|
</div>
|
||||||
{/* Small images (R) */}
|
{/* Small images (R) */}
|
||||||
<div style={{
|
<div style={{
|
||||||
@ -109,12 +122,12 @@ export default async function ImagePhotoGrid({
|
|||||||
width: cellWidth,
|
width: cellWidth,
|
||||||
height: cellHeight,
|
height: cellHeight,
|
||||||
}}>
|
}}>
|
||||||
{photos.slice(1).map(photo =>
|
{photoDataUrls.slice(1).map(photo =>
|
||||||
renderPhoto(photo, cellWidth, cellHeight),
|
renderPhoto(photo, cellWidth, cellHeight),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
: photos.slice(0, count).map(photo =>
|
: photoDataUrls.slice(0, count).map(photo =>
|
||||||
renderPhoto(photo, cellWidth, cellHeight),
|
renderPhoto(photo, cellWidth, cellHeight),
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export const awsS3Delete = async (Key: string) => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const awsS3GetSignedUrl = async (
|
export const awsS3GetSignedUrl = (
|
||||||
Key: string,
|
Key: string,
|
||||||
method: 'GET' | 'PUT',
|
method: 'GET' | 'PUT',
|
||||||
expiresIn: number,
|
expiresIn: number,
|
||||||
|
|||||||
@ -104,7 +104,7 @@ export const cloudflareR2Delete = async (Key: string) => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cloudflareR2GetSignedUrl = async (
|
export const cloudflareR2GetSignedUrl = (
|
||||||
Key: string,
|
Key: string,
|
||||||
method: 'GET' | 'PUT',
|
method: 'GET' | 'PUT',
|
||||||
expiresIn: number,
|
expiresIn: number,
|
||||||
|
|||||||
@ -251,7 +251,8 @@ export const getStorageUrlsForPrefix = async (prefix = '') => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSignedUrl = async (
|
// Used primarily for uploading files
|
||||||
|
export const getSignedUrlForKey = async (
|
||||||
key: string,
|
key: string,
|
||||||
method: 'GET' | 'PUT',
|
method: 'GET' | 'PUT',
|
||||||
expiresIn = 3600,
|
expiresIn = 3600,
|
||||||
@ -266,5 +267,24 @@ export const getSignedUrl = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Used for safely fetching files via presigned URLs
|
||||||
|
export const getSignedUrlForUrl = (
|
||||||
|
url: string,
|
||||||
|
method: 'GET' | 'PUT',
|
||||||
|
expiresIn = 3600,
|
||||||
|
) => {
|
||||||
|
const { fileName } = getFileNamePartsFromStorageUrl(url);
|
||||||
|
switch (storageTypeFromUrl(url)) {
|
||||||
|
case 'cloudflare-r2':
|
||||||
|
return cloudflareR2GetSignedUrl(fileName, method, expiresIn);
|
||||||
|
case 'minio':
|
||||||
|
return minioGetSignedUrl(fileName, method, expiresIn);
|
||||||
|
case 'aws-s3':
|
||||||
|
return awsS3GetSignedUrl(fileName, method, expiresIn);
|
||||||
|
default:
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const testStorageConnection = () =>
|
export const testStorageConnection = () =>
|
||||||
getStorageUrlsForPrefix();
|
getStorageUrlsForPrefix();
|
||||||
|
|||||||
@ -93,7 +93,7 @@ export const minioDelete = async (Key: string): Promise<void> => {
|
|||||||
await minioClient().send(deleteObjectCommand);
|
await minioClient().send(deleteObjectCommand);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const minioGetSignedUrl = async (
|
export const minioGetSignedUrl = (
|
||||||
Key: string,
|
Key: string,
|
||||||
method: 'GET' | 'PUT',
|
method: 'GET' | 'PUT',
|
||||||
expiresIn: number,
|
expiresIn: number,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user