refactored totally, but now exits and doesn't serve for some reason

This commit is contained in:
Jeffrey Paul 2019-11-08 21:30:54 -08:00
parent 6c9b82a10c
commit 297b8f4e1a
5 changed files with 115 additions and 140 deletions

View File

@ -1,5 +0,0 @@
runtime: custom
env: flex
includes:
- prod-secrets.yaml

View File

@ -1,13 +1,13 @@
//3456789112345676892123456789312345678941234567895123456789612345678971234567898
package main
import "time"
import "os"
import "sync"
import "time"
import "github.com/rs/zerolog"
import "github.com/rs/zerolog/log"
import "golang.org/x/crypto/ssh/terminal"
import "github.com/sneak/merp"
import "golang.org/x/crypto/ssh/terminal"
//revive:disable
var Version string
@ -21,7 +21,16 @@ var Appname string
func main() {
initLogging()
identify()
merp.ServeForever()
var wg sync.WaitGroup
wg.Add(1)
go func() {
ms := merp.NewMerpServer()
ms.ServeForever()
wg.Done()
}()
wg.Wait()
}
func identify() {

View File

@ -1,62 +1,48 @@
package models
package merp
import "os"
import "time"
import "github.com/astaxie/beego/orm"
import "github.com/sneak/merp/models"
import "github.com/rs/zerolog/log"
import _ "github.com/lib/pq" //revive:disable-line
var ormObject orm.Ormer
func initialize() {
func GetDB() orm.Ormer {
if os.Getenv("DEBUG") != "" {
orm.Debug = true
}
connectToDb()
syncDB()
o := connectDB()
syncDB(o)
return o
}
// ConnectToDb - Initializes the ORM and Connection to the postgres DB
func connectToDb() {
func connectDB() orm.Ormer {
orm.DefaultTimeLoc = time.UTC
dbURL := os.Getenv("POSTGRES_DB_URL")
orm.RegisterDriver("postgres", orm.DRPostgres)
orm.RegisterDataBase("default", "postgres", dbURL)
orm.SetMaxIdleConns("default", 1)
orm.SetMaxOpenConns("default", 5)
orm.RegisterModel(new(Merp))
ormObject = orm.NewOrm()
ormObject.Using("default")
orm.RegisterModel(new(models.Merp))
o := orm.NewOrm()
o.Using("default")
return o
}
// SyncDB() is responsible for creating the schema in the database
func syncDB() {
func syncDB(o orm.Ormer) {
// Database alias.
name := "default"
// Drop table and re-create.
force := false
// Print log.
verbose := true
// Error.
err := orm.RunSyncdb(name, force, verbose)
if err != nil {
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
View File

@ -2,7 +2,6 @@ package merp
import "encoding/json"
import "net/http"
import "regexp"
import "time"
import "github.com/astaxie/beego/orm"
@ -11,34 +10,21 @@ import "github.com/google/uuid"
import "github.com/rs/zerolog/log"
import "github.com/sneak/merp/models"
func thingRegex() *regexp.Regexp {
ThingRegex, e := regexp.Compile(`^[a-zA-Z0-9\_\-]+$`)
if e != nil {
panic(e)
}
return ThingRegex
}
func decodeJSON(in []byte) interface{} {
func decodeJSON(in []byte) (interface{}, error) {
var out interface{}
err := json.Unmarshal(in, &out)
if err != nil {
log.Error().Msg("error decoding json")
return nil
return nil, err
}
return out
return out, nil
}
func getLatestMerps() gin.HandlerFunc {
ThingRegex := thingRegex()
o := models.GetOrmObject()
h := func(c *gin.Context) {
func (ms *MerpServer) getLatestMerps() gin.HandlerFunc {
return func(c *gin.Context) {
thing := c.Param("thing")
if thing != "" {
if ThingRegex.MatchString(thing) == false {
if ms.thingRegex.MatchString(thing) == false {
c.JSON(http.StatusPreconditionFailed, gin.H{
"this": "failed",
"status": http.StatusPreconditionFailed,
@ -50,9 +36,9 @@ func getLatestMerps() gin.HandlerFunc {
var qs orm.QuerySeter
if thing == "" {
qs = o.QueryTable("merp").OrderBy("-created").Limit(50)
qs = ms.db.QueryTable("merp").OrderBy("-created").Limit(50)
} 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
@ -62,8 +48,8 @@ func getLatestMerps() gin.HandlerFunc {
for _, merp := range merps {
outelem := make(map[string]interface{})
outelem["thing"] = merp.Thing
outjs := decodeJSON([]byte(merp.Content))
if outjs == nil {
outjs, err := decodeJSON([]byte(merp.Content))
if err != nil {
outelem["content"] = gin.H{}
} else {
outelem["content"] = outjs
@ -79,40 +65,13 @@ func getLatestMerps() gin.HandlerFunc {
"with": output,
})
}
return h
}
func getLatestMerp() gin.HandlerFunc {
ThingRegex := thingRegex()
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) {
func (ms *MerpServer) handleNewMerp() gin.HandlerFunc {
return func(c *gin.Context) {
// request time
thing := c.Param("thing")
if ThingRegex.MatchString(thing) == false {
if ms.thingRegex.MatchString(thing) == false {
c.JSON(http.StatusPreconditionFailed, gin.H{
"this": "failed",
"status": http.StatusPreconditionFailed,
@ -159,7 +118,7 @@ func handleNewMerp() gin.HandlerFunc {
UUID: u.String(),
}
_, err := orm.Insert(&merp)
_, err := ms.db.Insert(&merp)
if err != nil {
c.JSON(
@ -185,6 +144,4 @@ func handleNewMerp() gin.HandlerFunc {
},
})
}
return h
}

122
server.go
View File

@ -1,27 +1,78 @@
package merp
//3456789112345676892123456789312345678941234567895123456789612345678971234567898
import "encoding/json"
import "fmt"
import "net/http"
import "os"
import "regexp"
import "strconv"
import "time"
//import "github.com/rs/zerolog/log"
import "github.com/didip/tollbooth"
import "github.com/didip/tollbooth_gin"
import "github.com/gin-gonic/gin"
import "github.com/dn365/gin-zerolog"
import "github.com/thoas/stats"
// ServeForever causes merp to serve http forever
func ServeForever() {
s := getServer()
s.ListenAndServe()
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 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) {
result := gin.H{
"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) {
w.Header().Set("Content-Type", "application/json")
stats := middleware.Data()
stats := ms.stats.Data()
b, _ := json.Marshal(stats)
w.Write(b)
}
}
func getRouter() *gin.Engine {
if os.Getenv("DEBUG") == "" {
func (ms *MerpServer) setupRoutes() {
if !ms.debug {
gin.SetMode(gin.ReleaseMode)
}
limiter := tollbooth.NewLimiter(5, nil)
statsMiddleware := stats.New()
ms.stats = stats.New()
// empty router
r := gin.New()
@ -67,41 +117,19 @@ func getRouter() *gin.Engine {
r.Use(ginzerolog.Logger("gin"))
r.Use(func(c *gin.Context) {
beginning, recorder := statsMiddleware.Begin(c.Writer)
beginning, recorder := ms.stats.Begin(c.Writer)
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("/admin/healthcheck.json", gin.WrapF(getHealthCheckHandler()))
r.GET("/admin/stats.json", gin.WrapF(getStatsHandler(statsMiddleware)))
r.GET("/admin/other.json", gin.WrapF(getStatsHandler(statsMiddleware)))
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())
// call it, it returns the appropriate handler function
// 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
ms.gin = r
}