func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) flag.Parse() // Connect to RethinkDB var err error session, err = r.Connect(r.ConnectOpts{ Address: *rethinkAddress, }) if err != nil { log.Fatal(err) } // Create the database and tables r.DbCreate(*rethinkName).Exec(session) r.Db(*rethinkName).TableCreate("invites").Exec(session) r.Db(*rethinkName).Table("invites").IndexCreate("email").Exec(session) r.Db(*rethinkName).Table("invites").IndexCreate("name").Exec(session) // Add a CORS middleware goji.Use(cors.New(cors.Options{ AllowCredentials: true, }).Handler) // Add routes to goji goji.Get("/", index) goji.Post("/check", check) goji.Post("/free", free) goji.Post("/create", create) // Start the server goji.Serve() }
func main() { flag.Parse() var err error session, err := r.Connect(r.ConnectOpts{ Hosts: strings.Split(*rethinkdbName, ","), Database: *rethinkdbDatabase, }) if err != nil { log.Fatal(err) } goji.Get("/accounts", listAccounts) goji.Post("/accounts", createAccount) goji.Get("/accounts/:id", getAccount) goji.Put("/accounts/:id", updateAccount) goji.Delete("/accounts/:id", deleteAccount) goji.Get("/accounts/:id/tokens", listAccountTokens) goji.Delete("/accounts/:id/tokens", deleteAccountToken) goji.Get("/tokens", listTokens) goji.Post("/tokens", createToken) goji.Get("/tokens/:id", getToken) goji.Put("/tokens/:id", updateToken) goji.Delete("/tokens/:id", deleteToken) goji.Serve() }
func main() { // Add routes to the global handler goji.Get("/", Root) // Fully backwards compatible with net/http's Handlers goji.Get("/greets", http.RedirectHandler("/", 301)) // Use your favorite HTTP verbs goji.Post("/greets", NewGreet) // Use Sinatra-style patterns in your URLs goji.Get("/users/:name", GetUser) // Goji also supports regular expressions with named capture groups. goji.Get(regexp.MustCompile(`^/greets/(?P<id>\d+)$`), GetGreet) // Middleware can be used to inject behavior into your app. The // middleware for this application are defined in middleware.go, but you // can put them wherever you like. goji.Use(PlainText) // If the patterns ends with "/*", the path is treated as a prefix, and // can be used to implement sub-routes. admin := web.New() goji.Handle("/admin/*", admin) // The standard SubRouter middleware helps make writing sub-routers // easy. Ordinarily, Goji does not manipulate the request's URL.Path, // meaning you'd have to repeat "/admin/" in each of the following // routes. This middleware allows you to cut down on the repetition by // eliminating the shared, already-matched prefix. admin.Use(middleware.SubRouter) // You can also easily attach extra middleware to sub-routers that are // not present on the parent router. This one, for instance, presents a // password prompt to users of the admin endpoints. admin.Use(SuperSecure) admin.Get("/", AdminRoot) admin.Get("/finances", AdminFinances) // Goji's routing, like Sinatra's, is exact: no effort is made to // normalize trailing slashes. goji.Get("/admin", http.RedirectHandler("/admin/", 301)) // Use a custom 404 handler goji.NotFound(NotFound) // Sometimes requests take a long time. goji.Get("/waitforit", WaitForIt) // Call Serve() at the bottom of your main() function, and it'll take // care of everything else for you, including binding to a socket (with // automatic support for systemd and Einhorn) and supporting graceful // shutdown on SIGINT. Serve() is appropriate for both development and // production. goji.Serve() }
func main() { // Parse the flags flag.Parse() // Connect to RethinkDB var err error session, err = r.Connect(r.ConnectOpts{ Address: *rethinkdbAddress, }) if err != nil { log.Fatal(err) } // Set up the database r.DBCreate(*rethinkdbDatabase).Exec(session) r.DB(*rethinkdbDatabase).TableCreate("maps").Exec(session) r.DB(*rethinkdbDatabase).Table("maps").IndexCreateFunc("commitName", func(row r.Term) interface{} { return []interface{}{ row.Field("commit"), row.Field("name"), } }).Exec(session) r.DB(*rethinkdbDatabase).TableCreate("reports").Exec(session) r.DB(*rethinkdbDatabase).Table("reports").IndexCreate("version").Exec(session) // Connect to Raven rc, err := raven.NewClient(*ravenDSN, nil) if err != nil { log.Fatal(err) } // Index page goji.Get("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("lavab/lavatrace 0.1.0")) }) // Map uploading header (alloc it here so that it won't be alloc'd in each request) tokenHeader := "Bearer " + *adminToken goji.Post("/maps/:commit", func(c web.C, w http.ResponseWriter, req *http.Request) { // Check if the token is valid if header := req.Header.Get("Authorization"); header == "" || header != tokenHeader { w.WriteHeader(403) w.Write([]byte("Invalid authorization token")) return } // Decode the body var request map[string]string if err := json.NewDecoder(req.Body).Decode(&request); err != nil { w.WriteHeader(400) w.Write([]byte(err.Error())) return } // Try to get the commit hash from the URL params commit, ok := c.URLParams["commit"] if !ok { w.WriteHeader(400) w.Write([]byte("Invalid commit ID")) return } // Insert every map into the database for key, value := range request { if err := r.DB(*rethinkdbDatabase).Table("maps").Insert(&Map{ ID: uniuri.NewLen(uniuri.UUIDLen), Commit: commit, Name: key, Body: value, }).Exec(session); err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } } // Return some dumb text w.Write([]byte("Success")) return }) // Report - registers a new event goji.Post("/report", func(w http.ResponseWriter, req *http.Request) { // Parse the request body var report *models.Report if err := json.NewDecoder(req.Body).Decode(&report); err != nil { w.WriteHeader(400) w.Write([]byte(err.Error())) return } // Prepare a new packet packet := &raven.Packet{ Interfaces: []raven.Interface{}, Platform: "javascript", Release: report.CommitID, } lo := &models.Log{ CommitID: report.CommitID, Version: report.Version, Assets: report.Assets, Entries: []*models.LogEntry{}, } // Transform entries into exceptions for _, entry := range report.Entries { // Prepare a new Entry en := &models.LogEntry{ Date: entry.Date, Type: entry.Type, Message: entry.Message, Objects: entry.Objects, Frames: []*models.LogFrame{}, } // Stacktrace is a string with format: // fileIndex:line:column for _, part := range strings.Split(entry.Stacktrace, ";") { // Parse each call call := strings.Split(part, ":") if len(call) < 3 { w.WriteHeader(400) w.Write([]byte("Invalid stacktrace")) return } // Integer parsing helper err = nil mustParse := func(input string) int { if err == nil { x, e := strconv.Atoi(input) if e != nil { err = e return 0 } return x } return 0 } // Parse the fields var ( fileIndex = call[0] lineNo = mustParse(call[1]) columnNo = mustParse(call[2]) ) // First case - we don't know the source switch fileIndex { case "/": en.Frames = append(en.Frames, &models.LogFrame{ Filename: "unknown", Name: "unknown", LineNo: lineNo, ColNo: columnNo, InApp: true, }) case "native": en.Frames = append(en.Frames, &models.LogFrame{ Filename: "native", Name: "native", LineNo: lineNo, ColNo: columnNo, InApp: false, }) default: // Convert file index to an int fii, err := strconv.Atoi(fileIndex) if err != nil { w.WriteHeader(400) w.Write([]byte(err.Error())) return } // Map index to file path if len(report.Assets) < fii+1 { w.WriteHeader(400) w.Write([]byte("Invalid asset ID")) return } asset := report.Assets[fii] // Get the asset's filename filename := path.Base(asset) + ".map" // Map the data mapping, err := getMapping(report.CommitID, filename, lineNo, columnNo) if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } // Append it to the stacktrace en.Frames = append(en.Frames, &models.LogFrame{ Filename: mapping.OriginalFile, Name: mapping.OriginalName, LineNo: mapping.OriginalLine, ColNo: mapping.OriginalColumn, InApp: true, AbsPath: asset, }) } } // Put entry into entries lo.Entries = append(lo.Entries, en) } // Append the Log to interfaces packet.Interfaces = append(packet.Interfaces, lo) // Set the culprit and message lastEntry := lo.Entries[len(lo.Entries)-1] lastFrame := lastEntry.Frames[len(lastEntry.Frames)-1] packet.Culprit = lastFrame.Name + "@" + strconv.Itoa(lastFrame.LineNo) + ":" + strconv.Itoa(lastFrame.ColNo) packet.Message = lastEntry.Message // Send the packet to Sentry eid, ch := rc.Capture(packet, nil) err = <-ch if err != nil { w.WriteHeader(500) w.Write([]byte(err.Error())) return } w.Write([]byte(eid)) return }) // Print out the current admin token log.Printf("Current admin token is %s", *adminToken) // Start the server goji.Serve() }