Skip to content

Commit

Permalink
upd: move to go-kit/server, go-kit/slogger
Browse files Browse the repository at this point in the history
  • Loading branch information
LeKovr committed Jan 2, 2024
1 parent 3c445e1 commit d9ef9b9
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 193 deletions.
3 changes: 1 addition & 2 deletions Makefile.golang
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ APP_VERSION ?= $(shell git describe --tags --always)
# Last project tag (used in `make changelog`)
RELEASE ?= $(shell git describe --tags --abbrev=0 --always)
# Repository address (compiled into main.repo)
REPO ?= $(CI_REPO_CLONE_URL)
REPO ?= $(shell git config --get remote.origin.url)

GO ?= go
Expand Down Expand Up @@ -47,7 +46,7 @@ build: $(PRG_DEST)
$(PRG_DEST): $(SOURCES) go.mod
@GOOS=$${TARGETOS} GOARCH=$${TARGETARCH} CGO_ENABLED=$(CGO_ENABLED) \
$(GO) build -v -o $@ -ldflags \
"$${LDFLAGS} -X main.version=$(APP_VERSION) -X main.repo=$${REPO:-none}" \
"$${LDFLAGS} -X main.version=$(APP_VERSION) -X main.repo=$${REPO}" \
./cmd/$(PRG)

## Build & run app
Expand Down
2 changes: 1 addition & 1 deletion buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ plugins:
opt:
- paths=source_relative
- name: openapiv2
out: static/js
out: static/html/js
opt:
- output_format=json
- allow_merge=true
Expand Down
206 changes: 76 additions & 130 deletions cmd/showonce/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,49 @@ package main

import (
"context"
"errors"
"fmt"
"io/fs"
"log/slog"
"net"
"net/http"
"os"
"os/signal"
"regexp"
"strings"
"syscall"
"time"

"github.com/LeKovr/go-kit/config"
"github.com/LeKovr/go-kit/logger"
"github.com/LeKovr/go-kit/server"
"github.com/LeKovr/go-kit/slogger"
"github.com/LeKovr/go-kit/ver"

// importing implementation.
app "github.com/LeKovr/showonce"
// importing storage implementation.
"github.com/LeKovr/showonce/static"
storage "github.com/LeKovr/showonce/storage/cache"

// importing generated stubs.
gen "github.com/LeKovr/showonce/zgen/go/proto"
"github.com/dopos/narra"
"github.com/felixge/httpsnoop"
"github.com/go-logr/logr"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/soheilhy/cmux"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection"

// importing implementation.
app "github.com/LeKovr/showonce"
// importing static files.
"github.com/LeKovr/showonce/static"
// importing storage implementation.
storage "github.com/LeKovr/showonce/storage/cache"
// importing generated stubs.
gen "github.com/LeKovr/showonce/zgen/go/proto"
)

// Config holds all config vars.
type Config struct {
Listen string `default:":8080" description:"Addr and port which server listens at" long:"listen"`
ListenGRPC string `default:":8081" description:"Addr and port which GRPC pub server listens at" long:"listen_grpc"`
Root string `default:"" description:"Static files root directory" env:"ROOT" long:"root"`
PrivPrefix string `default:"/my/" description:"URI prefix for pages which requires auth" long:"priv"`
GracePeriod time.Duration `default:"10s" description:"Stop grace period" long:"grace"`

VersionPrefix string `long:"ver_prefix" default:"/js/version.js" description:"URL for version response"`
VersionFormat string `long:"ver_format" default:"document.addEventListener('DOMContentLoaded', () => { appVersion.innerHTML = '%s'; });\n" description:"Format string for version response"`
Listen string `default:":8080" description:"Addr and port which server listens at" long:"listen"`
ListenGRPC string `default:":8081" description:"Addr and port which GRPC pub server listens at" long:"listen_grpc"`
Root string `default:"" description:"Static files root directory" env:"ROOT" long:"root"`
HTMLPath string `default:"html" description:"Static site subdirectory" long:"html"`
PrivPrefix string `default:"/my/" description:"URI prefix for pages which requires auth" long:"priv"`

Logger logger.Config `env-namespace:"LOG" group:"Logging Options" namespace:"log"`
Logger slogger.Config `env-namespace:"LOG" group:"Logging Options" namespace:"log"`
AuthServer narra.Config `env-namespace:"AS" group:"Auth Service Options" namespace:"as"`
Storage storage.Config `env-namespace:"DB" group:"Storage Options" namespace:"db"`
Server server.Config `env-namespace:"SRV" group:"Server Options" namespace:"srv"`
}

