Пример #1
0
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()
}
Пример #2
0
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()
}
Пример #3
0
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()
}
Пример #4
0
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()
}