Files
lijiaoqiao/platform-token-runtime/internal/app/bootstrap.go

112 lines
2.8 KiB
Go

package app
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/jackc/pgx/v5/pgxpool"
"lijiaoqiao/platform-token-runtime/internal/auth/service"
"lijiaoqiao/platform-token-runtime/internal/httpapi"
)
type Config struct {
Addr string
Env string
RuntimeStore service.RuntimeStore
AuditStore service.AuditStore
Now func() time.Time
}
var newPostgresStoreBundle = func(ctx context.Context, databaseURL string) (service.RuntimeStore, service.AuditStore, func(), error) {
if ctx == nil {
ctx = context.Background()
}
pool, err := pgxpool.New(ctx, strings.TrimSpace(databaseURL))
if err != nil {
return nil, nil, nil, err
}
if err := pool.Ping(ctx); err != nil {
pool.Close()
return nil, nil, nil, err
}
return service.NewPostgresRuntimeStore(pool), service.NewPostgresAuditStore(pool), pool.Close, nil
}
func BuildPostgresStores(ctx context.Context, databaseURL string) (service.RuntimeStore, service.AuditStore, func(), error) {
if strings.TrimSpace(databaseURL) == "" {
return nil, nil, nil, fmt.Errorf("token runtime database url is required")
}
return newPostgresStoreBundle(ctx, databaseURL)
}
func BuildRuntime(cfg Config) (*service.InMemoryTokenRuntime, service.AuditStore, error) {
now := cfg.Now
if now == nil {
now = time.Now
}
env := strings.ToLower(strings.TrimSpace(cfg.Env))
runtimeStore := cfg.RuntimeStore
auditStore := cfg.AuditStore
switch env {
case "", "dev":
if runtimeStore == nil {
runtimeStore = service.NewInMemoryRuntimeStore()
}
if auditStore == nil {
auditStore = service.NewMemoryAuditStore()
}
case "prod", "staging":
if runtimeStore == nil {
return nil, nil, fmt.Errorf("runtime store is required in %s", env)
}
if auditStore == nil {
return nil, nil, fmt.Errorf("audit store is required in %s", env)
}
default:
return nil, nil, fmt.Errorf("unsupported TOKEN_RUNTIME_ENV %q", cfg.Env)
}
return service.NewInMemoryTokenRuntimeWithStore(now, runtimeStore), auditStore, nil
}
func BuildServer(cfg Config) (*http.Server, error) {
now := cfg.Now
if now == nil {
now = time.Now
}
addr := strings.TrimSpace(cfg.Addr)
if addr == "" {
addr = ":18081"
}
runtime, auditor, err := BuildRuntime(cfg)
if err != nil {
return nil, err
}
api := httpapi.NewTokenAPI(runtime, auditor, now)
mux := http.NewServeMux()
mux.HandleFunc("/actuator/health", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"status":"UP"}`))
})
api.Register(mux)
return &http.Server{
Addr: addr,
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 30 * time.Second,
}, nil
}