MCPcopy
hub / github.com/simstudioai/sim / downloadFileFromUrl

Function downloadFileFromUrl

apps/sim/lib/uploads/utils/file-utils.server.ts:175–224  ·  view source on GitHub ↗
(
  fileUrl: string,
  options: DownloadFileFromUrlOptions = {}
)

Source from the content-addressed store, hash-verified

173 * For external URLs, validates DNS/SSRF and uses secure fetch with IP pinning.
174 */
175export async function downloadFileFromUrl(
176 fileUrl: string,
177 options: DownloadFileFromUrlOptions = {}
178): Promise<Buffer> {
179 const { timeoutMs = getMaxExecutionTimeout(), maxBytes, userId } = options
180
181 if (isInternalFileUrl(fileUrl)) {
182 if (!userId) {
183 logger.warn('Internal file download denied: no userId provided', { fileUrl })
184 throw new Error('Access denied: internal file URL requires an authenticated user')
185 }
186
187 const key = extractStorageKey(fileUrl)
188 if (!key) {
189 logger.warn('Internal file download denied: could not resolve storage key', { fileUrl })
190 throw new Error('Access denied: could not resolve internal file key')
191 }
192
193 const context = inferContextFromKey(key)
194
195 const hasAccess = await verifyFileAccess(key, userId, undefined, context, false)
196 if (!hasAccess) {
197 logger.warn('Internal file download denied: access check failed', { key, context, userId })
198 throw new Error('Access denied: file not found or insufficient permissions')
199 }
200
201 const { downloadFile } = await import('@/lib/uploads/core/storage-service')
202 return downloadFile({ key, context, maxBytes })
203 }
204
205 const urlValidation = await validateUrlWithDNS(fileUrl, 'fileUrl')
206 if (!urlValidation.isValid) {
207 throw new Error(`Invalid file URL: ${urlValidation.error}`)
208 }
209
210 const response = await secureFetchWithPinnedIP(fileUrl, urlValidation.resolvedIP!, {
211 timeout: timeoutMs,
212 maxResponseBytes: maxBytes,
213 })
214
215 if (!response.ok) {
216 await consumeOrCancelBody(response)
217 throw new Error(`Failed to download file: ${response.statusText}`)
218 }
219
220 return readResponseToBufferWithLimit(response, {
221 maxBytes: maxBytes ?? Number.MAX_SAFE_INTEGER,
222 label: 'file download',
223 })
224}
225
226export async function resolveInternalFileUrl(
227 filePath: string,

Callers 3

downloadFileWithTimeoutFunction · 0.90
processFileDataMethod · 0.90
processExecutionFileFunction · 0.85

Calls 11

getMaxExecutionTimeoutFunction · 0.90
isInternalFileUrlFunction · 0.90
extractStorageKeyFunction · 0.90
inferContextFromKeyFunction · 0.90
verifyFileAccessFunction · 0.90
validateUrlWithDNSFunction · 0.90
secureFetchWithPinnedIPFunction · 0.90
consumeOrCancelBodyFunction · 0.90
warnMethod · 0.65
downloadFileFunction · 0.50

Tested by

no test coverage detected