/
server.go
125 lines (102 loc) · 3.7 KB
/
server.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
package http
import (
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
cors2 "github.com/go-chi/cors"
"github.com/go-chi/render"
"github.com/riandyrn/otelchi"
"github.com/spf13/viper"
"golang.org/x/sync/errgroup"
"google.golang.org/protobuf/encoding/protojson"
serverAPI "github.com/shortlink-org/shortlink/boundaries/api/bff-web/infrastructure/http/api"
"github.com/shortlink-org/shortlink/boundaries/api/bff-web/infrastructure/http/controllers/cqrs"
"github.com/shortlink-org/shortlink/boundaries/api/bff-web/infrastructure/http/controllers/link"
"github.com/shortlink-org/shortlink/boundaries/api/bff-web/infrastructure/http/controllers/sitemap"
"github.com/shortlink-org/shortlink/pkg/http/handler"
auth_middleware "github.com/shortlink-org/shortlink/pkg/http/middleware/auth"
logger_middleware "github.com/shortlink-org/shortlink/pkg/http/middleware/logger"
metrics_middleware "github.com/shortlink-org/shortlink/pkg/http/middleware/metrics"
pprof_labels_middleware "github.com/shortlink-org/shortlink/pkg/http/middleware/pprof_labels"
span_middleware "github.com/shortlink-org/shortlink/pkg/http/middleware/span"
http_server "github.com/shortlink-org/shortlink/pkg/http/server"
)
const MAX_AGE = 300
// Run HTTP-server
func (api *Server) run(config http_server.Config, params Config) error {
viper.SetDefault("BASE_PATH", "/api") // Base path for API endpoints
api.ctx = params.Ctx
api.jsonpb = protojson.MarshalOptions{
UseProtoNames: true,
}
r := chi.NewRouter()
// CORS
cors := cors2.New(cors2.Options{
AllowedOrigins: []string{"*"},
AllowedMethods: []string{"GET", "POST", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
ExposedHeaders: []string{""},
AllowCredentials: true,
MaxAge: MAX_AGE,
})
r.Use(cors.Handler)
r.Use(render.SetContentType(render.ContentTypeJSON))
// A good base middleware stack
r.Use(middleware.RealIP)
r.Use(middleware.Heartbeat("/healthz"))
r.Use(middleware.Recoverer)
r.Use(middleware.SetHeader("Content-Type", "application/json"))
// Set a timeout value on the request context (ctx), that will signal
// through ctx.Done() that the request has timed out and further
// processing should be stopped.
r.Use(middleware.Timeout(config.Timeout))
// Additional middleware
r.Use(otelchi.Middleware(viper.GetString("SERVICE_NAME")))
r.Use(logger_middleware.Logger(params.Log))
r.Use(auth_middleware.Auth())
r.Use(pprof_labels_middleware.Labels)
r.Use(span_middleware.Span())
// Metrics
metrics, err := metrics_middleware.NewMetrics()
if err != nil {
return err
}
r.Use(metrics)
r.NotFound(handler.NotFoundHandler)
// Init routes
controller := &Controller{
link.NewController(params.Log, params.Link_rpc),
cqrs.LinkCQRSController{
LinkCommandServiceClient: params.Link_command,
LinkQueryServiceClient: params.Link_query,
},
sitemap.SitemapController{
SitemapServiceClient: params.Sitemap_rpc,
},
}
r.Mount(viper.GetString("BASE_PATH"), serverAPI.HandlerFromMux(controller, r))
srv := http_server.New(params.Ctx, r, config, params.Tracer)
// start HTTP-server
params.Log.Info(params.I18n.Sprintf("BFF Web run on port %d", config.Port))
err = srv.ListenAndServe()
if err != nil {
return err
}
return nil
}
// New API Provider for DI
func New(params Config) (*Server, error) {
// API port
viper.SetDefault("API_PORT", 7070) //nolint:gomnd
// Request Timeout (seconds)
viper.SetDefault("API_TIMEOUT", "60s")
config := http_server.Config{
Port: viper.GetInt("API_PORT"),
Timeout: viper.GetDuration("API_TIMEOUT"),
}
api := &Server{}
g := errgroup.Group{}
g.Go(func() error {
return api.run(config, params)
})
return api, nil
}