// Every path should return false or send a response.
// Otherwise we can get a timeout error as the browser waits for a response.
//
// NOTE: this method gets called on different threads!
protected override bool ProcessRequest(IRequestInfo info)
{
var localPath = GetLocalPathWithoutQuery(info);
//enhance: something feeds back these branding logos with a weird URL, that shouldn't be.
if (localPath.IndexOf("api/branding") > 20) // this 20 is just arbitrary... the point is, if it doesn't start with api/branding, it is bogus
{
return(false);
}
if (localPath.ToLower().StartsWith("api/"))
{
var endpoint = localPath.Substring(3).ToLowerInvariant().Trim(new char[] { '/' });
foreach (var pair in _endpointRegistrations.Where(pair =>
Regex.Match(endpoint,
"^" + //must match the beginning
pair.Key.ToLower()
).Success))
{
// A single synchronization object won't do, because when processing a request to create a thumbnail,
// we have to load the HTML page the thumbnail is based on. If the page content somehow includes
// an api request (api/branding/image is one example), that request will deadlock if the
// api/pageTemplateThumbnail request already has the main lock.
// To the best of my knowledge, there's no shared data between the thumbnailing process and any
// other api requests, so it seems safe to have one lock that prevents working on multiple
// thumbnails at the same time, and one that prevents working on other api requests at the same time.
var syncOn = SyncObj;
if (localPath.ToLowerInvariant().StartsWith("api/pagetemplatethumbnail"))
{
syncOn = ThumbnailSyncObj;
}
lock (syncOn)
{
return(ApiRequest.Handle(pair.Value, info, CurrentCollectionSettings, _bookSelection.CurrentSelection));
}
}
}
//OK, no more obvious simple API requests, dive into the rat's nest of other possibilities
if (base.ProcessRequest(info))
{
return(true);
}
if (localPath.Contains("CURRENTPAGE")) //useful when debugging. E.g. http://localhost:8091/bloom/CURRENTPAGE.htm will always show the page we're on.
{
localPath = _keyToCurrentPage;
}
string content;
bool gotSimulatedPage;
lock (_urlToSimulatedPageContent)
{
gotSimulatedPage = _urlToSimulatedPageContent.TryGetValue(localPath, out content);
}
if (gotSimulatedPage)
{
info.ContentType = "text/html";
info.WriteCompleteOutput(content ?? "");
return(true);
}
if (localPath.StartsWith(OriginalImageMarker) && IsImageTypeThatCanBeDegraded(localPath))
{
// Path relative to simulated page file, and we want the file contents without modification.
// (Note that the simulated page file's own URL starts with this, so it's important to check
// for that BEFORE we do this check.)
localPath = localPath.Substring(OriginalImageMarker.Length + 1);
return(ProcessAnyFileContent(info, localPath));
}
if (localPath.StartsWith("error", StringComparison.InvariantCulture))
{
ProcessError(info);
return(true);
}
else if (localPath.StartsWith("i18n/", StringComparison.InvariantCulture))
{
if (ProcessI18N(localPath, info))
{
return(true);
}
}
else if (localPath.StartsWith("directoryWatcher/", StringComparison.InvariantCulture))
{
return(ProcessDirectoryWatcher(info));
}
else if (localPath.StartsWith("localhost/", StringComparison.InvariantCulture))
{
var temp = LocalHostPathToFilePath(localPath);
if (RobustFile.Exists(temp))
{
localPath = temp;
}
}
// this is used only by the readium viewer
else if (localPath.StartsWith("node_modules/jquery/dist/jquery.js"))
{
localPath = BloomFileLocator.GetBrowserFile("jquery.min.js");
// Avoid having "output/browser/" removed on Linux developer machines.
// GetBrowserFile adds output to the path on developer machines, but not user installs.
return(ProcessContent(info, localPath));
}
//Firefox debugger, looking for a source map, was prefixing in this unexpected
//way.
localPath = localPath.Replace("output/browser/", "");
return(ProcessContent(info, localPath));
}