MCPcopy Create free account
hub / github.com/hashintel/hash / setupFileDownloadProxyHandler

Function setupFileDownloadProxyHandler

apps/hash-api/src/storage/index.ts:162–294  ·  view source on GitHub ↗
(app: Express, cache: Keyv)

Source from the content-addressed store, hash-verified

160 * @param cache - a cache to store presigned URLs so we don't needlessly create URLs for every download
161 */
162export const setupFileDownloadProxyHandler = (app: Express, cache: Keyv) => {
163 app.get("/file/*splat", async (req, res) => {
164 const key = (req.params as { splat: string[] }).splat.join("/");
165 const urlOnly = req.query.urlOnly;
166
167 // We purposefully return 404 for all error cases.
168 if (!key) {
169 res.sendStatus(404);
170 return;
171 }
172
173 const keyParts = key.split("/");
174 const [entityId, editionTimestamp, filename] = keyParts.slice(-3);
175
176 if (!entityId || !editionTimestamp || !filename) {
177 res.status(400).json({
178 error: `File path ${key} is invalid – should be of the form [EntityId]/[EditionTimestamp]/[Filename], with an optional leading [Prefix]/`,
179 });
180 return;
181 }
182 if (!isEntityId(entityId)) {
183 res.status(400).json({
184 error: `File path contains invalid entityId ${entityId} in ${key}`,
185 });
186 return;
187 }
188
189 const actorId = getActorIdFromRequest(req);
190
191 const fileEntity = await getFileEntity(
192 req.context,
193 { actorId },
194 {
195 entityId,
196 key,
197 },
198 );
199
200 if (!fileEntity) {
201 res.status(404).json({
202 error: `Could not find file entity ${entityId} with edition timestamp ${editionTimestamp}, either it does not exist or you do not have permission to access it.`,
203 });
204 return;
205 }
206
207 if (!isFileEntity(fileEntity)) {
208 res.status(400).json({
209 error: `Found entity ${fileEntity.metadata.recordId.entityId} is not a file entity – has type(s) ${fileEntity.metadata.entityTypeIds.join(", ")}`,
210 });
211 return;
212 }
213
214 const { fileStorageKey } = simplifyProperties(fileEntity.properties);
215 if (!fileStorageKey) {
216 res.status(400).json({
217 error: `File entity ${fileEntity.metadata.recordId.entityId} is missing the necessary properties for file retrieval`,
218 });
219 return;

Callers 1

mainFunction · 0.90

Calls 14

isEntityIdFunction · 0.90
getActorIdFromRequestFunction · 0.90
simplifyPropertiesFunction · 0.90
isStorageTypeFunction · 0.90
getFileEntityFunction · 0.85
splitMethod · 0.80
jsonMethod · 0.80
warnMethod · 0.80
isFileEntityFunction · 0.70
getMethod · 0.65
presignDownloadMethod · 0.65

Tested by

no test coverage detected