| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | package httpserver | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	// stdlib | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// local | 
					
						
							| 
									
										
										
										
											2019-10-13 15:12:54 +05:00
										 |  |  | 	"go.dev.pztrn.name/giredore/internal/configuration" | 
					
						
							|  |  |  | 	"go.dev.pztrn.name/giredore/internal/logger" | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// other | 
					
						
							|  |  |  | 	"github.com/labstack/echo" | 
					
						
							|  |  |  | 	"github.com/labstack/echo/middleware" | 
					
						
							|  |  |  | 	"github.com/rs/zerolog" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	log zerolog.Logger | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Srv *echo.Echo | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func Initialize() { | 
					
						
							|  |  |  | 	log = logger.Logger.With().Str("type", "internal").Str("package", "httpserver").Logger() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	log.Info().Msg("Initializing...") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Srv = echo.New() | 
					
						
							|  |  |  | 	Srv.Use(middleware.Recover()) | 
					
						
							|  |  |  | 	Srv.Use(requestLogger()) | 
					
						
							| 
									
										
										
										
											2019-10-07 18:21:26 +05:00
										 |  |  | 	Srv.Use(checkAllowedIPs()) | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 	Srv.DisableHTTP2 = true | 
					
						
							|  |  |  | 	Srv.HideBanner = true | 
					
						
							|  |  |  | 	Srv.HidePort = true | 
					
						
							| 
									
										
										
										
											2019-10-07 18:21:26 +05:00
										 |  |  | 	Srv.Binder = echo.Binder(&StrictJSONBinder{}) | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Srv.GET("/_internal/waitForOnline", waitForHTTPServerToBeUpHandler) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Shutdown stops HTTP server. Returns true on success and false on failure. | 
					
						
							|  |  |  | func Shutdown() { | 
					
						
							|  |  |  | 	log.Info().Msg("Shutting down HTTP server...") | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 	err := Srv.Shutdown(context.Background()) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		log.Fatal().Err(err).Msg("Failed to stop HTTP server") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 	log.Info().Msg("HTTP server shutted down") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Start starts HTTP server and checks that server is ready to process | 
					
						
							|  |  |  | // requests. Returns true on success and false on failure. | 
					
						
							|  |  |  | func Start() { | 
					
						
							|  |  |  | 	log.Info().Str("address", configuration.Cfg.HTTP.Listen).Msg("Starting HTTP server...") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		err := Srv.Start(configuration.Cfg.HTTP.Listen) | 
					
						
							|  |  |  | 		if !strings.Contains(err.Error(), "Server closed") { | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 			log.Fatal().Err(err).Msg("HTTP server critical error occurred") | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check that HTTP server was started. | 
					
						
							|  |  |  | 	httpc := &http.Client{Timeout: time.Second * 1} | 
					
						
							|  |  |  | 	checks := 0 | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 	for { | 
					
						
							|  |  |  | 		checks++ | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 		if checks >= configuration.Cfg.HTTP.WaitForSeconds { | 
					
						
							|  |  |  | 			log.Fatal().Int("seconds passed", checks).Msg("HTTP server isn't up") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 		time.Sleep(time.Second * 1) | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 		resp, err := httpc.Get("http://" + configuration.Cfg.HTTP.Listen + "/_internal/waitForOnline") | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2019-10-07 21:51:45 +05:00
										 |  |  | 			log.Debug().Err(err).Msg("HTTP error occurred, HTTP server isn't ready, waiting...") | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		response, err := ioutil.ReadAll(resp.Body) | 
					
						
							|  |  |  | 		resp.Body.Close() | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			log.Debug().Err(err).Msg("Failed to read response body, HTTP server isn't ready, waiting...") | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 		log.Debug().Str("status", resp.Status).Int("body length", len(response)).Msg("HTTP response received") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if resp.StatusCode == http.StatusOK { | 
					
						
							|  |  |  | 			if len(response) == 0 { | 
					
						
							|  |  |  | 				log.Debug().Msg("Response is empty, HTTP server isn't ready, waiting...") | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 			log.Debug().Int("status code", resp.StatusCode).Msgf("Response: %+v", string(response)) | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 			if len(response) == 17 { | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	log.Info().Msg("HTTP server is ready to process requests") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func waitForHTTPServerToBeUpHandler(ec echo.Context) error { | 
					
						
							|  |  |  | 	response := map[string]string{ | 
					
						
							|  |  |  | 		"error": "None", | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-05 21:53:22 +05:00
										 |  |  | 	return ec.JSON(200, response) | 
					
						
							|  |  |  | } |