// ReloadRoutes reloads the routes for this Router instance on the fly. It will
// create a new proxy mux, load applications (backends) and routes into it, and
// then flip the "mux" pointer in the Router.
func (rt *Router) ReloadRoutes() {
	// save a reference to the previous mux in case we have to restore it
	oldmux := rt.mux
	defer func() {
		if r := recover(); r != nil {
			log.Println("router: recovered from panic in ReloadRoutes:", r)
			rt.mux = oldmux
			log.Println("router: original routes have been restored")

	log.Println("mgo: connecting to", rt.mongoUrl)
	sess, err := mgo.Dial(rt.mongoUrl)
	if err != nil {
		panic(fmt.Sprintln("mgo:", err))
	defer sess.Close()
	sess.SetMode(mgo.Monotonic, true)

	db := sess.DB(rt.mongoDbName)

	log.Printf("router: reloading routes")
	newmux := triemux.NewMux()

	apps := loadApplications(db.C("applications"), newmux)
	loadRoutes(db.C("routes"), newmux, apps)

	rt.mux = newmux
	log.Printf("router: reloaded routes")
// NewRouter returns a new empty router instance. You will still need to call
// ReloadRoutes() to do the initial route load.
func NewRouter(mongoUrl, mongoDbName string) *Router {
	return &Router{
		mux:         triemux.NewMux(),
		mongoUrl:    mongoUrl,
		mongoDbName: mongoDbName,
func main() {
	mux := triemux.NewMux()

	googUrl, _ := url.Parse("http://google.com")
	aaplUrl, _ := url.Parse("http://apple.com")
	goog := httputil.NewSingleHostReverseProxy(googUrl)
	aapl := httputil.NewSingleHostReverseProxy(aaplUrl)

	// register a prefix route pointing to the Google backend (all requests to
	// "/google<anything>" will go to this backend)
	mux.Handle("/google", true, goog)

	// register an exact (non-prefix) route pointing to the Apple backend
	mux.Handle("/apple", false, aapl)

	log.Println("Listening on :8088")
	log.Fatalln(http.ListenAndServe(":8088", mux))