Suave is a simple web development F# library providing a lightweight web server and a set of combinators to manipulate route flow and task composition.
TL;DR: to make Suave able to serve an entire directory of files
that were embedded in an assembly, which is convenient for
single-file deployments to include all web assets inside the final
executable.
By default, the original file name will be transformed into a
resource name at build-time, e.g. in project Suave.Tests,
embedded-resource.txt become Suave.Tests.embedded-resource.txt.
There is an undocumented build property "UseStandardResourceNames"
for F#, which disables this transformation when set to false, so
that embedded-resource.txt remain embedded-resource.txt.
But this doesn't work well with embedding nested directories of
files, e.g. with project property <EmbeddedResource Include="wwwroot\**" /> and file wwwroot/js/vendor/jquery.min.js,
the resource name become jquery.min.js, losing the directory
parts.
ASP.NET Core solves this problem by abstracting file system access
through the use of File Providers,
one of them is the ManifestEmbeddedFileProvider.
To use this provider, the application has to reference nuget package
Microsoft.Extensions.FileProviders.Embedded and set a build
property
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>.
This setup will generate one additional resource, which is the
manifest that describes the source structure.
This PR parses that manifest file to construct a mapping between
source paths to actual resource names,
e.g. "wwwroot/js/vendor/jquery.min.js" maps to
"Suave.Tests.wwwroot.js.vendor.jquery.min.js", so Suave is able to
serve the entire wwwroot directory just like a physical directory.
This PR also handles when Assembly.Location is empty for reading the
last modification time and falls back to the process startup
time. (I can't think of better alternatives, in ASP.NET Core, they uses the current time)
Unit tests were updated to cover this change.
About the dependency on Microsoft.Extensions.FileProviders.Embedded
This PR doesn't make Suave depend on that package, it's the
application that's built with Suave has to reference it.
Although that package was developed as part of the ASP.NET Core,
it can be used outside of ASP.NET Core projects.
Dependency on it is actually only at build-time for the generation
of the manifest file. And it was built with IsTrimmable=true,
which works with IL trimimg.
Rationale:
TL;DR: to make Suave able to serve an entire directory of files that were embedded in an assembly, which is convenient for single-file deployments to include all web assets inside the final executable.
By default, the original file name will be transformed into a resource name at build-time, e.g. in project
Suave.Tests
,embedded-resource.txt
becomeSuave.Tests.embedded-resource.txt
.There is an undocumented build property "UseStandardResourceNames" for F#, which disables this transformation when set to
false
, so thatembedded-resource.txt
remainembedded-resource.txt
.But this doesn't work well with embedding nested directories of files, e.g. with project property
<EmbeddedResource Include="wwwroot\**" />
and filewwwroot/js/vendor/jquery.min.js
, the resource name becomejquery.min.js
, losing the directory parts.ASP.NET Core solves this problem by abstracting file system access through the use of File Providers, one of them is the
ManifestEmbeddedFileProvider
.To use this provider, the application has to reference nuget package
Microsoft.Extensions.FileProviders.Embedded
and set a build property<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
.This setup will generate one additional resource, which is the manifest that describes the source structure.
This PR parses that manifest file to construct a mapping between source paths to actual resource names, e.g. "wwwroot/js/vendor/jquery.min.js" maps to "Suave.Tests.wwwroot.js.vendor.jquery.min.js", so Suave is able to serve the entire
wwwroot
directory just like a physical directory.This PR also handles when Assembly.Location is empty for reading the last modification time and falls back to the process startup time. (I can't think of better alternatives, in ASP.NET Core, they uses the current time)
Unit tests were updated to cover this change.
About the dependency on
Microsoft.Extensions.FileProviders.Embedded
This PR doesn't make Suave depend on that package, it's the application that's built with Suave has to reference it.
Although that package was developed as part of the ASP.NET Core, it can be used outside of ASP.NET Core projects.
Dependency on it is actually only at build-time for the generation of the manifest file. And it was built with
IsTrimmable=true
, which works with IL trimimg.