Virtual FileSystem (VFS)

aah introduced the Virtual FileSystem (VFS) feature in v0.11.0

  • In-memory FileSystem
  • Ability to mount FileSystem directory into application virtual directory
  • The mounted virtual directory is accessible via aah.App().VFS() within aah application
  • A single consistent APIs for accessing Virtual and Physical FileSystem

Table of Contents

Quick glance of supported VFS APIs

The signatures are the same as the standard Go filesystem APIs (package os, filepath and ioutil).

// FileSystem methods => aah.App().VFS()
Open(name string) (File, error)
Lstat(name string) (os.FileInfo, error)
Stat(name string) (os.FileInfo, error)
ReadFile(filename string) ([]byte, error)
ReadDir(dirname string) ([]os.FileInfo, error)
Glob(pattern string) ([]string, error)
Walk(root string, walkFn filepath.WalkFunc) error
FindMount(name string) (*Mount, error)
AddMount(mountPath, physicalPath string) error

// FileSystem convenient methods => aah.App().VFS()
Dirs(root string) ([]string, error)
Files(root string) ([]string, error)
IsExists(name string) bool

File Interface returned by aah.App().VFS().Open()

// File interface returned by a vfs.FileSystem's Open method.
type File interface {
	Readdirnames(n int) ([]string, error)

Specific Case Interface

// RawBytes interface is to retrieve underlying file's raw bytes.
// Note: It could be gzip or non-gzip bytes. Use interface `Gziper`
// to identify byte classification.
type RawBytes interface {
	RawBytes() []byte

// Gziper interface is to identify whether the file's raw bytes is gzipped or not.
type Gziper interface {
	IsGzip() bool

Common Fact of VFS for Single and Non-Single Binary

  • By default, aah mounts the application base directory as /app.
  • Application base directory and its sub-directories are accessible via /app/**
    • For e.g.: accessing /app/config/aah.conf
      • aah.App().VFS().Open(path.Join(aah.App().VirtualBaseDir(), "config", "aah.conf"))
  • All the mounted directories are accessible via aah.App().VFS().

For Single Binary

  • The mounted directories get embedded into aah’s single binary when built with aah build --single or aah b -s.
  • Embed packaging uses same exclusion list from config build.excludes.
  • During the development phase, VFS loads files and directories from Physical FileSystem. Basically, the aah run command.
  • It appropriately does Gzip compression, while embedding files into binary.
  • Static Files delivery - serves Gzip file data. No decompression is done at this stage.
  • The embedded file path can be searchable via aah application binary using command <app-binary> vfs find --pattern "regex pattern". This is the trivial way to know which files have got embedded into the binary.

Note: Anti-viruses software(s) may considers Go binary byte code source files as a threat, so it would clean/delete generate files that would cause aah CLI to fail/hang. Add $GOPATH or particular aah application path as exclusion in the anti-virus.

For Non-Single Binary

  • VFS always loads files and directories from Physical FileSystem.
  • Mounted directories does not get packed in the Zip archive, during the aah build phase. Only the mount entry details are added into the aah binary.
    • Ensure that the mounted directories Physical Path does exist on the targeted deploy machine.

Adding Custom Directory Mount

Configuration goes into aah.project (generated by command aah new).

# Virtual FileSystem (VFS) configuration
# Doc:
vfs {
  # Adding custom mount points.
  # Configured mount points directories and sub-directories
  # are embedded into the aah binary during the single binary build.
  # Note: Embed packaging uses same exclusion list from config `build.excludes`.
  mount {
    # Choose a unique key name
    #my_mount {
    #  # Mount point (path separator is '/').
    #  mount_path = "/my_mount"
    #  # Physical FileSystem path.
    #  # Note: Only absolute path is accepted.
    #  physical_path = "/Users/jeeva/path/to/physical"

  # This config speeds up the single binary build process.
  # No need to spend time in gzipping for compressed content type.
  # Even without this config, aah decides best on what to gzip.
  no_gzip = [".png", ".jpeg", ".jpg", ".gif", ".bmp", ".tiff", ".tif"
    ".woff", ".woff2"]