const (
Expand All @@ -72,19 +66,26 @@ func Run(ctx context.Context, exitFunc func(code int)) {
// Load config
var cfg Config
err := config.Open(&cfg)
defer func() { config.Close(err, exitFunc) }()
defer func() {
if r := recover(); r != nil {
slog.Error("Recovered panic", "err", r)
}
config.Close(err, exitFunc)
}()
if err != nil {
return
}
log := logger.New(cfg.Logger, nil)
log.Info(application, "version", version)
go ver.Check(log, repo, version)
ctx = logr.NewContext(ctx, log)
err = slogger.Setup(cfg.Logger, nil)
if err != nil {
return
}
slog.Info(application, "version", version)
go ver.Check(repo, version)
db := storage.New(cfg.Storage)

Interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
// Inject logger.
return handler(logr.NewContext(ctx, log), req)
return handler(ctx, req)
}

opts := []grpc.ServerOption{
Expand All @@ -109,36 +110,38 @@ func Run(ctx context.Context, exitFunc func(code int)) {
mux := runtime.NewServeMux(
runtime.WithMetadata(func(ctx context.Context, request *http.Request) metadata.MD {
userName := request.Header.Get(cfg.AuthServer.UserHeader)
log.Info("Got PrivGRPC", "user", userName)
slog.Info("Got PrivGRPC", "user", userName)
/*
type key string
const myCustomKey key = "key"
func f(ctx context.Context) {
ctx = context.WithValue(ctx, myCustomKey, "foo")
}
*/

md := metadata.Pairs(app.MDUserKey, userName)
return md
}),
)

// static pages server
hfs, _ := static.New(cfg.Root)
fileServer := http.FileServer(hfs)
muxHTTP := http.NewServeMux()
muxHTTP.Handle("/", fileServer)

muxHTTP.HandleFunc(cfg.VersionPrefix, func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "text/javascript")
_, err := fmt.Fprintf(w, cfg.VersionFormat, version)
if err != nil {
log.Error(err, "Verion response")
}
})
var root, hfs fs.FS
if root, err = static.New(cfg.Root); err != nil {
return
}
if hfs, err = fs.Sub(root, cfg.HTMLPath); err != nil {
return
}
srv := server.New(cfg.Server).WithStatic(hfs).WithVersion(version)

// Setup OAuth
cfg.AuthServer.Do401 = true // we need redirect instead status 401
auth := narra.New(&cfg.AuthServer)
auth.SetupRoutes(muxHTTP, cfg.PrivPrefix)
auth.SetupRoutes(srv.ServeMux(), cfg.PrivPrefix)
re := regexp.MustCompile("^" + cfg.PrivPrefix)
hh := auth.ProtectMiddleware(withGW(mux, muxPub, muxHTTP), re)

ctx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
defer stop()

srv.Use(func(handler http.Handler) http.Handler {
return auth.ProtectMiddleware(withGW(mux, muxPub, srv.ServeMux()), re)
})
err = gen.RegisterPublicServiceHandlerFromEndpoint(ctx, muxPub, cfg.ListenGRPC, dialOpts)
if err != nil {
return
Expand All @@ -148,17 +151,6 @@ func Run(ctx context.Context, exitFunc func(code int)) {
if err != nil {
return
}
// Creating a normal HTTP server
srv := &http.Server{
Addr: cfg.Listen,
Handler: withReqLogger(hh),
BaseContext: func(_ net.Listener) context.Context {
return ctx
},
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}

// creating a listener for GRPC server
var listenerPub net.Listener
Expand All @@ -181,44 +173,28 @@ func Run(ctx context.Context, exitFunc func(code int)) {
// a different listener for HTTP2 since gRPC uses HTTP2
grpcL := m.Match(cmux.HTTP2())

// start servers
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
return srv.Serve(httpL)
})
g.Go(func() error {
return grpcPrivServer.Serve(grpcL)
})
g.Go(func() error {
log.V(1).Info("Start GRPC service", "addr", cfg.ListenGRPC)
return grpcPubServer.Serve(listenerPub)
})
g.Go(func() error {
log.V(1).Info("Start HTTP service", "addr", cfg.Listen)
return m.Serve()
})
g.Go(func() error {
<-gCtx.Done()
log.V(1).Info("Shutdown")
stop()
timedCtx, cancel := context.WithTimeout(ctx, cfg.GracePeriod)
defer cancel()
grpcPrivServer.GracefulStop()
grpcPubServer.GracefulStop()
return srv.Shutdown(timedCtx)
})
if er := g.Wait(); er != nil && !errors.Is(er, net.ErrClosed) {
err = er
}
log.Info("Exit")
}

// withReqLogger prints HTTP request log.
func withReqLogger(handler http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
m := httpsnoop.CaptureMetrics(handler, writer, request)
fmt.Printf("http[%d]-- %s -- %s\n", m.Code, m.Duration, request.RequestURI)
})
srv.Use(cfg.Server.WithAccessLog)
srv.WithListener(httpL)
srv.WithShutdown(
func(_ context.Context) error {
grpcPrivServer.GracefulStop()
grpcPubServer.GracefulStop()
return nil
})

