refactored totally, but now exits and doesn't serve for some reason
This commit is contained in:
parent
6c9b82a10c
commit
297b8f4e1a
@ -1,13 +1,13 @@
|
|||||||
//3456789112345676892123456789312345678941234567895123456789612345678971234567898
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "time"
|
|
||||||
import "os"
|
import "os"
|
||||||
|
import "sync"
|
||||||
|
import "time"
|
||||||
|
|
||||||
import "github.com/rs/zerolog"
|
import "github.com/rs/zerolog"
|
||||||
import "github.com/rs/zerolog/log"
|
import "github.com/rs/zerolog/log"
|
||||||
import "golang.org/x/crypto/ssh/terminal"
|
|
||||||
import "github.com/sneak/merp"
|
import "github.com/sneak/merp"
|
||||||
|
import "golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
//revive:disable
|
//revive:disable
|
||||||
var Version string
|
var Version string
|
||||||
@ -21,7 +21,16 @@ var Appname string
|
|||||||
func main() {
|
func main() {
|
||||||
initLogging()
|
initLogging()
|
||||||
identify()
|
identify()
|
||||||
merp.ServeForever()
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
ms := merp.NewMerpServer()
|
||||||
|
ms.ServeForever()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func identify() {
|
func identify() {
|
||||||
|
@ -1,62 +1,48 @@
|
|||||||
package models
|
package merp
|
||||||
|
|
||||||
import "os"
|
import "os"
|
||||||
import "time"
|
import "time"
|
||||||
import "github.com/astaxie/beego/orm"
|
import "github.com/astaxie/beego/orm"
|
||||||
|
import "github.com/sneak/merp/models"
|
||||||
import "github.com/rs/zerolog/log"
|
import "github.com/rs/zerolog/log"
|
||||||
import _ "github.com/lib/pq" //revive:disable-line
|
import _ "github.com/lib/pq" //revive:disable-line
|
||||||
|
|
||||||
var ormObject orm.Ormer
|
func GetDB() orm.Ormer {
|
||||||
|
|
||||||
func initialize() {
|
|
||||||
if os.Getenv("DEBUG") != "" {
|
if os.Getenv("DEBUG") != "" {
|
||||||
orm.Debug = true
|
orm.Debug = true
|
||||||
}
|
}
|
||||||
|
|
||||||
connectToDb()
|
o := connectDB()
|
||||||
syncDB()
|
syncDB(o)
|
||||||
|
|
||||||
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectToDb - Initializes the ORM and Connection to the postgres DB
|
// ConnectToDb - Initializes the ORM and Connection to the postgres DB
|
||||||
func connectToDb() {
|
func connectDB() orm.Ormer {
|
||||||
|
|
||||||
orm.DefaultTimeLoc = time.UTC
|
orm.DefaultTimeLoc = time.UTC
|
||||||
|
|
||||||
dbURL := os.Getenv("POSTGRES_DB_URL")
|
dbURL := os.Getenv("POSTGRES_DB_URL")
|
||||||
|
|
||||||
orm.RegisterDriver("postgres", orm.DRPostgres)
|
orm.RegisterDriver("postgres", orm.DRPostgres)
|
||||||
orm.RegisterDataBase("default", "postgres", dbURL)
|
orm.RegisterDataBase("default", "postgres", dbURL)
|
||||||
orm.SetMaxIdleConns("default", 1)
|
orm.SetMaxIdleConns("default", 1)
|
||||||
orm.SetMaxOpenConns("default", 5)
|
orm.SetMaxOpenConns("default", 5)
|
||||||
|
orm.RegisterModel(new(models.Merp))
|
||||||
orm.RegisterModel(new(Merp))
|
o := orm.NewOrm()
|
||||||
ormObject = orm.NewOrm()
|
o.Using("default")
|
||||||
ormObject.Using("default")
|
return o
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncDB() is responsible for creating the schema in the database
|
// SyncDB() is responsible for creating the schema in the database
|
||||||
func syncDB() {
|
func syncDB(o orm.Ormer) {
|
||||||
// Database alias.
|
// Database alias.
|
||||||
name := "default"
|
name := "default"
|
||||||
|
|
||||||
// Drop table and re-create.
|
// Drop table and re-create.
|
||||||
force := false
|
force := false
|
||||||
|
|
||||||
// Print log.
|
// Print log.
|
||||||
verbose := true
|
verbose := true
|
||||||
|
|
||||||
// Error.
|
// Error.
|
||||||
err := orm.RunSyncdb(name, force, verbose)
|
err := orm.RunSyncdb(name, force, verbose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal().Msg(err.Error())
|
log.Fatal().Msg(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrmObject - Getter function for the ORM object with which we can query the database
|
|
||||||
func GetOrmObject() orm.Ormer {
|
|
||||||
if ormObject == nil {
|
|
||||||
initialize()
|
|
||||||
}
|
|
||||||
return ormObject
|
|
||||||
}
|
|
71
merp.go
71
merp.go
@ -2,7 +2,6 @@ package merp
|
|||||||
|
|
||||||
import "encoding/json"
|
import "encoding/json"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "regexp"
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
import "github.com/astaxie/beego/orm"
|
import "github.com/astaxie/beego/orm"
|
||||||
@ -11,34 +10,21 @@ import "github.com/google/uuid"
|
|||||||
import "github.com/rs/zerolog/log"
|
import "github.com/rs/zerolog/log"
|
||||||
import "github.com/sneak/merp/models"
|
import "github.com/sneak/merp/models"
|
||||||
|
|
||||||
func thingRegex() *regexp.Regexp {
|
func decodeJSON(in []byte) (interface{}, error) {
|
||||||
ThingRegex, e := regexp.Compile(`^[a-zA-Z0-9\_\-]+$`)
|
|
||||||
if e != nil {
|
|
||||||
panic(e)
|
|
||||||
}
|
|
||||||
return ThingRegex
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeJSON(in []byte) interface{} {
|
|
||||||
var out interface{}
|
var out interface{}
|
||||||
err := json.Unmarshal(in, &out)
|
err := json.Unmarshal(in, &out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Msg("error decoding json")
|
log.Error().Msg("error decoding json")
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
return out
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLatestMerps() gin.HandlerFunc {
|
func (ms *MerpServer) getLatestMerps() gin.HandlerFunc {
|
||||||
ThingRegex := thingRegex()
|
return func(c *gin.Context) {
|
||||||
o := models.GetOrmObject()
|
|
||||||
|
|
||||||
h := func(c *gin.Context) {
|
|
||||||
|
|
||||||
thing := c.Param("thing")
|
thing := c.Param("thing")
|
||||||
|
|
||||||
if thing != "" {
|
if thing != "" {
|
||||||
if ThingRegex.MatchString(thing) == false {
|
if ms.thingRegex.MatchString(thing) == false {
|
||||||
c.JSON(http.StatusPreconditionFailed, gin.H{
|
c.JSON(http.StatusPreconditionFailed, gin.H{
|
||||||
"this": "failed",
|
"this": "failed",
|
||||||
"status": http.StatusPreconditionFailed,
|
"status": http.StatusPreconditionFailed,
|
||||||
@ -50,9 +36,9 @@ func getLatestMerps() gin.HandlerFunc {
|
|||||||
|
|
||||||
var qs orm.QuerySeter
|
var qs orm.QuerySeter
|
||||||
if thing == "" {
|
if thing == "" {
|
||||||
qs = o.QueryTable("merp").OrderBy("-created").Limit(50)
|
qs = ms.db.QueryTable("merp").OrderBy("-created").Limit(50)
|
||||||
} else {
|
} else {
|
||||||
qs = o.QueryTable("merp").Filter("thing", thing).OrderBy("-created").Limit(50)
|
qs = ms.db.QueryTable("merp").Filter("thing", thing).OrderBy("-created").Limit(50)
|
||||||
}
|
}
|
||||||
|
|
||||||
var merps []*models.Merp
|
var merps []*models.Merp
|
||||||
@ -62,8 +48,8 @@ func getLatestMerps() gin.HandlerFunc {
|
|||||||
for _, merp := range merps {
|
for _, merp := range merps {
|
||||||
outelem := make(map[string]interface{})
|
outelem := make(map[string]interface{})
|
||||||
outelem["thing"] = merp.Thing
|
outelem["thing"] = merp.Thing
|
||||||
outjs := decodeJSON([]byte(merp.Content))
|
outjs, err := decodeJSON([]byte(merp.Content))
|
||||||
if outjs == nil {
|
if err != nil {
|
||||||
outelem["content"] = gin.H{}
|
outelem["content"] = gin.H{}
|
||||||
} else {
|
} else {
|
||||||
outelem["content"] = outjs
|
outelem["content"] = outjs
|
||||||
@ -79,40 +65,13 @@ func getLatestMerps() gin.HandlerFunc {
|
|||||||
"with": output,
|
"with": output,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return h
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLatestMerp() gin.HandlerFunc {
|
func (ms *MerpServer) handleNewMerp() gin.HandlerFunc {
|
||||||
ThingRegex := thingRegex()
|
return func(c *gin.Context) {
|
||||||
|
|
||||||
h := func(c *gin.Context) {
|
|
||||||
thing := c.Param("thing")
|
|
||||||
if ThingRegex.MatchString(thing) == false {
|
|
||||||
c.JSON(http.StatusPreconditionFailed, gin.H{
|
|
||||||
"this": "failed",
|
|
||||||
"status": http.StatusPreconditionFailed,
|
|
||||||
"because": "invalid thing format, try [a-zA-Z0-9-_]",
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"this": "succeeded",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleNewMerp() gin.HandlerFunc {
|
|
||||||
// server startup time
|
|
||||||
|
|
||||||
ThingRegex := thingRegex()
|
|
||||||
// establish db connection *first*, before requests
|
|
||||||
orm := models.GetOrmObject()
|
|
||||||
|
|
||||||
h := func(c *gin.Context) {
|
|
||||||
// request time
|
// request time
|
||||||
thing := c.Param("thing")
|
thing := c.Param("thing")
|
||||||
if ThingRegex.MatchString(thing) == false {
|
if ms.thingRegex.MatchString(thing) == false {
|
||||||
c.JSON(http.StatusPreconditionFailed, gin.H{
|
c.JSON(http.StatusPreconditionFailed, gin.H{
|
||||||
"this": "failed",
|
"this": "failed",
|
||||||
"status": http.StatusPreconditionFailed,
|
"status": http.StatusPreconditionFailed,
|
||||||
@ -159,7 +118,7 @@ func handleNewMerp() gin.HandlerFunc {
|
|||||||
UUID: u.String(),
|
UUID: u.String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := orm.Insert(&merp)
|
_, err := ms.db.Insert(&merp)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(
|
c.JSON(
|
||||||
@ -185,6 +144,4 @@ func handleNewMerp() gin.HandlerFunc {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return h
|
|
||||||
}
|
}
|
||||||
|
122
server.go
122
server.go
@ -1,27 +1,78 @@
|
|||||||
package merp
|
package merp
|
||||||
|
|
||||||
//3456789112345676892123456789312345678941234567895123456789612345678971234567898
|
|
||||||
|
|
||||||
import "encoding/json"
|
import "encoding/json"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "os"
|
import "os"
|
||||||
|
import "regexp"
|
||||||
|
import "strconv"
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
//import "github.com/rs/zerolog/log"
|
|
||||||
import "github.com/didip/tollbooth"
|
import "github.com/didip/tollbooth"
|
||||||
import "github.com/didip/tollbooth_gin"
|
import "github.com/didip/tollbooth_gin"
|
||||||
import "github.com/gin-gonic/gin"
|
import "github.com/gin-gonic/gin"
|
||||||
import "github.com/dn365/gin-zerolog"
|
import "github.com/dn365/gin-zerolog"
|
||||||
import "github.com/thoas/stats"
|
import "github.com/thoas/stats"
|
||||||
|
|
||||||
// ServeForever causes merp to serve http forever
|
import "github.com/astaxie/beego/orm"
|
||||||
func ServeForever() {
|
import _ "github.com/lib/pq" //revive:disable-line
|
||||||
s := getServer()
|
|
||||||
s.ListenAndServe()
|
type MerpServer struct {
|
||||||
|
db orm.Ormer
|
||||||
|
debug bool
|
||||||
|
gin *gin.Engine
|
||||||
|
port uint
|
||||||
|
server *http.Server
|
||||||
|
stats *stats.Stats
|
||||||
|
thingRegex *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHealthCheckHandler() http.HandlerFunc {
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeForever causes merp to serve http forever
|
||||||
|
func (ms *MerpServer) ServeForever() {
|
||||||
|
ms.server.ListenAndServe()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *MerpServer) HealthCheckHandler() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
result := gin.H{
|
result := gin.H{
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
@ -38,24 +89,23 @@ func getHealthCheckHandler() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatsHandler(middleware *stats.Stats) http.HandlerFunc {
|
func (ms *MerpServer) StatsHandler() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
stats := middleware.Data()
|
stats := ms.stats.Data()
|
||||||
b, _ := json.Marshal(stats)
|
b, _ := json.Marshal(stats)
|
||||||
w.Write(b)
|
w.Write(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRouter() *gin.Engine {
|
func (ms *MerpServer) setupRoutes() {
|
||||||
|
if !ms.debug {
|
||||||
if os.Getenv("DEBUG") == "" {
|
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
limiter := tollbooth.NewLimiter(5, nil)
|
limiter := tollbooth.NewLimiter(5, nil)
|
||||||
|
|
||||||
statsMiddleware := stats.New()
|
ms.stats = stats.New()
|
||||||
|
|
||||||
// empty router
|
// empty router
|
||||||
r := gin.New()
|
r := gin.New()
|
||||||
@ -67,41 +117,19 @@ func getRouter() *gin.Engine {
|
|||||||
r.Use(ginzerolog.Logger("gin"))
|
r.Use(ginzerolog.Logger("gin"))
|
||||||
|
|
||||||
r.Use(func(c *gin.Context) {
|
r.Use(func(c *gin.Context) {
|
||||||
beginning, recorder := statsMiddleware.Begin(c.Writer)
|
beginning, recorder := ms.stats.Begin(c.Writer)
|
||||||
c.Next()
|
c.Next()
|
||||||
statsMiddleware.End(beginning, stats.WithRecorder(recorder))
|
ms.stats.End(beginning, stats.WithRecorder(recorder))
|
||||||
})
|
})
|
||||||
|
|
||||||
r.GET("/.well-known/healthcheck.json", gin.WrapF(getHealthCheckHandler()))
|
r.GET("/.well-known/healthcheck.json", gin.WrapF(ms.HealthCheckHandler()))
|
||||||
r.GET("/admin/healthcheck.json", gin.WrapF(getHealthCheckHandler()))
|
r.GET("/admin/healthcheck.json", gin.WrapF(ms.HealthCheckHandler()))
|
||||||
r.GET("/admin/stats.json", gin.WrapF(getStatsHandler(statsMiddleware)))
|
r.GET("/admin/stats.json", gin.WrapF(ms.StatsHandler()))
|
||||||
r.GET("/admin/other.json", gin.WrapF(getStatsHandler(statsMiddleware)))
|
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())
|
||||||
|
|
||||||
// call it, it returns the appropriate handler function
|
ms.gin = r
|
||||||
// so we can execute some code at startup time
|
|
||||||
// and not just request time
|
|
||||||
r.GET("/merp/for/:thing", tollbooth_gin.LimitHandler(limiter), handleNewMerp())
|
|
||||||
r.GET("/get/latest/merp/for/:thing", tollbooth_gin.LimitHandler(limiter), getLatestMerp())
|
|
||||||
r.GET("/get/latest/merps", tollbooth_gin.LimitHandler(limiter), getLatestMerps())
|
|
||||||
r.GET("/get/merps/for/:thing", tollbooth_gin.LimitHandler(limiter), getLatestMerps())
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServer() *http.Server {
|
|
||||||
r := getRouter()
|
|
||||||
|
|
||||||
port := "8080"
|
|
||||||
if os.Getenv("PORT") != "" {
|
|
||||||
port = os.Getenv("PORT")
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &http.Server{
|
|
||||||
Addr: fmt.Sprintf(":%s", port),
|
|
||||||
Handler: r,
|
|
||||||
ReadTimeout: 10 * time.Second,
|
|
||||||
WriteTimeout: 10 * time.Second,
|
|
||||||
MaxHeaderBytes: 1 << 20,
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user