MCPcopy Create free account
hub / github.com/Openpanel-dev/openpanel / fetchImage

Function fetchImage

apps/api/src/controllers/misc.controller.ts:70–117  ·  view source on GitHub ↗
(
  url: URL,
)

Source from the content-addressed store, hash-verified

68
69// Fetch image with timeout and size limits
70async function fetchImage(
71 url: URL,
72): Promise<{ buffer: Buffer; contentType: string; status: number }> {
73 const controller = new AbortController();
74 const timeout = setTimeout(() => controller.abort(), 1000); // 10s timeout
75
76 try {
77 const response = await fetch(url.toString(), {
78 redirect: 'follow',
79 signal: controller.signal,
80 headers: {
81 'user-agent': USER_AGENT,
82 accept: 'image/*,*/*;q=0.8',
83 },
84 });
85
86 clearTimeout(timeout);
87
88 if (!response.ok) {
89 return {
90 buffer: Buffer.alloc(0),
91 contentType: 'text/plain',
92 status: response.status,
93 };
94 }
95
96 // Size guard
97 const contentLength = Number(response.headers.get('content-length') ?? '0');
98 if (contentLength > MAX_BYTES) {
99 throw new Error(`Remote file too large: ${contentLength} bytes`);
100 }
101
102 const arrayBuffer = await response.arrayBuffer();
103 const buffer = Buffer.from(arrayBuffer);
104
105 // Additional size check for actual content
106 if (buffer.length > MAX_BYTES) {
107 throw new Error('Remote file exceeded size limit');
108 }
109
110 const contentType =
111 response.headers.get('content-type') || 'application/octet-stream';
112 return { buffer, contentType, status: 200 };
113 } catch (error) {
114 clearTimeout(timeout);
115 return { buffer: Buffer.alloc(0), contentType: 'text/plain', status: 500 };
116 }
117}
118
119// Check if URL is an ICO file
120function isIcoFile(url: string, contentType?: string): boolean {

Callers 2

getFaviconFunction · 0.85
getOgImageFunction · 0.85

Calls 4

fetchFunction · 0.50
toStringMethod · 0.45
getMethod · 0.45
fromMethod · 0.45

Tested by

no test coverage detected