Search code examples
fantomafbedsheet

How do I route to a directory?


I'm playing around with afBedSheet and wish to handle all requests to a directory. eg a request to /abcd calls abcdMethod#doSomething

I have the routes set up as

@Contribute { serviceId="Routes" }
static Void contributeRoutes(OrderedConfig conf) {
  conf.add(Route(`/abcd/?`, abcdMethod#doSomething))
}

Yet when I browse to /abcd I get 404 errors :(

How do I make this work?


Solution

  • Ensure your route handler method doSomething() does NOT take any arguments. For example, save the following as Example.fan:

    using afIoc
    using afBedSheet
    
    class MyRoutes {
      Text abcdMethod() {
        return Text.fromPlain("Hello from `abcd/`!")
      }
    }
    
    class AppModule {
      @Contribute { serviceId="Routes" }
      static Void contributeRoutes(OrderedConfig conf) {
        conf.add(Route(`/abcd/?`, MyRoutes#abcdMethod))
      }
    }
    
    class Example {
      Int main() {
        afBedSheet::Main().main([AppModule#.qname, "8080"])
      }
    }
    

    And run it with:

    > fan Example.fan -env dev
    

    (Appending -env dev will list all available routes on the 404 page.)

    Because /abcd/? has a trailing ?, it will match both the file URL of http://localhost:8080/abcd and the directory URL of http://localhost:8080/abcd/. But note it will not match any URLs inside /abcd.

    To match files inside /abcd, add a Uri parameter to your route method (to capture the path) and change your route to:

    /abcd/**  only matches direct descendants --> /abcd/wotever
    
    /abcd/*** will match subdirectories too   --> /abcd/wot/ever
    

    For example:

    using afIoc
    using afBedSheet
    
    class MyRoutes {
      Text abcdMethod(Uri? subpath) {
        return Text.fromPlain("Hello from `abcd/` - the sub-path is $subpath")
      }
    }
    
    class AppModule {
      @Contribute { serviceId="Routes" }
      static Void contributeRoutes(OrderedConfig conf) {
        conf.add(Route(`/abcd/***`, MyRoutes#abcdMethod))
      }
    }
    
    class Example {
      Int main() {
        afBedSheet::Main().main([AppModule#.qname, "8080"])
      }
    }