| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- // package serv_http -- востроенный HTTP-сервер
- package serv_http
- import (
- "fmt"
- "os"
- "time"
- "github.com/gofiber/fiber/v2"
- "git.p78su.freemyip.com/svi/gostore/pkg/types"
- )
- // ServHttp -- встроенный HTTP-сервер
- type ServHttp struct {
- serv types.IService
- fiberApp *fiber.App
- port string
- login string // Логин для входа не сервер
- pass string // Пароль для входа на сервер
- mem types.IStoreMem
- disk types.IStoreDisk
- }
- // NewServHttp -- возвращает новый HTTP-сервер
- func NewServHttp(serv types.IService) (types.IServHttp, error) {
- if serv == nil {
- return nil, fmt.Errorf("NewServHttp(): IService==nil")
- }
- port := os.Getenv("STORE_HTTP_PORT")
- if port == "" {
- return nil, fmt.Errorf("NewServHttp(): env STORE_HTTP_PORT not set")
- }
- config := fiber.Config{
- Prefork: false,
- ServerHeader: "GoStore",
- StrictRouting: false,
- CaseSensitive: false,
- Immutable: false,
- UnescapePath: false,
- ETag: false,
- BodyLimit: 10_000_000,
- Concurrency: 0,
- Views: nil,
- ViewsLayout: "",
- PassLocalsToViews: false,
- ReadTimeout: time.Second * 60,
- WriteTimeout: time.Second * 60,
- IdleTimeout: time.Second * 10,
- ReadBufferSize: 0,
- WriteBufferSize: 0,
- CompressedFileSuffix: "",
- 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: false,
- // ColorScheme: fiber.Colors{
- // Black: "",
- // Red: "",
- // Green: "",
- // Yellow: "",
- // Blue: "",
- // Magenta: "",
- // Cyan: "",
- // White: "",
- // Reset: "",
- // },
- // RequestMethods: []string{},
- EnableSplittingOnParsers: false,
- }
- app := fiber.New(config)
- sf := &ServHttp{
- serv: serv,
- fiberApp: app,
- port: port,
- login: serv.User().Login(),
- pass: serv.User().Pass(),
- mem: serv.StoreMem(),
- disk: serv.StoreDisk(),
- }
- sf.fiberApp.Get("/time", sf.getTime)
- sf.fiberApp.Post("/put/:login/:pass/:key", sf.postLogin, sf.postPut)
- sf.fiberApp.Post("/get/:login/:pass/:key", sf.postLogin, sf.postGet)
- sf.fiberApp.Post("/del/:login/:pass/:key", sf.postLogin, sf.postDel)
- sf.fiberApp.Post("/find/:login/:pass/:key", sf.postLogin, sf.postFind)
- return sf, nil
- }
- type ListValRequest struct {
- Val_ []string `json:"val" form:"val"`
- }
- // postFind -- возвращает список ключей по префиксу
- func (sf *ServHttp) postFind(ctx *fiber.Ctx) error {
- key := ctx.Params("key")
- lstKey, err := sf.disk.Find(key)
- if err != nil {
- return fiber.NewError(40, "ServHttp.postFind(): in get keys by prefix from db")
- }
- return ctx.JSON(&ListValRequest{
- Val_: lstKey,
- })
- }
- type ValRequest struct {
- Val_ []byte `json:"val" form:"val"`
- }
- // postDel -- удаляет содержимое ключа
- func (sf *ServHttp) postDel(ctx *fiber.Ctx) error {
- key := ctx.Params("key")
- sf.mem.Del(key)
- sf.disk.Del(key)
- return nil
- }
- // postGet -- возвращает содержимое ключа
- func (sf *ServHttp) postGet(ctx *fiber.Ctx) error {
- key := ctx.Params("key")
- val, err := sf.mem.Get(key)
- if err == nil {
- return ctx.JSON(&ValRequest{
- Val_: val,
- })
- }
- val, err = sf.disk.Get(key)
- if err != nil {
- return fiber.NewError(30, "ServHttp.postGet(): in get val from db")
- }
- _ = sf.mem.Put(key, val)
- return ctx.JSON(&ValRequest{
- Val_: val,
- })
- }
- // postPut -- сохраняет содержимое ключа
- func (sf *ServHttp) postPut(ctx *fiber.Ctx) error {
- key := ctx.Params("key")
- req := &ValRequest{}
- if err := ctx.BodyParser(req); err != nil {
- return fiber.NewError(20, "ServHttp.postPut(): bad FORM")
- }
- _ = sf.mem.Put(key, req.Val_)
- err := sf.disk.Put(key, req.Val_)
- if err != nil {
- return fiber.NewError(21, "ServHttp.postPut(): in put val on db")
- }
- return nil
- }
- // getTime -- возвращает ответ с меткой времени (для KeepAlive)
- func (sf *ServHttp) getTime(ctx *fiber.Ctx) error {
- ctx.Response().Header.Add("Cache-Control", "no-cache") // Cache-Control: no-cache
- return ctx.SendString(time.Now().Local().String())
- }
- // 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) postLogin(ctx *fiber.Ctx) error {
- login := ctx.Params("login")
- if login != sf.login {
- return fiber.NewError(1, "ServHttp.postLogin(): bad login/pass")
- }
- pass := ctx.Params("pass")
- if pass != sf.pass {
- return fiber.NewError(2, "ServHttp.postLogin(): bad login/pass")
- }
- key := ctx.Params("key")
- if key == "" {
- return fiber.NewError(3, "ServHttp.postLogin(): key is empty")
- }
- ctx.Next()
- return nil
- }
|