const mixinafBedSheet::FileHandler
afBedSheet::FileHandler : afBedSheet::ClientAssetProducer
(Service) - A ClientAssetProducer
that maps URLs to files on the file system. Use to serve up file assets.
Note if no configuration is given to FileHandler
then it defaults to serving files from the etc/web-static/
directory.
Configuration
Suppose your project has this directory structure:
myProj/ |- fan/ |- test/ |- etc |- www/ |- css/ | |- app.css |- images/ | |- logo.png |- scripts/
To serve up files from the css/
directory add the following to AppModule
:
@Contribute { serviceType=FileHandler# } Void contributeFileHandler(Configuration config) { config[`/stylesheets/`] = `etc/www/css/`.toFile }
Browsers may then access app.css
with the URL /stylesheets/app.css
.
Rather than hardcoding the string /stylesheets/app.css
in HTML, it is better to generate a client URL from FileHandler
.
urlStr := fileHandler.fromLocalUrl(`/stylesheets/app.css`).clientUrl.encode
Most of the time urlStr
will be the same as the hardcoded URL but it has the added benefit of:
- Failing fast if the file does not exist
- generating correct URLs in non-root WebMods
- utilising an asset caching strategy
The generated clientUrl
contains any extra WebMod
path segments required to reach the BedSheet WebMod
. It is also transformed by asset caching strategies such as Cold Feet.
Serve All Root Directories
Using the above example, extra config would need to be added to serve the images/
and the scripts/
directories. This is not ideal. So to serve all the files and directories under etc/www/
add config for the root URL:
conf[`/`] = `etc/www/`.toFile
This way everything under etc/www/
is served as is. Example, logo.png
is accessed with the URL /images/logo.png
.
Note if no configuration is given to FileHandler
then it defaults to serving root files from the etc/web-static/
directory.
Fail Fast
An understated advantage of using FileHandler
to generate client URLs is that it fails fast.
Should an asset not exist on the file system (due to a bodged rename, a case sensitivity issue, or other) then FileHandler
will throw an Err on the server when the client URL is constructed. This allows your web tests to quickly pick up these tricky errors.
The lesser appealing alternative is for the incorrect URL to be served to the browser which on following, will subsequently receive a 404 - Not Found
. While this may not seem a big deal, these errors often go unnoticed and easily find their way into production.
Precedence with Routes
FileHandler
is a ClientAssetProducer
so file assets are served by the Asset Middleware. By default the Asset Middleware is processed before the Routes Middleware so should an asset and Route serve the same URL, the asset takes precedence. (Meaning the asset is served and Route is not processed.)
@uses Configuration of Uri:File
- directoryMappings
abstract Uri:File directoryMappings()
Returns the map of URL to directory mappings
- fromLocalUrl
abstract ClientAsset? fromLocalUrl(Uri localUrl, Bool checked := true)
Given a local URL (a simple URL relative to the WebMod), this returns a corresponding (cached)
FileAsset
.url := fileHandler.fromLocalUrl(`/stylesheets/app.css`).clientUrl.encode
Throws
ArgErr
if the checked and file does not exist,null
otherwise.- fromServerFile
abstract ClientAsset? fromServerFile(File serverFile, Bool checked := true)
Given a file on the server, this returns a corresponding (cached)
ClientAsset
.Throws
ArgErr
if the checked and file does not exist,null
otherwise.