diff --git a/keyserver/src/services/blob.js b/keyserver/src/services/blob.js --- a/keyserver/src/services/blob.js +++ b/keyserver/src/services/blob.js @@ -3,8 +3,8 @@ import blobService from 'lib/facts/blob-service.js'; import type { BlobHashAndHolder } from 'lib/types/holder-types.js'; import { - getBlobFetchableURL, makeBlobServiceEndpointURL, + downloadBlob, } from 'lib/utils/blob-service.js'; import { uploadBlob, @@ -112,17 +112,13 @@ +blob: Blob, }; async function download(hash: string): Promise { - const url = getBlobFetchableURL(hash); const headers = await createRequestHeaders(); - const response = await fetch(url, { - method: blobService.httpEndpoints.GET_BLOB.method, - headers, - }); + const blobResult = await downloadBlob(hash, headers); - if (!response.ok) { - return { found: false, status: response.status }; + if (blobResult.result !== 'success') { + return { found: false, status: blobResult.status }; } - const blob = await response.blob(); + const blob = await blobResult.response.blob(); return { found: true, blob }; } diff --git a/lib/components/base-auto-join-community-handler.react.js b/lib/components/base-auto-join-community-handler.react.js --- a/lib/components/base-auto-join-community-handler.react.js +++ b/lib/components/base-auto-join-community-handler.react.js @@ -5,7 +5,6 @@ import * as React from 'react'; import { NeynarClientContext } from '../components/neynar-client-provider.react.js'; -import blobService from '../facts/blob-service.js'; import { useIsLoggedInToIdentityAndAuthoritativeKeyserver } from '../hooks/account-hooks.js'; import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js'; import { @@ -22,7 +21,7 @@ import type { CalendarQuery } from '../types/entry-types.js'; import type { SetState } from '../types/hook-types.js'; import { defaultThreadSubscription } from '../types/subscription-types.js'; -import { getBlobFetchableURL } from '../utils/blob-service.js'; +import { downloadBlob } from '../utils/blob-service.js'; import { useCurrentUserFID } from '../utils/farcaster-utils.js'; import { promiseAll } from '../utils/promises.js'; import { useSelector } from '../utils/redux-utils.js'; @@ -122,18 +121,13 @@ for (const channelID of followedFarcasterChannelIDs) { promises[channelID] = (async () => { const blobHash = farcasterChannelTagBlobHash(channelID); - const blobURL = getBlobFetchableURL(blobHash); - - const blobResult = await fetch(blobURL, { - method: blobService.httpEndpoints.GET_BLOB.method, - headers, - }); - - if (blobResult.status !== 200) { + const blobResult = await downloadBlob(blobHash, headers); + if (blobResult.result !== 'success') { return null; } - const { commCommunityID, keyserverURL } = await blobResult.json(); + const { commCommunityID, keyserverURL } = + await blobResult.response.json(); const keyserverID = extractKeyserverIDFromID(commCommunityID); // The user is already in the community diff --git a/lib/shared/invite-links.js b/lib/shared/invite-links.js --- a/lib/shared/invite-links.js +++ b/lib/shared/invite-links.js @@ -1,8 +1,7 @@ // @flow import type { AuthMetadata } from './identity-client-context.js'; -import blobService from '../facts/blob-service.js'; -import { getBlobFetchableURL } from '../utils/blob-service.js'; +import { downloadBlob } from '../utils/blob-service.js'; import { createDefaultHTTPRequestHeaders } from '../utils/services-utils.js'; function inviteLinkBlobHash(secret: string): string { @@ -18,18 +17,16 @@ secret: string, authMetadata?: AuthMetadata, ): Promise { - const blobURL = getBlobFetchableURL(inviteLinkBlobHash(secret)); const headers = authMetadata ? createDefaultHTTPRequestHeaders(authMetadata) : {}; - const result = await fetch(blobURL, { - method: blobService.httpEndpoints.GET_BLOB.method, - headers, - }); - if (result.status !== 200) { + + const blobResult = await downloadBlob(inviteLinkBlobHash(secret), headers); + if (blobResult.result !== 'success') { return null; } - const resultText = await result.text(); + + const resultText = await blobResult.response.text(); const resultObject = JSON.parse(resultText); if (resultObject.keyserverID && resultObject.keyserverURL) { const keyserverURL: string = resultObject.keyserverURL; diff --git a/lib/utils/blob-service.js b/lib/utils/blob-service.js --- a/lib/utils/blob-service.js +++ b/lib/utils/blob-service.js @@ -83,6 +83,29 @@ +statusText: string, }; +export type BlobDownloadResult = + | { +result: 'success', response: Response } + | { +result: 'error', +status: number, +statusText: string }; + +async function downloadBlob( + blobHash: string, + headers: { [string]: string }, +): Promise { + const blobURL = getBlobFetchableURL(blobHash); + + const response = await fetch(blobURL, { + method: blobServiceConfig.httpEndpoints.GET_BLOB.method, + headers, + }); + + if (response.status !== 200) { + const { status, statusText } = response; + return { result: 'error', status, statusText }; + } + + return { result: 'success', response }; +} + async function uploadBlob( blob: Blob | string, hash: string, @@ -218,6 +241,7 @@ generateBlobHolder, getBlobFetchableURL, makeBlobServiceEndpointURL, + downloadBlob, uploadBlob, assignMultipleHolders, removeMultipleHolders,