How to write a Fantom Web Server in just 7 lines of code!

This web application will serve up static files from your file system. It is the smallest, yet usable, web application I could think of!

Once running, it maps all incoming HTTP requests to files in the C:\Projects\ directory. So if you keep your HTML and CSS files there, they would all be available from a web browser.

Create the web server in these small steps!

1). It uses BedSheet v1.5 so first make sure you have it installed in your Fantom environment.

fanr install -r http://eggbox.fantomfactory.org/fanr "afBedSheet 1.5"

2). Create a text file called WebServer.fan in C:\Projects\:

select all
using afIoc
using afBedSheet

class WebServer {
    Int main() {
        BedSheetBuilder(AppModule#.qname).startWisp(8080)
    }
}

const class AppModule {
    @Contribute { serviceType=FileHandler# }
    static Void contributeFileHandler(Configuration conf) {
        conf[`/`] = `file:C:/Projects/`
    }
}

Note: Okay, so the pedantic amongst you would have counted more than 7 lines of code there. But if you delete some whitespace and fully qualify the class names you can actually write it in 5 lines of code!

So I think advertising 7 lines is a happy compromise! :p

3). Run WebServer.fan as a Fantom script from the command line:

select all
C:\Projects>fan WebServer.fan

[info] [afBedSheet] Found mod 'WebServer_0::AppModule'
[info] [web] http started on port 8080
[info] [afBedSheet] Starting Bed App 'WebServer_0' on port 8080
[info] [afIoc] Adding module WebServer_0::AppModule
[info] [afIoc] Adding module afBedSheet::BedSheetModule
[info] [afIoc] Adding module afIocConfig::IocConfigModule
[info] [afIoc] Adding module afBedSheet::BedSheetEnvModule
[info] [afIoc] Adding module afConcurrent::ConcurrentModule
[info] [afIoc]

27.03% of services were built on startup (10/37)
   ___    __                 _____        _
  / _ |  / /_____  _____    / ___/__  ___/ /_________  __ __
 / _  | / // / -_|/ _  /===/ __// _ \/ _/ __/ _  / __|/ // /
/_/ |_|/_//_/\__|/_//_/   /_/   \_,_/__/\__/____/_/   \_, /
           Alien-Factory BedSheet v1.5.2, IoC v3.0.2 /___/

[info] [afIoc] IoC Registry built in 220ms and started up in 498ms

Bed App 'WebServer_0' v0 listening on http://localhost:8080/

4). Point your browser to http://localhost:8080/WebServer.fan and watch the application serve itself!

How Does It Work?

The main() method starts BedSheet, passing in the fully qualified name of the module class ( AppModule ) and the port to listen on ( 8080 ).

Classes in scripts do have fully qualified names, even though they're not officially part of a pod. That is because, behind the scenes, Fantom creates a transient pod to temporarily house the scripts in. You can see this in the log message:

[info] [afIoc] Adding module WebServer_0::AppModule

The AppModule itself does nothing more than configure the FileHandler service. The FileHandler service then maps these requests to the C:\Projects\ directory.

To serve files under a different URL, say /poo, change the configuration line to:

conf[`/poo`] = `file:C:/Projects/`

Now the script is served under http://localhost:8080/poo/WebServer.fan.

We could also change the configuration to always serve files from the same directory as the script:

conf[`/poo`] = `./`

Of course, you could put any directory in there, just make sure it ends with a trailing slash.

Note the file: scheme was only required because originally we had a Windows path starting with C:/.

Epilogue

We've just seen how to use a Fantom script to start a mini BedSheet web application that serves files. We then changed the FileHandler configuration to serve files under different URLs and from different directories.

Brilliant!

Have fun!

Edits

  • 29 July 2016 - Updated example to BedSheet 1.5.
  • 17 June 2014 - Updated example from File Server to Web Server, added BedSheet output.
  • 26 November 2013 - Original article.

Discuss