-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.go
151 lines (121 loc) · 3.92 KB
/
app.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package app
import (
"context"
"errors"
"log"
"net/http"
"time"
"github.com/go-chi/chi"
authz "github.com/wurt83ow/gophkeeper-server/internal/authorization"
"github.com/wurt83ow/gophkeeper-server/internal/bdkeeper"
"github.com/wurt83ow/gophkeeper-server/internal/config"
"github.com/wurt83ow/gophkeeper-server/internal/controllers"
"github.com/wurt83ow/gophkeeper-server/internal/logger"
"github.com/wurt83ow/gophkeeper-server/internal/middleware"
"github.com/wurt83ow/gophkeeper-server/internal/storage"
)
// Server represents the application server.
type Server struct {
srv *http.Server
ctx context.Context
}
// NewServer creates a new Server instance.
func NewServer(ctx context.Context) *Server {
server := new(Server)
server.ctx = ctx
return server
}
// Serve starts the server.
func (server *Server) Serve() {
// Create and initialize a new option instance
option := config.NewOptions()
option.ParseFlags()
// Get a new logger
nLogger, err := logger.NewLogger(option.LogLevel())
if err != nil {
log.Fatalln(err)
}
// Initialize the keeper instance
keeper, err := initializeKeeper(option.DataBaseDSN, nLogger)
if err != nil {
log.Fatalln(err)
}
defer keeper.Close()
// Initialize the storage instance
memoryStorage := initializeStorage(keeper, nLogger)
authz := authz.NewJWTAuthz(option.JWTSigningKey(), nLogger)
// Create a new controller to process incoming requests
baseController := initializeBaseController(memoryStorage, option, nLogger, authz)
// Create an instance of ChiServerOptions with your middleware
options := controllers.ChiServerOptions{
Middlewares: []controllers.MiddlewareFunc{
authz.JWTAuthzMiddleware(memoryStorage, nLogger),
},
}
// Create a handler with options
genHandler := controllers.HandlerWithOptions(baseController, options)
// Get a middleware for logging requests
reqLog := middleware.NewReqLog(nLogger)
// Create router and mount routes
r := chi.NewRouter()
r.Use(reqLog.RequestLogger)
r.Mount("/", genHandler)
// Configure and start the server
startServer(server, r, option.RunAddr(), option.EnableHTTPS(),
option.HTTPSCertFile(), option.HTTPSKeyFile())
}
func initializeKeeper(dataBaseDSN func() string, logger *logger.Logger) (*bdkeeper.BDKeeper, error) {
return bdkeeper.NewBDKeeper(dataBaseDSN, logger, nil)
}
func initializeStorage(keeper storage.Keeper, logger *logger.Logger) *storage.MemoryStorage {
if keeper == nil {
return nil
}
return storage.NewMemoryStorage(keeper, logger)
}
func initializeBaseController(storage *storage.MemoryStorage, options *config.Options,
logger *logger.Logger, authz *authz.JWTAuthz,
) *controllers.BaseController {
return controllers.NewBaseController(storage, options, logger, authz)
}
func startServer(server *Server, router chi.Router, address string,
enableHTTPS bool, HTTPSCertFile, HTTPSKeyFile string) {
const (
oneMegabyte = 1 << 20
readTimeout = 3 * time.Second
)
server.srv = &http.Server{
Addr: address,
Handler: router,
ReadHeaderTimeout: readTimeout,
WriteTimeout: readTimeout,
IdleTimeout: readTimeout,
MaxHeaderBytes: oneMegabyte, // 1 MB
}
log.Printf("Starting server at %s\n", address)
// Start the HTTP/HTTPS server
var err error
if enableHTTPS {
log.Printf("HTTPS enabled")
err = server.srv.ListenAndServeTLS(HTTPSCertFile, HTTPSKeyFile)
} else {
log.Printf("HTTPS disabled")
err = server.srv.ListenAndServe()
}
if err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalln(err)
}
}
// Shutdown gracefully shuts down the server.
func (server *Server) Shutdown() {
log.Printf("server stopped")
const shutdownTimeout = 5 * time.Second
ctxShutDown, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
defer cancel()
if err := server.srv.Shutdown(ctxShutDown); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("server Shutdown Failed:%s", err)
}
}
log.Println("server exited properly")
}