// package serv_http -- востроенный HTTP-сервер package serv_http import ( "fmt" "log" "os" "sync" "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cache" "github.com/gofiber/fiber/v2/middleware/compress" "github.com/gofiber/fiber/v2/utils" "github.com/gofiber/template/html/v2" "git.p78su.freemyip.com/svi/gostore/internal/serv_http/router_anonym" "git.p78su.freemyip.com/svi/gostore/pkg/types" ) // ServHttp -- встроенный HTTP-сервер type ServHttp struct { serv types.IService fiberApp *fiber.App port string store types.IStore anonym *router_anonym.RouterAnonym block sync.RWMutex isWork bool // Признак работы } // NewServHttp -- возвращает новый HTTP-сервер func NewServHttp(serv types.IService) (*ServHttp, error) { if serv == nil { return nil, fmt.Errorf("NewServHttp(): IService==nil") } port := os.Getenv("HTTP_PORT") if port == "" { return nil, fmt.Errorf("NewServHttp(): env HTTP_PORT not set") } engineTmpl := html.New("./static/tmpl", ".tmpl.html") appConf := fiber.Config{ Prefork: false, ServerHeader: "GoStore", StrictRouting: false, CaseSensitive: false, Immutable: false, UnescapePath: false, ETag: false, BodyLimit: 10_000_000, Concurrency: 0, Views: engineTmpl, ViewsLayout: "", PassLocalsToViews: false, ReadTimeout: time.Second * 60, WriteTimeout: time.Second * 60, IdleTimeout: time.Second * 10, ReadBufferSize: 0, WriteBufferSize: 0, CompressedFileSuffix: ".fiber.gz", ProxyHeader: "", GETOnly: false, // ErrorHandler: func(*fiber.Ctx, error) error { panic("not implemented") }, DisableKeepalive: false, DisableDefaultDate: false, DisableDefaultContentType: false, DisableHeaderNormalizing: false, DisableStartupMessage: false, AppName: "GoStore", StreamRequestBody: false, DisablePreParseMultipartForm: false, ReduceMemoryUsage: false, // JSONEncoder: func(interface{}) ([]byte, error) { panic("not implemented") }, // JSONDecoder: func([]byte, interface{}) error { panic("not implemented") }, // XMLEncoder: func(interface{}) ([]byte, error) { panic("not implemented") }, Network: "tcp4", EnableTrustedProxyCheck: false, TrustedProxies: []string{}, EnableIPValidation: false, EnablePrintRoutes: true, // ColorScheme: fiber.Colors{ // Black: "", // Red: "", // Green: "", // Yellow: "", // Blue: "", // Magenta: "", // Cyan: "", // White: "", // Reset: "", // }, // RequestMethods: []string{}, EnableSplittingOnParsers: false, } app := fiber.New(appConf) app.Static("/static", "./static") compressConf := compress.Config{ Level: compress.LevelBestCompression, } app.Use(compress.New(compressConf)) cacheConf := cache.Config{ Next: nil, Expiration: 30 * time.Minute, CacheHeader: "X-Cache", CacheControl: true, KeyGenerator: func(c *fiber.Ctx) string { return utils.CopyString(c.Path()) }, ExpirationGenerator: nil, StoreResponseHeaders: false, Storage: nil, MaxBytes: 0, Methods: []string{fiber.MethodGet, fiber.MethodHead}, } app.Use(cache.New(cacheConf)) sf := &ServHttp{ serv: serv, fiberApp: app, port: port, store: serv.Store(), } var err error sf.anonym, err = router_anonym.NewRouterAnonym(sf) if err != nil { return nil, err } sf.fiberApp.Get("/", sf.get) sf.serv.Wg().Add(1) sf.isWork = true go sf.close() return sf, nil } // Возвращает индексную страницу хранилища func (sf *ServHttp) get(ctx *fiber.Ctx) error { return ctx.Render("index", fiber.Map{}) } // Service -- возвращает сервис func (sf *ServHttp) Service() types.IService { return sf.serv } // FiberApp -- возвращает fiber-приложение func (sf *ServHttp) FiberApp() *fiber.App { return sf.fiberApp } // Run -- запускает веб-сервер в работу func (sf *ServHttp) Run() error { defer sf.serv.CancelApp() err := sf.fiberApp.Listen(":" + sf.port) if err != nil { return fmt.Errorf("ServHttp.Run(): in listen port(%q), err=\n\t%w", sf.port, err) } return nil } func (sf *ServHttp) close() { <-sf.serv.Ctx().Done() sf.block.Lock() defer sf.block.Unlock() if !sf.isWork { return } sf.isWork = false err := sf.fiberApp.Shutdown() if err != nil { log.Printf("ServHttp.close(): in shutdown fiberApp, err=\n\t%v\n", err) } sf.serv.Wg().Done() }