@@ -12,8 +12,12 @@ import (
1212 "github.com/mirkobrombin/goup/internal/logger"
1313 "github.com/mirkobrombin/goup/internal/plugin"
1414 "github.com/mirkobrombin/goup/internal/server/middleware"
15+ "github.com/mirkobrombin/goup/internal/tools"
1516 "github.com/mirkobrombin/goup/internal/tui"
1617 log "github.com/sirupsen/logrus"
18+
19+ "github.com/valyala/fasthttp"
20+ "github.com/valyala/fasthttp/fasthttpadaptor"
1721)
1822
1923var (
@@ -105,6 +109,15 @@ func StartServers(configs []config.SiteConfig, enableTUI bool, enableBench bool)
105109 }
106110}
107111
112+ func anyHasSSL (confs []config.SiteConfig ) bool {
113+ for _ , c := range confs {
114+ if c .SSL .Enabled {
115+ return true
116+ }
117+ }
118+ return false
119+ }
120+
108121// startSingleServer starts a server for a single site configuration.
109122func startSingleServer (conf config.SiteConfig , mwManager * middleware.MiddlewareManager , pm * plugin.PluginManager ) {
110123 identifier := conf .Domain
@@ -139,57 +152,143 @@ func startSingleServer(conf config.SiteConfig, mwManager *middleware.MiddlewareM
139152 return
140153 }
141154
142- server := createHTTPServer (conf , handler )
143- startServerInstance (server , conf , logger )
155+ // If SSL is enabled, keep the original net/http + quic-go approach, since
156+ // fasthttp does not support QUIC (yet?).
157+ if conf .SSL .Enabled {
158+ server := createHTTPServer (conf , handler )
159+ startServerInstance (server , conf , logger )
160+ } else {
161+ // fasthttp for all other cases.
162+ startFasthttpServer (conf , handler , logger )
163+ }
144164}
145165
146166// startVirtualHostServer starts a server that handles multiple domains on the same port.
147167func startVirtualHostServer (port int , configs []config.SiteConfig , mwManager * middleware.MiddlewareManager , pm * plugin.PluginManager ) {
148168 identifier := fmt .Sprintf ("port_%d" , port )
149169 logger := loggers [identifier ]
150170
151- radixTree := radix .New ()
171+ // If any of the sites has SSL enabled, we need to use the net/http server.
172+ if anyHasSSL (configs ) {
173+ radixTree := radix .New ()
152174
153- for _ , conf := range configs {
154- if conf .ProxyPass == "" {
155- if _ , err := os .Stat (conf .RootDirectory ); os .IsNotExist (err ) {
156- logger .Errorf ("Root directory does not exist for %s: %v" , conf .Domain , err )
175+ for _ , conf := range configs {
176+ if conf .ProxyPass == "" {
177+ if _ , err := os .Stat (conf .RootDirectory ); os .IsNotExist (err ) {
178+ logger .Errorf ("Root directory does not exist for %s: %v" , conf .Domain , err )
179+ }
180+ }
181+
182+ if err := pm .InitPluginsForSite (conf , logger ); err != nil {
183+ logger .Errorf ("Error initializing plugins for site %s: %v" , conf .Domain , err )
184+ continue
185+ }
186+
187+ mwManagerCopy := mwManager .Copy ()
188+ mwManagerCopy .Use (plugin .PluginMiddleware (pm ))
189+
190+ handler , err := createHandler (conf , logger , identifier , mwManagerCopy )
191+ if err != nil {
192+ logger .Errorf ("Error creating handler for %s: %v" , conf .Domain , err )
193+ continue
157194 }
195+
196+ radixTree .Insert (conf .Domain , handler )
158197 }
159198
160- if err := pm .InitPluginsForSite (conf , logger ); err != nil {
161- logger .Errorf ("Error initializing plugins for site %s: %v" , conf .Domain , err )
162- continue
199+ serverConf := config.SiteConfig {
200+ Port : port ,
163201 }
164202
165- mwManagerCopy := mwManager .Copy ()
166- mwManagerCopy .Use (plugin .PluginMiddleware (pm ))
203+ mainHandler := func (w_ http.ResponseWriter , r_ * http.Request ) {
204+ host := r_ .Host
205+ if colonIndex := strings .Index (host , ":" ); colonIndex != - 1 {
206+ host = host [:colonIndex ]
207+ }
167208
168- handler , err := createHandler (conf , logger , identifier , mwManagerCopy )
169- if err != nil {
170- logger .Errorf ("Error creating handler for %s: %v" , conf .Domain , err )
171- continue
209+ if handler , found := radixTree .Get (host ); found {
210+ handler .(http.Handler ).ServeHTTP (w_ , r_ )
211+ } else {
212+ http .NotFound (w_ , r_ )
213+ }
172214 }
173215
174- radixTree . Insert ( conf . Domain , handler )
175- }
216+ server := createHTTPServer ( serverConf , http . HandlerFunc ( mainHandler ) )
217+ startServerInstance ( server , serverConf , logger )
176218
177- serverConf := config.SiteConfig {
178- Port : port ,
179- }
180- mainHandler := http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
181- host := r .Host
182- if colonIndex := strings .Index (host , ":" ); colonIndex != - 1 {
183- host = host [:colonIndex ]
219+ } else {
220+ // fasthttp for all other cases.
221+ radixTree := radix .New ()
222+
223+ for _ , conf := range configs {
224+ if conf .ProxyPass == "" {
225+ if _ , err := os .Stat (conf .RootDirectory ); os .IsNotExist (err ) {
226+ logger .Errorf ("Root directory does not exist for %s: %v" , conf .Domain , err )
227+ }
228+ }
229+
230+ if err := pm .InitPluginsForSite (conf , logger ); err != nil {
231+ logger .Errorf ("Error initializing plugins for site %s: %v" , conf .Domain , err )
232+ continue
233+ }
234+
235+ mwManagerCopy := mwManager .Copy ()
236+ mwManagerCopy .Use (plugin .PluginMiddleware (pm ))
237+
238+ nethttpHandler , err := createHandler (conf , logger , identifier , mwManagerCopy )
239+ if err != nil {
240+ logger .Errorf ("Error creating handler for %s: %v" , conf .Domain , err )
241+ continue
242+ }
243+
244+ fasthttpHandler := fasthttpadaptor .NewFastHTTPHandler (nethttpHandler )
245+ radixTree .Insert (conf .Domain , fasthttpHandler )
184246 }
185247
186- if handler , found := radixTree .Get (host ); found {
187- handler .(http.Handler ).ServeHTTP (w , r )
188- } else {
189- http .NotFound (w , r )
248+ fasthttpMainHandler := func (ctx * fasthttp.RequestCtx ) {
249+ host := string (ctx .Host ())
250+ if colonIndex := strings .Index (host , ":" ); colonIndex != - 1 {
251+ host = host [:colonIndex ]
252+ }
253+
254+ if handler , found := radixTree .Get (host ); found {
255+ handler .(fasthttp.RequestHandler )(ctx )
256+ } else {
257+ ctx .SetStatusCode (fasthttp .StatusNotFound )
258+ }
259+ }
260+
261+ serverConf := config.SiteConfig {
262+ Port : port ,
263+ }
264+
265+ server := & fasthttp.Server {
266+ Handler : fasthttpMainHandler ,
267+ ReadTimeout : tools .TimeDurationOrDefault (serverConf .RequestTimeout ),
268+ WriteTimeout : tools .TimeDurationOrDefault (serverConf .RequestTimeout ),
190269 }
191- })
192270
193- server := createHTTPServer (serverConf , mainHandler )
194- startServerInstance (server , serverConf , logger )
271+ logger .Infof ("Serving on HTTP port %d with fasthttp" , port )
272+ err := server .ListenAndServe (fmt .Sprintf (":%d" , port ))
273+ if err != nil {
274+ logger .Errorf ("Fasthttp server error on port %d: %v" , port , err )
275+ }
276+ }
277+ }
278+
279+ // startFasthttpServer starts a fasthttp server for the given site configuration.
280+ func startFasthttpServer (conf config.SiteConfig , nethttpHandler http.Handler , logger * log.Logger ) {
281+ fasthttpHandler := fasthttpadaptor .NewFastHTTPHandler (nethttpHandler )
282+
283+ server := & fasthttp.Server {
284+ Handler : fasthttpHandler ,
285+ ReadTimeout : tools .TimeDurationOrDefault (conf .RequestTimeout ),
286+ WriteTimeout : tools .TimeDurationOrDefault (conf .RequestTimeout ),
287+ }
288+
289+ logger .Infof ("Serving on HTTP port %d with fasthttp" , conf .Port )
290+ err := server .ListenAndServe (fmt .Sprintf (":%d" , conf .Port ))
291+ if err != nil {
292+ logger .Errorf ("Fasthttp server error on port %d: %v" , conf .Port , err )
293+ }
195294}
0 commit comments