in packages/metro/src/Server.js [374:425]
async _processSingleAssetRequest(req: IncomingMessage, res: ServerResponse) {
const urlObj = url.parse(decodeURI(req.url), true);
let [, assetPath] =
(urlObj &&
urlObj.pathname &&
urlObj.pathname.match(/^\/assets\/(.+)$/)) ||
[];
if (!assetPath && urlObj && urlObj.query && urlObj.query.unstable_path) {
const [, actualPath, secondaryQuery] = nullthrows(
urlObj.query.unstable_path.match(/^([^?]*)\??(.*)$/),
);
if (secondaryQuery) {
Object.assign(urlObj.query, querystring.parse(secondaryQuery));
}
assetPath = actualPath;
}
if (!assetPath) {
throw new Error('Could not extract asset path from URL');
}
const processingAssetRequestLogEntry = log(
createActionStartEntry({
action_name: 'Processing asset request',
asset: assetPath[1],
}),
);
try {
const data = await getAsset(
assetPath,
this._config.projectRoot,
this._config.watchFolders,
urlObj.query.platform,
this._config.resolver.assetExts,
);
// Tell clients to cache this for 1 year.
// This is safe as the asset url contains a hash of the asset.
if (process.env.REACT_NATIVE_ENABLE_ASSET_CACHING === true) {
res.setHeader('Cache-Control', 'max-age=31536000');
}
res.end(this._rangeRequestMiddleware(req, res, data, assetPath));
process.nextTick(() => {
log(createActionEndEntry(processingAssetRequestLogEntry));
});
} catch (error) {
console.error(error.stack);
res.writeHead(404);
res.end('Asset not found');
}
}