err = srv.Run(ctx,
func(_ context.Context) error {
return grpcPrivServer.Serve(grpcL)
},
func(_ context.Context) error {
slog.Info("Start GRPC service", "addr", cfg.ListenGRPC)
return grpcPubServer.Serve(listenerPub)
},
func(_ context.Context) error {
slog.Info("Start HTTP service", "addr", cfg.Listen)
return m.Serve()
},
)
}

func withGW(gwmux, gwmuxPub *runtime.ServeMux, handler http.Handler) http.Handler {
Expand All @@ -243,33 +219,3 @@ func chooseClientAddr(addr string) string {
}
return addr
}

/*
type JAST interface {
SetField(name string, value interface{}) error
SetFields(name string, values []interface{}) error
}
func Setup(options ..Option) (JAST, error) {
}
main() {
app := jast.Setup(cfg).
Logger(log).
UseHTTP(true).
GRPC("/app",pubService).
GRPC("/my/app",privService).
Static(openapi).
Static(openapiUI)
//...
err = app.Serve()
)
if err == nil {
app.Run(exitFunc)
}
}
*/
22 changes: 12 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,44 @@ go 1.21.3

require (
github.com/LeKovr/go-kit/config v0.2.1
github.com/LeKovr/go-kit/logger v0.2.2
github.com/LeKovr/go-kit/ver v0.1.0
github.com/LeKovr/go-kit/server v0.12.24
github.com/LeKovr/go-kit/slogger v0.12.24
github.com/LeKovr/go-kit/ver v0.10.0
github.com/alecthomas/assert/v2 v2.4.1
github.com/dopos/narra v0.26.3
github.com/felixge/httpsnoop v1.0.4
github.com/go-logr/logr v1.3.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1
github.com/oklog/ulid/v2 v2.1.0
github.com/soheilhy/cmux v0.1.5
github.com/stretchr/testify v1.8.4
golang.org/x/sync v0.5.0
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17
google.golang.org/grpc v1.60.0
google.golang.org/protobuf v1.31.0
google.golang.org/grpc v1.60.1
google.golang.org/protobuf v1.32.0
zgo.at/zcache/v2 v2.1.0
)

require (
github.com/alecthomas/repr v0.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/zerologr v1.2.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1 // indirect
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/lmittmann/tint v1.0.3 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/zerolog v1.29.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.11.0 // indirect
Expand Down
Loading

0 comments on commit d9ef9b9

Please sign in to comment.