func ExampleManyRoutes() { // new router router := vestigo.NewRouter() // standard http.HandlerFunc handler := func(w http.ResponseWriter, r *http.Request) { fmt.Printf("version: %s, resource: %s\n", vestigo.Param(r, "version"), r.URL.Path) } // setup a GET /v:version/hi endpoint route in router router.Get("/v:version/hi", handler) // setup a GET /v:version/hi endpoint route in router router.Post("/v:version/hi", handler) // setup a GET /v:version/hi endpoint route in router router.Put("/v:version/hi", handler) // setup a GET /v:version/hi endpoint route in router router.Delete("/v:version/hi", handler) // setup a GET /v:version/hi endpoint route in router router.Patch("/v:version/hi", handler) // create a new request and response writer r, _ := http.NewRequest("PATCH", "/v2.3/hi", nil) w := httptest.NewRecorder() // execute the request router.ServeHTTP(w, r) // Output: version: 2.3, resource: /v2.3/hi }
func (s *server) start() error { s.client = rpcmq.NewClient("amqp://"+s.config.Rpcmq.Host+":"+s.config.Rpcmq.Port, s.config.Rpcmq.MsgQueue, s.config.Rpcmq.ReplyQueue, s.config.Rpcmq.Exchange, s.config.Rpcmq.ExchangeType) s.client.DeliveryMode = rpcmq.Transient err := s.client.Init() if err != nil { log.Fatalf("Init rpcmq: %v", err) } defer s.client.Shutdown() s.supervisor = monmq.NewSupervisor("amqp://"+s.config.Monmq.Host+":"+s.config.Monmq.Port, s.config.Monmq.ReplyQueue, s.config.Monmq.Exchange) if err := s.supervisor.Init(); err != nil { log.Fatalf("Init monmq: %v", err) } defer s.supervisor.Shutdown() if s.config.DB.Type == "mysql" { dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4,utf8", s.config.DB.Username, s.config.DB.Password, s.config.DB.Host, s.config.DB.Port, s.config.DB.Name) s.pm = persistence.NewMySQLPersistenceManager(dsn) defer s.pm.Close() } else if s.config.DB.Type == "elasticsearch" { esUrl := fmt.Sprintf("http://%s:%s", s.config.DB.Host, s.config.DB.Port) s.pm = persistence.NewElasticPersistenceManager(esUrl, s.config.DB.Name) } else { log.Fatalf("Invalid DB Type %s. Check the config", s.config.DB.Type) } m := vestigo.NewRouter() logHandler := olog.NewLogHandler(s.logger, logLine) m.Post("/tasks", orujo.NewPipe( http.HandlerFunc(s.tasksHandler), orujo.M(logHandler)).ServeHTTP, ) m.Get("/status", orujo.NewPipe( http.HandlerFunc(s.getStatusHandler), orujo.M(logHandler)).ServeHTTP, ) m.Post("/status", orujo.NewPipe( http.HandlerFunc(s.setStatusHandler), orujo.M(logHandler)).ServeHTTP, ) m.Get("/ips/:ip", orujo.NewPipe( http.HandlerFunc(s.queryHandler), orujo.M(logHandler)).ServeHTTP, ) m.Get("/ips", orujo.NewPipe( http.HandlerFunc(s.queryHandler), orujo.M(logHandler)).ServeHTTP, ) fmt.Println("Listening on " + s.config.Local.Host + ":" + s.config.Local.Port + "...") log.Fatalln(http.ListenAndServe(s.config.Local.Host+":"+s.config.Local.Port, m)) return nil }
func MarketplaceHandler() http.Handler { m := NewMarketplace() router := vestigo.NewRouter() router.SetGlobalCors(&vestigo.CorsAccessControl{ AllowOrigin: []string{"*"}, }) router.Get("/listings", Serial(m, m.SearchListings)) router.Post("/listings", Serial(m, m.CreateListing)) router.Get("/listings/:listing", Serial(m, m.GetListing)) router.Post("/listings/:listing", Serial(m, m.PatchListing)) router.Patch("/listings/:listing", Serial(m, m.PatchListing)) router.Get("/inquiries", Serial(m, m.SearchInquiries)) router.Post("/listings/:listing/inquiries", Serial(m, m.SendInquiry)) router.Handle("/", http.FileServer(http.Dir("static"))) return router }
func ExampleCorsRoute() { // new router router := vestigo.NewRouter() // setup global cors config for router router.SetGlobalCors(&vestigo.CorsAccessControl{ AllowOrigin: []string{"*", "test.com"}, // allow these origins AllowCredentials: true, // credentials is allowed globally ExposeHeaders: []string{"X-Header", "X-Y-Header"}, // Expose these headers MaxAge: 3600 * time.Second, // Cache max age AllowHeaders: []string{"X-Header", "X-Y-Header"}, // Allow these headers }) // standard http.HandlerFunc handler := func(w http.ResponseWriter, r *http.Request) {} // setup a GET/v:version/hi endpoint route in router router.Get("/v:version/hi", handler) // Setup a CORS policy for a particular route router.SetCors("/v:version/hi", &vestigo.CorsAccessControl{ AllowMethods: []string{"HEAD"}, AllowHeaders: []string{"X-Header", "X-Z-Header"}, }) // create a new request and response writer r, _ := http.NewRequest("OPTIONS", "/v2.3/hi", nil) // Initiate CORS r.Header.Add("Origin", "test.com") r.Header.Add("Access-Control-Request-Method", "HEAD") w := httptest.NewRecorder() // execute the request router.ServeHTTP(w, r) fmt.Println(w.Header().Get("Access-Control-Allow-Methods")) // Output: HEAD }
func main() { // logger setup defer glog.Flush() if glog.V(logutils.Info) { glog.Infof("Starting gonoxious client, listening on %s", ListenAddr) if glog.V(logutils.Debug) { glog.Infof("start time: %v, listen: %s, privkey: %s, pubkey: %s", time.Now(), ListenAddr, PrivKeyFileName, PubKeyFileName) } } // load up keypair, if no keypair, generate keypair // TODO: get all the crypto in place // negroni middleware setup, with custom logger n := negroni.New( negroni.NewRecovery(), logutils.NewLogMiddleware(logutils.Info), ) // setup URL router router := vestigo.NewRouter() // chat message endpoint: router.Post("/", handlers.ChatHandler) n.UseHandler(router) // graceful start/stop server srv := &graceful.Server{ Timeout: 5 * time.Second, Server: &http.Server{Addr: ListenAddr, Handler: n}, } srv.ListenAndServe() glog.Fatal("ending gonoxious") }
func (s *server) start() error { m := vestigo.NewRouter() logger := log.New(os.Stdout, "[GODAN-UI] ", log.LstdFlags) logHandler := olog.NewLogHandler(logger, logLine) m.SetGlobalCors(&vestigo.CorsAccessControl{ AllowOrigin: []string{"*"}, AllowCredentials: false, MaxAge: 3600 * time.Second, AllowHeaders: []string{"Authorization", "Content-Type"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, }) m.Get("/users/:username", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.getUserHandler)).ServeHTTP, ) m.Put("/users/:username", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.updateUserHandler)).ServeHTTP, ) m.Delete("/users/:username", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.deleteUserHandler)).ServeHTTP, ) m.Get("/users", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.getUsersHandler)).ServeHTTP, ) m.Post("/users", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.newUserHandler)).ServeHTTP, ) m.Post("/login", orujo.NewPipe( orujo.M(logHandler), http.HandlerFunc(s.loginHandler)).ServeHTTP, ) m.Post("/tasks", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.newTaskHandler)).ServeHTTP, ) m.Get("/ips/:ip", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.getIpHandler)).ServeHTTP, ) m.Get("/ips", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.getIpHandler)).ServeHTTP, ) m.Get("/status", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.getStatusHandler)).ServeHTTP, ) m.Post("/status", orujo.NewPipe( orujo.M(logHandler), s.auth, http.HandlerFunc(s.setStatusHandler)).ServeHTTP, ) fmt.Println("Listening on " + s.config.Local.Host + ":" + s.config.Local.Port + "...") log.Fatalln(http.ListenAndServe(s.config.Local.Host+":"+s.config.Local.Port, m)) return nil }
func NewServer() *vestigo.Router { protectedHandler := alice.New(session, ProtectedPage) postForm := alice.New(session, ProtectedPage, bindPost) postUser := alice.New(session, bindUser) recoverUser := alice.New(session, bindUser) postSearch := alice.New(bindSearch) postReset := alice.New(bindReset) postSettings := alice.New(session, bindSettings) sessionRedirect := alice.New(session, SessionRedirect) r := vestigo.NewRouter() r.Get("/", Homepage) r.Get("/rss", ReadFeed) r.Get("/apple-touch-icon.png", staticFile) r.Get("/favicon.ico", staticFile) r.Get("/browserconfig.xml", staticFile) r.Get("/crossdomain.xml", staticFile) r.Get("/robots.txt", staticFile) r.Get("/tile-wide.png", staticFile) r.Get("/tile.png", staticFile) r.Get("/static/*", staticResource) // Please note that `/new` route has to be before the `/:slug` route. Otherwise the program will try // to fetch for Post named "new". // For now I'll keep it this way to streamline route naming. r.Get("/posts/new", protectedHandler.ThenFunc(func(w http.ResponseWriter, r *http.Request) { render.R.HTML(w, 200, "post/new", nil) }).(http.HandlerFunc)) r.Post("/posts/new", postForm.ThenFunc(CreatePost).(http.HandlerFunc)) r.Post("/posts/search", postSearch.ThenFunc(SearchPost).(http.HandlerFunc)) r.Get("/post/:slug/edit", protectedHandler.ThenFunc(EditPost).(http.HandlerFunc)) r.Post("/post/:slug/edit", postForm.ThenFunc(UpdatePost).(http.HandlerFunc)) r.Get("/post/:slug/delete", protectedHandler.ThenFunc(DeletePost).(http.HandlerFunc)) r.Get("/post/:slug/publish", protectedHandler.ThenFunc(PublishPost).(http.HandlerFunc)) r.Get("/post/:slug/unpublish", protectedHandler.ThenFunc(UnpublishPost).(http.HandlerFunc)) r.Get("/post/:slug", ReadPost) r.Get("/user", protectedHandler.Then(http.HandlerFunc(ReadUser)).(http.HandlerFunc)) //r.HandleFunc("/delete", ProtectedPage, binding.Form(User{}), DeleteUser) r.Get("/user/settings", protectedHandler.ThenFunc(ReadSettings).(http.HandlerFunc)) r.Post("/user/settings", postSettings.ThenFunc(UpdateSettings).(http.HandlerFunc)) r.Post("/user/installation", postSettings.ThenFunc(UpdateSettings).(http.HandlerFunc)) r.Get("/user/register", sessionRedirect.ThenFunc(func(w http.ResponseWriter, r *http.Request) { render.R.HTML(w, 200, "user/register", nil) }).(http.HandlerFunc)) r.Post("/user/register", postUser.ThenFunc(CreateUser).(http.HandlerFunc)) r.Get("/user/recover", func(w http.ResponseWriter, r *http.Request) { render.R.HTML(w, 200, "user/recover", nil) }) r.Post("/user/recover", postUser.ThenFunc(RecoverUser).(http.HandlerFunc)) r.Get("/user/reset/:id/:recovery", sessionRedirect.ThenFunc(func(w http.ResponseWriter, r *http.Request) { render.R.HTML(w, 200, "user/reset", nil) }).(http.HandlerFunc)) r.Post("/user/reset/:id/:recovery", postReset.ThenFunc(ResetUserPassword).(http.HandlerFunc)) r.Get("/user/login", sessionRedirect.ThenFunc(func(w http.ResponseWriter, r *http.Request) { render.R.HTML(w, 200, "user/login", nil) }).(http.HandlerFunc)) r.Post("/user/login", recoverUser.ThenFunc(LoginUser).(http.HandlerFunc)) r.Get("/user/logout", LogoutUser) r.Get("/api", func(w http.ResponseWriter, r *http.Request) { render.R.HTML(w, 200, "api/index", nil) }) r.Get("/api/settings", protectedHandler.ThenFunc(ReadSettings).(http.HandlerFunc)) r.Post("/api/settings", postSettings.ThenFunc(UpdateSettings).(http.HandlerFunc)) r.Post("/api/installation", postSettings.ThenFunc(UpdateSettings).(http.HandlerFunc)) r.Get("/api/users", ReadUsers) r.Get("/api/users/", ReadUsers) r.Get("/api/user/logout", LogoutUser) r.Get("/api/user/:id", ReadUser) //r.Delete("/user", DeleteUser) r.Post("/api/user", postUser.ThenFunc(CreateUser).(http.HandlerFunc)) r.Post("/api/user/login", recoverUser.ThenFunc(LoginUser).(http.HandlerFunc)) r.Post("/api/user/recover", recoverUser.ThenFunc(RecoverUser).(http.HandlerFunc)) r.Post("/api/user/reset/:id/:recovery", postReset.ThenFunc(ResetUserPassword).(http.HandlerFunc)) r.Post("/api/posts/search", postSearch.ThenFunc(SearchPost).(http.HandlerFunc)) r.Get("/api/posts", ReadPosts) r.Post("/api/post", postForm.ThenFunc(CreatePost).(http.HandlerFunc)) r.Post("/api/post/:slug/edit", postForm.ThenFunc(UpdatePost).(http.HandlerFunc)) r.Get("/api/post/:slug/delete", protectedHandler.ThenFunc(DeletePost).(http.HandlerFunc)) r.Get("/api/post/:slug/publish", protectedHandler.ThenFunc(PublishPost).(http.HandlerFunc)) r.Get("/api/post/:slug/unpublish", protectedHandler.ThenFunc(UnpublishPost).(http.HandlerFunc)) r.Get("/api/post/:slug", ReadPost) return r }
func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) // Set up validation for config from our environment. envVars := map[string]*re.Regexp{ "PORT": digits, "DATABASE_URL": nows, "RELAYMSG_PG_DB": word, "RELAYMSG_PG_SCHEMA": word, "RELAYMSG_PG_USER": word, "RELAYMSG_PG_PASS": nows, "RELAYMSG_PG_MAX_CONNS": digits, "RELAYMSG_BATCH_INTERVAL": digits, "RELAYMSG_INBOUND_DOMAIN": nows, "RELAYMSG_ALLOWED_ORIGIN": nows, } // Config container cfg := map[string]string{} for k, v := range envVars { cfg[k] = os.Getenv(k) if !v.MatchString(cfg[k]) { log.Fatalf("Unsupported value for %s, double check your parameters.", k) } } // Set defaults if cfg["PORT"] == "" { cfg["PORT"] = "5000" } if cfg["RELAYMSG_BATCH_INTERVAL"] == "" { cfg["RELAYMSG_BATCH_INTERVAL"] = "10" } batchInterval, err := strconv.Atoi(cfg["RELAYMSG_BATCH_INTERVAL"]) if err != nil { log.Fatal(err) } if cfg["RELAYMSG_INBOUND_DOMAIN"] == "" { cfg["RELAYMSG_INBOUND_DOMAIN"] = "hey.avocado.industries" } if cfg["RELAYMSG_PG_MAX_CONNS"] == "" { cfg["RELAYMSG_PG_MAX_CONNS"] = "18" } maxConns, err := strconv.Atoi(cfg["RELAYMSG_PG_MAX_CONNS"]) if err != nil { log.Fatal(err) } pgcfg := &pg.PGConfig{ Db: cfg["RELAYMSG_PG_DB"], User: cfg["RELAYMSG_PG_USER"], Pass: cfg["RELAYMSG_PG_PASS"], Opts: map[string]string{ "sslmode": "disable", }, Url: cfg["DATABASE_URL"], } dbh, err := pgcfg.Connect() if err != nil { log.Fatal(err) } if maxConns > 0 { dbh.SetMaxOpenConns(maxConns) } // Configure PostgreSQL dumper with connection details. schema := cfg["RELAYMSG_PG_SCHEMA"] if schema == "" { schema = "request_dump" } pgDumper := &pg.PgDumper{Schema: schema} // make sure schema and raw_requests table exist err = pg.SchemaInit(dbh, schema) if err != nil { log.Fatal(err) } // make sure relay_messages table exists err = SchemaInit(dbh, schema) if err != nil { log.Fatal(err) } pgDumper.Dbh = dbh // Set up our handler which writes to, and reads from PostgreSQL. reqDumper := storage.HandlerFactory(pgDumper) // Set up our handler which writes individual events to PostgreSQL. msgParser := &RelayMsgParser{ Dbh: dbh, Schema: schema, Domain: cfg["RELAYMSG_INBOUND_DOMAIN"], } // recurring job to transform blobs of webhook data into relay_messages interval := time.Duration(batchInterval) * time.Second ticker := time.NewTicker(interval) go func() { for { select { case <-ticker.C: go func() { _, err := storage.ProcessBatch(pgDumper, msgParser) if err != nil { log.Printf("%s\n", err) } }() } } }() router := vestigo.NewRouter() router.SetGlobalCors(&vestigo.CorsAccessControl{ AllowOrigin: []string{cfg["RELAYMSG_ALLOWED_ORIGIN"]}, ExposeHeaders: []string{"accept"}, AllowHeaders: []string{"accept"}, }) // Install handler to store votes in database (incoming webhook events) router.Post("/incoming", reqDumper) router.Get("/summary/:localpart", msgParser.SummaryHandler()) portSpec := fmt.Sprintf(":%s", cfg["PORT"]) log.Fatal(http.ListenAndServe(portSpec, router)) }