merp/server.go

136 lines
3.1 KiB
Go
Raw Normal View History

2019-11-08 12:35:27 +00:00
package merp
2019-10-03 19:30:04 +00:00
2019-11-07 19:19:04 +00:00
import "encoding/json"
2019-10-25 15:09:31 +00:00
import "fmt"
2019-10-25 16:17:14 +00:00
import "net/http"
2019-10-25 15:09:31 +00:00
import "os"
import "regexp"
import "strconv"
2019-10-25 16:17:14 +00:00
import "time"
2019-11-08 12:53:57 +00:00
import "github.com/didip/tollbooth"
import "github.com/didip/tollbooth_gin"
2019-10-25 16:17:14 +00:00
import "github.com/gin-gonic/gin"
import "github.com/dn365/gin-zerolog"
2019-11-08 12:35:27 +00:00
import "github.com/thoas/stats"
2019-10-03 19:30:04 +00:00
import "github.com/astaxie/beego/orm"
import _ "github.com/lib/pq" //revive:disable-line
type MerpServer struct {
db orm.Ormer
debug bool
gin *gin.Engine
port uint
server *http.Server
stats *stats.Stats
thingRegex *regexp.Regexp
}
func NewMerpServer() *MerpServer {
ms := new(MerpServer)
ms.init()
return ms
}
func (ms *MerpServer) init() {
ms.thingRegex = regexp.MustCompile(`^[a-zA-Z0-9\_\-]+$`)
if os.Getenv("DEBUG") != "" {
ms.debug = true
}
ms.port = 8080
var s uint64
var err error
if os.Getenv("PORT") != "" {
if s, err = strconv.ParseUint(os.Getenv("PORT"), 10, 64); err == nil {
} else {
panic("invalid PORT in environment")
}
ms.port = uint(s)
}
ms.connectDB()
ms.setupRoutes()
ms.server = &http.Server{
Addr: fmt.Sprintf(":%s", ms.port),
Handler: ms.gin,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
}
func (ms *MerpServer) connectDB() {
ms.db = GetDB()
}
2019-11-08 13:01:57 +00:00
// ServeForever causes merp to serve http forever
func (ms *MerpServer) ServeForever() {
ms.server.ListenAndServe()
2019-11-07 08:51:35 +00:00
}
func (ms *MerpServer) HealthCheckHandler() http.HandlerFunc {
2019-11-07 19:19:04 +00:00
return func(w http.ResponseWriter, r *http.Request) {
result := gin.H{
"status": "ok",
"now": time.Now().UTC().Format(time.RFC3339),
}
json, err := json.Marshal(result)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(json)
}
}
func (ms *MerpServer) StatsHandler() http.HandlerFunc {
2019-11-08 12:35:27 +00:00
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
stats := ms.stats.Data()
2019-11-08 12:35:27 +00:00
b, _ := json.Marshal(stats)
w.Write(b)
}
}
func (ms *MerpServer) setupRoutes() {
if !ms.debug {
2019-10-25 16:17:14 +00:00
gin.SetMode(gin.ReleaseMode)
}
2019-11-08 12:53:57 +00:00
limiter := tollbooth.NewLimiter(5, nil)
ms.stats = stats.New()
2019-11-08 12:35:27 +00:00
2019-10-25 16:17:14 +00:00
// empty router
r := gin.New()
// wrap panics:
r.Use(gin.Recovery())
// attach logger middleware
r.Use(ginzerolog.Logger("gin"))
2019-11-08 12:35:27 +00:00
r.Use(func(c *gin.Context) {
beginning, recorder := ms.stats.Begin(c.Writer)
2019-11-08 12:35:27 +00:00
c.Next()
ms.stats.End(beginning, stats.WithRecorder(recorder))
2019-11-08 12:35:27 +00:00
})
r.GET("/.well-known/healthcheck.json", gin.WrapF(ms.HealthCheckHandler()))
r.GET("/admin/healthcheck.json", gin.WrapF(ms.HealthCheckHandler()))
r.GET("/admin/stats.json", gin.WrapF(ms.StatsHandler()))
r.GET("/admin/other.json", gin.WrapF(ms.StatsHandler()))
r.GET("/merp/for/:thing", tollbooth_gin.LimitHandler(limiter), ms.handleNewMerp())
r.GET("/get/latest/merp/for/:thing", tollbooth_gin.LimitHandler(limiter), ms.getLatestMerps())
r.GET("/get/latest/merps", tollbooth_gin.LimitHandler(limiter), ms.getLatestMerps())
r.GET("/get/merps/for/:thing", tollbooth_gin.LimitHandler(limiter), ms.getLatestMerps())
2019-10-03 19:30:04 +00:00
ms.gin = r
2019-10-03 19:30:04 +00:00
}