in src/msha/middlewares/response.middleware.ts [85:243]
export function getStorageContent(
req: http.IncomingMessage,
res: http.ServerResponse,
pathToServe: string | undefined,
matchedRoute: SWAConfigFileRoute | undefined,
responseOverridesRule: SWAConfigFileResponseOverrides | undefined,
navigationFallbackRule: SWAConfigFileNavigationFallback | undefined,
mimeTypeRule: SWAConfigFileMimeTypes | undefined,
routeHeaders: SWAConfigFileRouteHeaders | undefined,
globalHeaders: SWAConfigFileGlobalHeaders | undefined
): {
isFunctionFallbackRequest: boolean;
isSuccessfulSiteHit: boolean;
} {
logger.silly(`checking storage content`);
// don't serve staticwebapp.config.json / routes.json
if (isSWAConfigFileUrl(req)) {
logger.silly(` - request to config file detected. Exit`);
handleErrorPage(req, res, 404, responseOverridesRule);
return {
isFunctionFallbackRequest: false,
isSuccessfulSiteHit: false,
};
}
let requestPath = req.url as string;
let filePathFromRequest: string | null = null;
let decodedRequestPath = req.url;
const { urlPathnameWithoutQueryParams } = parseQueryParams(req, matchedRoute);
// we only process if the user is NOT connecting to a remote dev server.
// if the user is connecting to a remote dev server, we skip the following logic.
if (IS_APP_DEV_SERVER()) {
logger.silly(`remote dev server detected.`);
return {
isFunctionFallbackRequest: false,
isSuccessfulSiteHit: true,
};
} else {
requestPath = urlPathnameWithoutQueryParams;
decodedRequestPath = urlPathnameWithoutQueryParams;
if (pathToServe) {
requestPath = pathToServe;
decodedRequestPath = decodeURI(pathToServe);
}
filePathFromRequest = tryFindFileForRequest(requestPath!);
}
if (!filePathFromRequest) {
let shouldDisplayNotFoundPage = true;
if (navigationFallbackRule?.rewrite) {
const isFunctionFallback = isFunctionRequest(req, navigationFallbackRule.rewrite);
logger.silly(` - isFunctionFallback: ${chalk.yellow(isFunctionFallback)}`);
if (isFunctionFallback) {
return {
isFunctionFallbackRequest: true,
isSuccessfulSiteHit: false,
};
} else {
const navigationFallbackRewrite = navigationFallbackRule.rewrite;
logger.silly(`validating navigation fallback rewrite rule`);
logger.silly(` - rewrite: ${chalk.yellow(navigationFallbackRewrite)}`);
const isNavigationFallbackWritePathExists = tryFindFileForRequest(navigationFallbackRewrite);
if (
isNavigationFallbackWritePathExists &&
!isRequestPathExcludedFromNavigationFallback(decodedRequestPath, navigationFallbackRule, matchedRoute)
) {
shouldDisplayNotFoundPage = false;
}
if (navigationFallbackRewrite) {
filePathFromRequest = navigationFallbackRewrite;
if (!shouldDisplayNotFoundPage) {
logger.silly(`rewrite request to ${chalk.yellow(filePathFromRequest)}`);
req.url = filePathFromRequest;
}
}
}
}
logger.silly(` - shouldDisplayNotFoundPage: ${chalk.yellow(shouldDisplayNotFoundPage)}`);
if (shouldDisplayNotFoundPage) {
handleErrorPage(req, res, 404, responseOverridesRule);
return {
isFunctionFallbackRequest: false,
isSuccessfulSiteHit: false,
};
}
}
if (!filePathFromRequest) {
return {
isFunctionFallbackRequest: false,
isSuccessfulSiteHit: false,
};
}
// if the file path is a remote HTTP request, this means we are connecting to a dev server.
// exist here and let the remote server handle the request.
if (isHttpUrl(filePathFromRequest)) {
return {
isFunctionFallbackRequest: false,
isSuccessfulSiteHit: true,
};
}
// mime type
const mimeType = getMimeTypeForExtension(filePathFromRequest, mimeTypeRule);
res.setHeader("Content-Type", mimeType);
// compute both global and route headers
const matchingRouteHeaders = getHeadersForRoute(routeHeaders, globalHeaders);
if (responseOverridesRule) {
// Handle HEAD request
if (req.method === "HEAD") {
updateResponseHeaders(res, matchingRouteHeaders);
res.statusCode = 200;
return {
isFunctionFallbackRequest: false,
isSuccessfulSiteHit: true,
};
}
// Handle OPTIONS request
if (req.method === "OPTIONS") {
updateResponseHeaders(res, matchingRouteHeaders);
const allowStr = "GET, HEAD, OPTIONS";
res.setHeader("Allow", allowStr);
res.statusCode = 204; // No Content
return {
isFunctionFallbackRequest: false,
isSuccessfulSiteHit: true,
};
}
}
// Handle GET request
updateResponseHeaders(res, matchingRouteHeaders);
req.url = filePathFromRequest;
return {
isSuccessfulSiteHit: true,
isFunctionFallbackRequest: false,
};
}