gromer
git clone https://git.pyrossh.dev/gromer
gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.
92dca76
— Peter John
2021-11-02T16:56:50+05:30
add logging
Generated files not shown: go.sum
- cmd/wapp/main.go +10 -5
- go.mod +11 -9
- html.go +32 -5
cmd/wapp/main.go
CHANGED
|
@@ -241,7 +241,6 @@ import (
|
|
|
241
241
|
"github.com/apex/gateway/v2"
|
|
242
242
|
"github.com/gorilla/mux"
|
|
243
243
|
"github.com/pyros2097/wapp"
|
|
244
|
-
"github.com/rs/zerolog"
|
|
245
244
|
"github.com/rs/zerolog/log"
|
|
246
245
|
|
|
247
246
|
"{{ moduleName }}/context"
|
|
@@ -253,10 +252,9 @@ import (
|
|
|
253
252
|
var assetsFS embed.FS
|
|
254
253
|
|
|
255
254
|
func main() {
|
|
256
|
-
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
|
257
|
-
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
258
255
|
isLambda := os.Getenv("_LAMBDA_SERVER_PORT") != ""
|
|
259
256
|
r := mux.NewRouter()
|
|
257
|
+
r.NotFoundHandler = http.HandlerFunc(notFound)
|
|
260
258
|
r.PathPrefix("/assets/").Handler(http.FileServer(http.FS(assetsFS)))
|
|
261
259
|
{{#each routes as |route| }}handle(r, "{{ route.Method }}", "{{ route.Path }}", {{ route.Pkg }}.{{ route.Method }})
|
|
262
260
|
{{/each}}
|
|
@@ -275,15 +273,22 @@ func main() {
|
|
|
275
273
|
}
|
|
276
274
|
}
|
|
277
275
|
|
|
276
|
+
func notFound(w http.ResponseWriter, r *http.Request) {
|
|
277
|
+
wapp.LogReq(404, r)
|
|
278
|
+
}
|
|
279
|
+
|
|
278
280
|
func handle(router *mux.Router, method, route string, h interface{}) {
|
|
279
281
|
router.HandleFunc(route, func(w http.ResponseWriter, r *http.Request) {
|
|
282
|
+
var status int
|
|
283
|
+
defer func() {
|
|
280
|
-
|
|
284
|
+
wapp.LogReq(status, r)
|
|
285
|
+
}()
|
|
281
286
|
ctx, err := context.WithContext(r.Context())
|
|
282
287
|
if err != nil {
|
|
283
288
|
wapp.RespondError(w, 500, err)
|
|
284
289
|
return
|
|
285
290
|
}
|
|
286
|
-
err = wapp.PerformRequest(route, h, ctx, w, r)
|
|
291
|
+
status, err = wapp.PerformRequest(route, h, ctx, w, r)
|
|
287
292
|
if err != nil {
|
|
288
293
|
log.Error().Stack().Err(err).Msg("")
|
|
289
294
|
}
|
go.mod
CHANGED
|
@@ -3,25 +3,27 @@ module github.com/pyros2097/wapp
|
|
|
3
3
|
go 1.16
|
|
4
4
|
|
|
5
5
|
require (
|
|
6
|
-
github.com/PuerkitoBio/goquery v1.7.1 // indirect
|
|
7
|
-
github.com/apex/gateway/v2 v2.0.0
|
|
8
6
|
github.com/aymerick/raymond v2.0.2+incompatible // indirect
|
|
9
|
-
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible
|
|
7
|
+
github.com/bradleyjkemp/cupaloy v2.3.0+incompatible
|
|
8
|
+
github.com/fatih/color v1.13.0
|
|
10
|
-
github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf
|
|
9
|
+
github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf
|
|
11
|
-
github.com/gobuffalo/velvet v0.0.0-20170320144106-d97471bf5d8f
|
|
10
|
+
github.com/gobuffalo/velvet v0.0.0-20170320144106-d97471bf5d8f
|
|
12
11
|
github.com/gorilla/mux v1.8.0
|
|
13
|
-
github.com/kr/pretty v0.1.0 // indirect
|
|
14
12
|
github.com/markbates/inflect v1.0.4 // indirect
|
|
15
13
|
github.com/microcosm-cc/bluemonday v1.0.15 // indirect
|
|
14
|
+
github.com/rs/zerolog v1.26.0
|
|
16
15
|
github.com/sergi/go-diff v1.2.0 // indirect
|
|
17
16
|
github.com/shurcooL/github_flavored_markdown v0.0.0-20210228213109-c3a9aa474629 // indirect
|
|
17
|
+
github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636 // indirect
|
|
18
|
+
github.com/shurcooL/go-goon v0.0.0-20210110234559-7585751d9a17 // indirect
|
|
18
19
|
github.com/shurcooL/highlight_diff v0.0.0-20181222201841-111da2e7d480 // indirect
|
|
19
20
|
github.com/shurcooL/highlight_go v0.0.0-20191220051317-782971ddf21b // indirect
|
|
20
21
|
github.com/shurcooL/octicon v0.0.0-20191102190552-cbb32d6a785c // indirect
|
|
22
|
+
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
|
21
23
|
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect
|
|
22
24
|
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect
|
|
23
|
-
github.com/stretchr/testify v1.7.0
|
|
25
|
+
github.com/stretchr/testify v1.7.0 // indirect
|
|
24
|
-
golang.org/x/mod v0.5.1
|
|
26
|
+
golang.org/x/mod v0.5.1
|
|
25
|
-
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
|
|
27
|
+
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
|
|
26
28
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
|
27
29
|
)
|
html.go
CHANGED
|
@@ -6,14 +6,23 @@ import (
|
|
|
6
6
|
"fmt"
|
|
7
7
|
"io"
|
|
8
8
|
"net/http"
|
|
9
|
+
"os"
|
|
9
10
|
"reflect"
|
|
10
11
|
"regexp"
|
|
11
12
|
"strconv"
|
|
12
13
|
"strings"
|
|
13
14
|
|
|
15
|
+
"github.com/fatih/color"
|
|
14
16
|
"github.com/gorilla/mux"
|
|
17
|
+
"github.com/rs/zerolog"
|
|
18
|
+
"github.com/rs/zerolog/log"
|
|
15
19
|
)
|
|
16
20
|
|
|
21
|
+
func init() {
|
|
22
|
+
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
|
23
|
+
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
func writeIndent(w io.Writer, indent int) {
|
|
18
27
|
for i := 0; i < indent*2; i++ {
|
|
19
28
|
w.Write([]byte(" "))
|
|
@@ -416,7 +425,7 @@ func RespondError(w http.ResponseWriter, status int, err error) {
|
|
|
416
425
|
|
|
417
426
|
var pathParamsRegex = regexp.MustCompile(`{(.*?)}`)
|
|
418
427
|
|
|
419
|
-
func PerformRequest(route string, h interface{}, ctx interface{}, w http.ResponseWriter, r *http.Request) error {
|
|
428
|
+
func PerformRequest(route string, h interface{}, ctx interface{}, w http.ResponseWriter, r *http.Request) (int, error) {
|
|
420
429
|
params := pathParamsRegex.FindAllString(route, -1)
|
|
421
430
|
args := []reflect.Value{reflect.ValueOf(ctx)}
|
|
422
431
|
funcType := reflect.TypeOf(h)
|
|
@@ -432,7 +441,7 @@ func PerformRequest(route string, h interface{}, ctx interface{}, w http.Respons
|
|
|
432
441
|
err := json.NewDecoder(r.Body).Decode(instance.Interface())
|
|
433
442
|
if err != nil {
|
|
434
443
|
RespondError(w, 500, err)
|
|
435
|
-
return err
|
|
444
|
+
return 500, err
|
|
436
445
|
}
|
|
437
446
|
} else if r.Method == "GET" {
|
|
438
447
|
rv := instance.Elem()
|
|
@@ -452,17 +461,35 @@ func PerformRequest(route string, h interface{}, ctx interface{}, w http.Respons
|
|
|
452
461
|
responseError := values[2].Interface()
|
|
453
462
|
if responseError != nil {
|
|
454
463
|
RespondError(w, responseStatus, responseError.(error))
|
|
455
|
-
return responseError.(error)
|
|
464
|
+
return responseStatus, responseError.(error)
|
|
456
465
|
}
|
|
457
466
|
if v, ok := response.(HtmlPage); ok {
|
|
458
467
|
w.WriteHeader(responseStatus)
|
|
459
468
|
w.Header().Set("Content-Type", "text/html")
|
|
460
469
|
v.WriteHtml(w)
|
|
461
|
-
return nil
|
|
470
|
+
return 200, nil
|
|
462
471
|
}
|
|
463
472
|
w.WriteHeader(responseStatus)
|
|
464
473
|
w.Header().Set("Content-Type", "application/json")
|
|
465
474
|
data, _ := json.Marshal(response)
|
|
466
475
|
w.Write(data)
|
|
467
|
-
return nil
|
|
476
|
+
return 200, nil
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
func LogReq(status int, r *http.Request) {
|
|
480
|
+
a := color.FgGreen
|
|
481
|
+
if status >= 500 {
|
|
482
|
+
a = color.FgRed
|
|
483
|
+
} else if status >= 400 {
|
|
484
|
+
a = color.FgYellow
|
|
485
|
+
}
|
|
486
|
+
m := color.FgCyan
|
|
487
|
+
if r.Method == "POST" {
|
|
488
|
+
m = color.FgYellow
|
|
489
|
+
} else if r.Method == "PUT" {
|
|
490
|
+
m = color.FgMagenta
|
|
491
|
+
} else if r.Method == "DELETE" {
|
|
492
|
+
m = color.FgRed
|
|
493
|
+
}
|
|
494
|
+
log.Info().Msgf("%3s %s %s", color.New(a).Sprint(status), color.New(m).Sprintf("%-4s", r.Method), color.WhiteString(r.URL.Path))
|
|
468
495
|
}
|