Skip to content

Commit

Permalink
Add way to opt in to uploading assets with signed URLs
Browse files Browse the repository at this point in the history
This will allow folks to opt in to using signed URLs by setting the
HAPPO_SIGNED_URL env var.

This requires a separate change to land on the server side before it can
be used.
  • Loading branch information
lencioni committed Feb 14, 2025
1 parent 10eed79 commit c73ae85
Showing 1 changed file with 83 additions and 1 deletion.
84 changes: 83 additions & 1 deletion src/uploadAssets.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { logTag } from './Logger';
import makeRequest from './makeRequest';

export default async function uploadAssets(
/**
* Uploads assets via Happo's API
*
* @param {Buffer|Stream} streamOrBuffer
* @param {Object} options
* @param {string} options.hash
* @param {string} options.endpoint
* @param {string} options.apiKey
* @param {string} options.apiSecret
* @param {Logger} options.logger
* @param {string} options.project
* @returns {Promise<string>} The URL of the uploaded assets
*/
async function uploadAssetsThroughHappo(
streamOrBuffer,
{ hash, endpoint, apiKey, apiSecret, logger, project },
) {
Expand Down Expand Up @@ -52,3 +65,72 @@ export default async function uploadAssets(
);
return assetsRes.path;
}

/**
* Uploads assets via signed URL
*
* @param {Buffer|Stream} streamOrBuffer
* @param {Object} options
* @param {string} options.hash
* @param {string} options.endpoint
* @param {string} options.apiKey
* @param {string} options.apiSecret
* @param {Logger} options.logger
* @param {string} options.project
* @returns {Promise<string>} The URL of the uploaded assets
*/
async function uploadAssetsWithSignedUrl(
streamOrBuffer,
{ hash, endpoint, apiKey, apiSecret, logger, project },
) {
// First we need to get the signed URL from Happo.
const signedUrlRes = await makeRequest(
{
url: `${endpoint}/api/snap-requests/assets/${hash}/signed-url`,
method: 'GET',
json: true,
},
{ apiKey, apiSecret, retryCount: 3 },
);

// If the asset has already been uploaded, we can return the path now.
if (signedUrlRes.path) {
logger.info(`${logTag(project)}Reusing existing assets at ${signedUrlRes.path}`);
return signedUrlRes.path;
}

// Upload the assets to the signed URL using node's built-in fetch.
const putRes = await fetch(signedUrlRes.signedUrl, {
method: 'PUT',
body: streamOrBuffer,
headers: {
'Content-Type': 'application/zip',
},
});

if (!putRes.ok) {
throw new Error(
`Failed to upload assets to S3 signed URL: ${putRes.status} ${putRes.statusText}`,
);
}

// Finally, we need to tell Happo that we've uploaded the assets.
const finalizeRes = await makeRequest(
{
url: `${endpoint}/api/snap-requests/assets/${hash}/finalize`,
method: 'POST',
json: true,
},
{ apiKey, apiSecret, retryCount: 3 },
);

return finalizeRes.path;
}

export default async function uploadAssets(streamOrBuffer, options) {
if (process.env.HAPPO_SIGNED_URL) {
return uploadAssetsWithSignedUrl(streamOrBuffer, options);
}

return uploadAssetsThroughHappo(streamOrBuffer, options);
}

0 comments on commit c73ae85

Please sign in to comment.