const mixinafBedSheet::FileHandler
afBedSheet::FileHandler
(Service) - Request Handler that maps URLs to files on the file system.
Example, to map all URLs prefixed with /pub/
to files under the <app>/etc/web/
directory, add the following to your AppModule
:
@Contribute { serviceType=FileHandler# } static Void contributeFileHandler(Configuration conf) { conf[`/pub/`] = `etc/web/`.toFile }
Use the fromServerFile()
to generate client URLs to be used by the browser. Example:
// note how the file uses a relative URL fromServerFile(`etc/web/css/mystyle.css`.toFile).clientUrl // --> `/pub/css/mystyle.css`
Now when the browser requests the URL /pub/css/mystyle.css
, BedSheet
will return the file <app>/etc/web/css/mystyle.css
.
It is common to serve files from the root URL:
conf[`/`] = `etc/web/`
That way etc/web/
may contain etc/web/css/
, etc/web/images/
and etc/web/scripts/
.
The generated clientUrl
contains any extra WebMod
path segments required to reach the BedSheet WebMod
. It also contains path segments as provided by any asset caching strategies, such as Cold Feet.
Fail Fast
An understated advantage of using FileHandler
to generate URLs for your assets 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 URI 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 Other Routes
The FileHandler
directory mappings are automatically added to the Routes service on startup. That means it is possible to specify a Route
URL with more than one handler; a custom handler and this FileHandler
. With a bit of configuration it is possible to specify which takes precedence.
The FileHandler
route contributions are set with the ID afBedSheet.fileHander
, so when Route
precedence is important, use it in your config:
@Contribute { serviceType=Routes# } static Void contributeRoutes(Configuration config) { // this Route will be served in place of the file 'url1.txt' config.set("beforeExample", Route(`/url1.txt`, ...)).before("afBedSheet.fileHandler") // this Route will be served if there is no file called 'url2.txt' config.set("afterExample", Route(`/url2.txt`, ...)).after("afBedSheet.fileHandler") }
@uses Configuration of Uri:File
- directoryMappings
abstract Uri:File directoryMappings()
Returns the map of URL to directory mappings
- fromLocalUrl
abstract FileAsset fromLocalUrl(Uri localUrl)
Given a local URL (a simple URL relative to the WebMod), this returns a corresponding (cached)
FileAsset
. ThrowsArgErr
if the URL is not mapped.- fromServerFile
abstract FileAsset fromServerFile(File serverFile)
Given a file on the server, this returns a corresponding (cached)
FileAsset
. ThrowsArgErr
if the file directory is not mapped.