func main() {

	router1 := httprouter.New()
	router1.GET("/keys", GetKeyServer3000)
	router1.PUT("/keys/:key_id/:value", PutServer1)
	server := http.Server{
		Addr:    "0.0.0.0:3000",
		Handler: router1,
	}
	router2 := httprouter.New()
	router2.GET("/keys", GetKeyServer3001)
	router2.PUT("/keys/:key_id/:value", PutServer2)

	go func() {
		http.ListenAndServe("localhost:3001", router2)
	}()

	router3 := httprouter.New()
	router3.GET("/keys", GetKeyServer3002)
	router3.PUT("/keys/:key_id/:value", PutServer3)

	go func() {
		http.ListenAndServe("localhost:3002", router3)
	}()

	server.ListenAndServe()

}
Exemple #2
0
func APIHandler(conf *Config) http.Handler {
	api := &API{
		conf: conf,
	}
	if conf.Cache {
		if err := api.cacheDashboardJS(); err != nil {
			panic(err)
		}
	}

	router := httprouter.New()
	router2 := httprouter.New()

	prefixPath := func(p string) string {
		return path.Join(conf.PathPrefix, p)
	}

	router.HandlerFunc("GET", status.Path, status.HealthyHandler.ServeHTTP)

	router.POST(prefixPath("/user/sessions"), api.WrapHandler(api.Login))
	router.DELETE(prefixPath("/user/session"), api.WrapHandler(api.Logout))

	router.GET(prefixPath("/config"), api.WrapHandler(api.GetConfig))

	router.NotFound = router2.ServeHTTP
	router2.GET(prefixPath("/*path"), api.WrapHandler(api.ServeAsset))

	return httphelper.ContextInjector("dashboard",
		httphelper.NewRequestLogger(
			api.CorsHandler(router)))
}
Exemple #3
0
func runHTTPListeners(d db.DB) {
	httpMux := htr.New()
	httpsMux := htr.New()

	// httpMux.SetupRoutes()
	err := api.SetupRoutes(
		httpsMux,
		api.Auth(d),
		api.User(d),
		api.Task(d),
	)

	if err != nil {
		log.Fatalf("router setup failed: %s\n", err.Error())
	}

	var (
		httpErr  = make(chan error)
		httpsErr = make(chan error)
	)

	println("Listening on HTTP 25000")
	println("Listening on HTTPS 25001")

	go func() { httpErr <- http.ListenAndServeTLS(":25001", "cert.pem", "key.key", httpsMux) }()
	go func() { httpsErr <- http.ListenAndServe(":25000", httpMux) }()

	var e error
	select {
	case e = <-httpErr:
	case e = <-httpsErr:
	}
	log.Fatalf("error serving http(s): %s", e.Error())
}
Exemple #4
0
func main() {
	flag.Parse()

	// initialize database
	db, err := bolt.Open(*database, 0600, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Fatalf("Could not open database: %s", err)
	}
	defer db.Close()

	if err := db.Update(initBuckets); err != nil {
		log.Fatal(err)
	}

	hookStore := &HookStore{db}

	// webhooks
	hh := &HookHandler{hookStore, db}
	router := httprouter.New()
	router.GET("/h/:id", hh.ReceiveHook)
	router.POST("/h/:id", hh.ReceiveHook)

	go func() {
		log.Printf("Listening on %s", *listenAddr)
		log.Print(http.ListenAndServe(*listenAddr, router))
	}()

	hooks, err := hookStore.List()
	if err != nil {
		log.Fatal("Fail to load hooks")
	}
	ist := NewIssueStatusTracker(NewIssueAPI(), hooks, db)

	// admin interface
	ah := &AdminHandler{hooks: hookStore, ist: ist}
	arouter := httprouter.New()
	arouter.Handler("GET", "/public/*path", http.StripPrefix("/public", http.FileServer(http.Dir("public"))))
	arouter.GET("/", ah.Index)
	arouter.Handler("GET", "/hooks", http.RedirectHandler("/", http.StatusMovedPermanently))

	arouter.GET("/hooks/new", ah.NewHook)
	arouter.POST("/hooks", ah.CreateHook)
	arouter.GET("/hooks/edit/:id", ah.EditHook)
	arouter.POST("/hooks/edit/:id", ah.UpdateHook)

	arouter.GET("/hooks/edit/:id/add", ah.AddComponent)
	arouter.POST("/hooks/edit/:id/create", ah.CreateComponent)
	arouter.GET("/hooks/edit/:id/edit/:c", ah.EditComponent)
	arouter.POST("/hooks/edit/:id/update/:c", ah.UpdateComponent)

	go func() {
		log.Printf("Admin interface on %s", *adminAddr)
		log.Print(http.ListenAndServe(*adminAddr, arouter))
	}()

	ist.RefreshIssues()
	ist.StartPolling()
}
Exemple #5
0
func New(e *engine.Engine) *App {

	if e == nil {
		panic("httphandler.New(e *engine.Engine): e is nil")
	}

	app := &App{
		engine: e,
		mux:    http.NewServeMux(),
	}

	// ---------------------------------------------------------------------------

	var (
		ordersRouter     = httprouter.New()
		orderItemsRouter = httprouter.New()
		productsRouter   = httprouter.New()
	)

	productsRouter.POST("/products/", app.createProductHandler)
	productsRouter.GET("/products/:id", app.loadProductHandler)
	productsRouter.GET("/products/", app.listProductsHandler)
	productsRouter.PUT("/products/:id", app.updateProductHandler)

	ordersRouter.POST("/orders/", app.createOrderHandler)
	ordersRouter.GET("/orders/:id", app.loadOrderHandler)
	ordersRouter.GET("/orders/", app.listOrdersHandler)
	ordersRouter.PUT("/orders/:id", app.updateOrderHandler)

	orderItemsRouter.POST("/orders/:orderID/items/", app.createOrderItemHandler)
	orderItemsRouter.GET("/orders/:orderID/items/:productID", app.loadOrderItemHandler)
	orderItemsRouter.GET("/orders/:orderID/items/", app.listOrderItemsHandler)
	orderItemsRouter.PUT("/orders/:orderID/items/:productID", app.updateOrderItemHandler)
	orderItemsRouter.DELETE("/orders/:orderID/items/:productID", app.removeOrderItemHandler)

	// (facepalm) using httphandler here was not the best decision:
	app.mux.HandleFunc("/orders/", func(w http.ResponseWriter, r *http.Request) {
		if strings.Contains(r.URL.Path, "/items") {
			orderItemsRouter.ServeHTTP(w, r)
		} else {
			ordersRouter.ServeHTTP(w, r)
		}
	})

	app.mux.Handle("/", productsRouter)

	// ---------------------------------------------------------------------------

	return app
}
func loadHttpRouter(routes []route) http.Handler {
	router := httprouter.New()
	for _, route := range routes {
		router.Handle(route.method, route.path, httpRouterHandle)
	}
	return router
}
Exemple #7
0
func main() {
	router := httprouter.New()
	router.GET("/", Index)
	router.GET("/user/*name", Index)

	log.Fatal(http.ListenAndServe(":8080", router))
}
Exemple #8
0
func (c *context) attachRoutes() {
	c.router = httprouter.New()

	_routes := *c.routes
	for i := range _routes {
		// Individual Controller calls per routes are expected to happen from here
		d := D{c: c, actions: _routes[i].actions, data: make(map[string]interface{})}
		switch _routes[i].method {
		case "GET":
			c.router.GET(_routes[i].url, d.call)
			break
		case "POST":
			c.router.POST(_routes[i].url, d.call)
			break
		case "PUT":
			c.router.PUT(_routes[i].url, d.call)
			break
		case "DELETE":
			c.router.DELETE(_routes[i].url, d.call)
			break
		case "OPTIONS":
			c.router.OPTIONS(_routes[i].url, d.call)
			break
		default:
			break
		}
	}
}
Exemple #9
0
func main() {
	routes, err := ParseRoutes(".")
	if err != nil {
		log.Fatal(err)
	}
	db, err = GetDbConnection()
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
	router := httprouter.New()
	for _, route := range routes {
		if route.Method == "GET" {
			router.GET(route.Path, handler(route))
		}
		if route.Method == "POST" {
			router.POST(route.Path, handler(route))
		}
		if route.Method == "PUT" {
			router.PUT(route.Path, handler(route))
		}
		if route.Method == "DELETE" {
			router.DELETE(route.Path, handler(route))
		}
	}
	port := "8080"
	if len(os.Args) > 1 {
		port = os.Args[1]
	}
	log.Fatal(http.ListenAndServe(":"+port, router))
}
Exemple #10
0
// newStatusServer allocates and returns a statusServer.
func newStatusServer(
	db *client.DB,
	gossip *gossip.Gossip,
	metricSource metricMarshaler,
	ctx *base.Context,
	rpcCtx *rpc.Context,
	stores *storage.Stores,
) *statusServer {
	server := &statusServer{
		db:           db,
		gossip:       gossip,
		metricSource: metricSource,
		router:       httprouter.New(),
		rpcCtx:       rpcCtx,
		stores:       stores,
	}

	server.router.GET(statusLogFilesListPattern, server.handleLogFilesList)
	server.router.GET(statusLogFilePattern, server.handleLogFile)
	server.router.GET(statusLogsPattern, server.handleLogs)
	// TODO(tschottdorf): significant overlap with /debug/pprof/goroutine,
	// except that this one allows querying by NodeID.
	server.router.GET(statusStacksPattern, server.handleStacks)
	server.router.GET(statusMetricsPattern, server.handleMetrics)
	server.router.GET(statusVars, server.handleVars)

	return server
}
Exemple #11
0
func (this *Monitor) setupRoutes() {
	this.router = httprouter.New()
	this.router.GET("/ver", this.versionHandler)
	this.router.GET("/metrics", this.metricsHandler)
	this.router.PUT("/set", this.configHandler)
	this.router.POST("/alertHook", this.alertHookHandler) // zabbix will call me on alert event
}
Exemple #12
0
// NewAPIWithMarshalers does the same as NewAPIWithBaseURL with the addition
// of a set of marshalers that provide a way to interact with clients that
// use a serialization format other than JSON. The marshalers map is indexed
// by the MIME content type to use for a given request-response pair. If the
// client provides an Accept header the server will respond using the client's
// preferred content type, otherwise it will respond using whatever content
// type the client provided in its Content-Type request header.
func NewAPIWithMarshalers(prefix string, baseURL string, marshalers map[string]ContentMarshaler) *API {
	if len(marshalers) == 0 {
		panic("marshaler map must not be empty")
	}

	// Add initial and trailing slash to prefix
	prefixSlashes := strings.Trim(prefix, "/")
	if len(prefixSlashes) > 0 {
		prefixSlashes = "/" + prefixSlashes + "/"
	} else {
		prefixSlashes = "/"
	}

	router := httprouter.New()
	router.MethodNotAllowed = notAllowedHandler{marshalers: marshalers}

	info := information{prefix: prefix, baseURL: baseURL}

	return &API{
		router:     router,
		prefix:     prefixSlashes,
		info:       info,
		marshalers: marshalers,
	}
}
Exemple #13
0
// New returns a new *router to be used to configure the endpoints
func New() *Router {
	r := Router{}
	r.router = httprouter.New()
	r.middleware = nil

	return &r
}
Exemple #14
0
// newStatusServer allocates and returns a statusServer.
func newStatusServer(
	db *client.DB,
	gossip *gossip.Gossip,
	metricSource json.Marshaler,
	ctx *base.Context,
	rpcCtx *rpc.Context,
	stores *storage.Stores,
) *statusServer {
	// Create an http client with a timeout
	httpClient, err := ctx.GetHTTPClient()
	if err != nil {
		log.Error(err)
		return nil
	}

	server := &statusServer{
		db:           db,
		gossip:       gossip,
		metricSource: metricSource,
		router:       httprouter.New(),
		rpcCtx:       rpcCtx,
		proxyClient:  httpClient,
		stores:       stores,
	}

	server.router.GET(statusLogFilesListPattern, server.handleLogFilesList)
	server.router.GET(statusLogFilePattern, server.handleLogFile)
	server.router.GET(statusLogsPattern, server.handleLogs)
	// TODO(tschottdorf): significant overlap with /debug/pprof/goroutine,
	// except that this one allows querying by NodeID.
	server.router.GET(statusStacksPattern, server.handleStacks)
	server.router.GET(statusMetricsPattern, server.handleMetrics)

	return server
}
Exemple #15
0
func main() {
	Values[1] = "z"
	Values[2] = "y"
	Values[3] = "x"
	Values[4] = "q"
	Values[5] = "w"
	Values[6] = "v"
	Values[7] = "u"
	Values[8] = "t"
	Values[9] = "s"
	Values[10] = "r"

	for _, each := range ListOfServers {
		HashingMapping[calculateHashValue(each)] = each
	}

	for k, _ := range Values {
		HashingMapping[calculateHashValue(strconv.Itoa(k))] = strconv.Itoa(k)
	}

	for k, _ := range HashingMapping {
		SortedHashingMappingKeys = append(SortedHashingMappingKeys, k)
	}

	sort.Strings(SortedHashingMappingKeys)
	mux := httprouter.New()
	mux.PUT("/keys/:key/:value", putDataTo)
	mux.GET("/keys/:key", getRequest)
	server := http.Server{
		Addr:    "0.0.0.0:8000",
		Handler: mux,
	}
	server.ListenAndServe()
}
Exemple #16
0
// NewServer returns a new front-end web server that handles HTTP requests for the app.
func NewServer() *Server {
	router := httprouter.New()
	server := &Server{mux: router}
	router.GET("/", server.Root)
	router.POST("/slack/:slackAlpha/:slackBeta/:slackGamma", server.Slack)
	return server
}
Exemple #17
0
func main() {
	flag.Parse()
	addr := Host + ":" + Port

	logger.Info("botyardq", "path", DBPath, "host", Host, "port", Port)

	broker = NewBroker(DBPath)
	err := broker.Init()
	if err != nil {
		logger.Error("broker", "err", err)
		os.Exit(1)
	}

	router := httprouter.New()
	router.POST("/v1/queues/:queue", PushHandler)
	router.GET("/v1/queues/:queue", PopHandler)
	router.DELETE("/v1/queues/:queue/:id", DeleteHandler)

	logger.Info("Serving at " + addr)
	err = http.ListenAndServe(addr, router)
	if err != nil {
		log.Error("listen", "err", err)
		os.Exit(1)
	}

	logger.Info("bye")
}
Exemple #18
0
func main() {
	var mongoServer, httpBinding string
	flag.StringVar(&mongoServer, "mongoServer", "", "The connection to the mongo server")
	flag.StringVar(&dbName, "dbName", "", "The database containing the crits collections")
	flag.StringVar(&httpBinding, "httpBinding", "", "The desired HTTP binding")
	flag.Parse()

	if mongoServer == "" || dbName == "" || httpBinding == "" {
		panic("Please set mongoServer, dbName, and httpBinding!")
	}

	var err error
	session, err = mgo.Dial(mongoServer)
	if err != nil {
		panic(err)
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)

	router := httprouter.New()
	router.GET("/:id", handler)
	log.Fatal(http.ListenAndServe(httpBinding, router))

}
Exemple #19
0
func main() {
	defer shutdown.Exit()

	api := &API{}

	router := httprouter.New()
	router.POST("/databases", api.createDatabase)
	router.DELETE("/databases", api.dropDatabase)
	router.GET("/ping", api.ping)

	port := os.Getenv("PORT")
	if port == "" {
		port = "3000"
	}
	addr := ":" + port

	hb, err := discoverd.AddServiceAndRegister(serviceName+"-api", addr)
	if err != nil {
		shutdown.Fatal(err)
	}
	shutdown.BeforeExit(func() { hb.Close() })

	handler := httphelper.ContextInjector(serviceName+"-api", httphelper.NewRequestLogger(router))
	shutdown.Fatal(http.ListenAndServe(addr, handler))
}
Exemple #20
0
func run() error {
	kingpin.Parse()

	db, err := newDB()
	if err != nil {
		return errgo.Mask(err)
	}
	keyPair, err := loadKeyPair()
	if err != nil {
		return errgo.Mask(err)
	}
	service := boltstorage.NewService(db)
	handler := sfhttp.NewHandler(keyPair, service)

	r := httprouter.New()
	handler.Register(r)

	var t tomb.Tomb
	if *httpFlag != "" {
		t.Go(func() error {
			return http.ListenAndServe(*httpFlag, r)
		})
	}
	if *httpsFlag != "" && *certFlag != "" && *keyFlag != "" {
		t.Go(func() error {
			return http.ListenAndServeTLS(*httpsFlag, *certFlag, *keyFlag, r)
		})
	}

	log.Printf("public key: %s", keyPair.PublicKey.Encode())
	return t.Wait()
}
Exemple #21
0
func Listen(datadir, binding string, loglevel log.Level) error {
	var err error
	dataStore, err = helper.DefaultStore(datadir)
	if err != nil {
		return errgo.Notef(err, "can not get data store")
	}

	router := httprouter.New()

	// Router handler
	router.MethodNotAllowed = httphelper.HandlerLoggerHTTP(httphelper.PageRouterMethodNotAllowed)
	router.NotFound = httphelper.HandlerLoggerHTTP(httphelper.PageRouterNotFound)

	// Root and Favicon
	router.GET("/", httphelper.HandlerLoggerRouter(pageRoot))
	router.GET("/favicon.ico", httphelper.HandlerLoggerRouter(pageFavicon))

	// Show
	router.GET("/show/:type/", httphelper.HandlerLoggerRouter(pageShow))
	router.GET("/show/:type/:project", httphelper.HandlerLoggerRouter(pageShow))

	log.Info("Listening on ", binding)
	err = http.ListenAndServe(binding, router)
	if err != nil {
		return errgo.Notef(err, "can not listen to binding")
	}

	return nil
}
Exemple #22
0
// Create all routes and start the HTTP-server
func serveRequests() {
	router := httprouter.New()

	// Default API-message
	router.GET("/api", routes.ApiIndex)

	// API
	setupApi1(router)
	setupApi2(router)

	// Web-Frontend
	if lib.GetConfiguration().Application.UseWebFrontend {
		setupWebFrontend(router)
	} else {
		router.GET("/", routes.NoWebFrontendIndex)
	}

	// 404 Handler
	router.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "Error 404: Not Found", 404)
	})

	logging.MustGetLogger("").Debug("Listening on " + lib.GetConfiguration().Address + ":" + strconv.Itoa(lib.GetConfiguration().Port) + "...")
	logging.MustGetLogger("").Fatal(http.ListenAndServe(lib.GetConfiguration().Address+":"+strconv.Itoa(lib.GetConfiguration().Port), router))
}
Exemple #23
0
func (server *RESTServer) addRoutes() http.Handler {
	var routes = []struct {
		method  string
		route   string
		handler httprouter.Handle
	}{
		{"GET", "/", server.WelcomeHandler},
		{"HEAD", "/", server.WelcomeHandler},
		{"GET", "/jobs", server.GetJobsHandler},
		{"GET", "/jobs/:id", server.GetJobIdHandler},
		{"HEAD", "/jobs/:id", server.GetJobIdHandler},
		{"GET", "/jobs/:id/files/*path", server.GetJobIdFileHandler},
		{"HEAD", "/jobs/:id/files/*path", server.GetJobIdFileHandler},
		{"PUT", "/jobs/:id", server.PutJobIdHandler},
		{"DELETE", "/jobs/:id", server.DeleteJobIdHandler},
		{"POST", "/jobs/:id/queue", server.SubmitJobIdHandler},
		{"PUT", "/jobs/:id/files/*path", server.PutJobIdFileHandler},
		{"DELETE", "/jobs/:id/files/*path", server.DeleteJobIdFileHandler},
	}

	r := httprouter.New()
	for _, route := range routes {
		r.Handle(route.method,
			route.route,
			logWrapper(route.handler))
	}
	return r
}
Exemple #24
0
// New creates a REST API server with a given config
func New(cfg *Config) (*Server, error) {
	// pull a few parameters from the configuration passed in by snapd
	https := cfg.HTTPS
	cpath := cfg.RestCertificate
	kpath := cfg.RestKey
	s := &Server{
		err:        make(chan error),
		killChan:   make(chan struct{}),
		addrString: cfg.Address,
	}
	if https {
		var err error
		s.snapTLS, err = newtls(cpath, kpath)
		if err != nil {
			return nil, err
		}
		protocolPrefix = "https"
	}

	restLogger.Info(fmt.Sprintf("Configuring REST API with HTTPS set to: %v", https))
	s.n = negroni.New(
		NewLogger(),
		negroni.NewRecovery(),
		negroni.HandlerFunc(s.authMiddleware),
	)
	s.r = httprouter.New()
	// Use negroni to handle routes
	s.n.UseHandler(s.r)
	return s, nil
}
Exemple #25
0
func newRouter(server *Server) *httprouter.Router {
	router := httprouter.New()
	router.GET("/:pageID/count.js", server.getCountHandler)
	router.PUT("/:pageID", server.setCountHandler)
	router.GET("/", server.getStatsHandler)
	return router
}
Exemple #26
0
func init() {
	r := httprouter.New()
	http.Handle("/", r)
	r.GET("/", cover)
	r.GET("/put", handlePut)
	r.GET("/get", handleGet)
	r.GET("/list", handleList)
	r.GET("/browse", browse)
	r.GET("/newStory", newStory)
	r.GET("/newScene", newScene)
	r.GET("/user/:name", profile)
	r.GET("/login", login)
	r.GET("/signup", signup)
	r.GET("/logout", logout)
	r.GET("/editProfile", editProfile)
	r.GET("/view/:story/:owner", viewStory)
	r.POST("/api/checkemail", checkEmail)
	r.POST("/api/checkusername", checkUserName)
	r.POST("/api/login", loginProcess)
	r.POST("/api/signup", createUser)
	r.POST("/api/editProfile", editProfileProcess)
	r.POST("/api/editPassword", editPassword)
	r.POST("/api/story", newStoryProcess)
	r.POST("/api/scene", newSceneProcess)
	http.Handle("/public/", http.StripPrefix("/public", http.FileServer(http.Dir("public/"))))

	tpl = template.New("roottemplate")
	tpl = template.Must(tpl.ParseGlob("templates/*.html"))
}
Exemple #27
0
// Returns a new blank Engine instance without any middleware attached.
// The most basic configuration
func New() *Engine {
	engine := &Engine{}
	engine.RouterGroup = &RouterGroup{nil, "", nil, engine}
	engine.router = httprouter.New()
	engine.router.NotFound = engine.handle404
	return engine
}
Exemple #28
0
func init() {

	router := httprouter.New()

	router.GET("/", IndexPage)
	router.POST("/", IndexPagePost)

	router.GET("/contact/", ContactPage)
	router.POST("/contact/", ContactPagePost)

	router.GET("/register/", RegisterPage)
	router.POST("/register/", RegisterPagePost)

	router.GET("/login/", LoginPage)
	router.POST("/login/", LoginPagePost)

	router.GET("/docs/", DocsPage)

	router.GET("/api/v1/", Api)

	router.GET("/not-found/", NotFoundPage)

	router.GET("/error/", ErrorPage)

	router.ServeFiles("/assets/*filepath", http.Dir("assets"))

	router.NotFound = http.HandlerFunc(NotFoundHandler)

	log.Fatal(http.ListenAndServe(":9007", router))

}
Exemple #29
0
func BenchmarkMiddleware(b *testing.B) {
	g := New()
	g.Sub("/a", func(a *Composer) {
		a.Use().Func(func(rw http.ResponseWriter, r *http.Request) {
		})
		a.Use().Func(func(rw http.ResponseWriter, r *http.Request) {
		})
		a.Sub("/c", func(c *Composer) {
			c.Use().Func(func(rw http.ResponseWriter, r *http.Request) {
			})
			c.Use().Func(func(rw http.ResponseWriter, r *http.Request) {
			})
			c.Get("/action", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
				fmt.Fprintf(rw, "hello")
			}))
		})
	})
	routes := g.BuildRoutes()
	router := httprouter.New()
	for _, route := range routes {
		router.Handle(route.Method, route.Pattern, func(rw http.ResponseWriter, r *http.Request, params httprouter.Params) {
			route.Handler.ServeHTTP(rw, r)
		})
	}

	b.ReportAllocs()
	b.ResetTimer()
	recorder := httptest.NewRecorder()
	request, _ := http.NewRequest("GET", "/a/c/action", nil)
	for i := 0; i < b.N; i++ {
		router.ServeHTTP(recorder, request)
	}
}
Exemple #30
0
func router() *httprouter.Router {
	r := httprouter.New()

	// Set 404 handler
	r.NotFound = http.HandlerFunc(controller.Error404)

	// Serve static files, no directory browsing
	r.GET("/static/*filepath", hr.HandlerFunc(controller.Static))

	// Home page
	r.GET("/", hr.Handler(http.HandlerFunc(controller.Index)))
	//r.GET("/", hr.HandlerFunc(controller.Index))

	// Login
	r.GET("/login", hr.HandlerFunc(controller.LoginGET))
	r.POST("/login", hr.HandlerFunc(controller.LoginPOST))
	r.GET("/logout", hr.HandlerFunc(controller.Logout))

	// Register
	r.GET("/register", hr.HandlerFunc(controller.RegisterGET))
	r.POST("/register", hr.HandlerFunc(controller.RegisterPOST))

	// About
	r.GET("/about", hr.HandlerFunc(controller.AboutGET))

	// Enable Pprof
	r.GET("/debug/pprof/*pprof", pprofhandler.Handler)

	return r
}