forked from urdt/ussd
		
	Merge remote-tracking branch 'remotes/origin/master' into wip-code-check
This commit is contained in:
		
						commit
						c2d2bd250a
					
				
							
								
								
									
										215
									
								
								cmd/http/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								cmd/http/main.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,215 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"path" | ||||
| 	"strconv" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"git.defalsify.org/vise.git/asm" | ||||
| 	"git.defalsify.org/vise.git/db" | ||||
| 	fsdb "git.defalsify.org/vise.git/db/fs" | ||||
| 	gdbmdb "git.defalsify.org/vise.git/db/gdbm" | ||||
| 	"git.defalsify.org/vise.git/engine" | ||||
| 	"git.defalsify.org/vise.git/resource" | ||||
| 	"git.defalsify.org/vise.git/logging" | ||||
| 
 | ||||
| 	"git.grassecon.net/urdt/ussd/internal/handlers/ussd" | ||||
| 	httpserver "git.grassecon.net/urdt/ussd/internal/http" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	logg = logging.NewVanilla() | ||||
| 	scriptDir = path.Join("services", "registration") | ||||
| ) | ||||
| 
 | ||||
| func getFlags(fp string, debug bool) (*asm.FlagParser, error) { | ||||
| 	flagParser := asm.NewFlagParser().WithDebug() | ||||
| 	_, err := flagParser.Load(fp) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return flagParser, nil | ||||
| } | ||||
| 
 | ||||
| func getHandler(appFlags *asm.FlagParser, rs *resource.DbResource, userdataStore db.Db) (*ussd.Handlers, error) { | ||||
| 
 | ||||
| 	ussdHandlers, err := ussd.NewHandlers(appFlags, userdataStore) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	rs.AddLocalFunc("select_language", ussdHandlers.SetLanguage) | ||||
| 	rs.AddLocalFunc("create_account", ussdHandlers.CreateAccount) | ||||
| 	rs.AddLocalFunc("save_pin", ussdHandlers.SavePin) | ||||
| 	rs.AddLocalFunc("verify_pin", ussdHandlers.VerifyPin) | ||||
| 	rs.AddLocalFunc("check_identifier", ussdHandlers.CheckIdentifier) | ||||
| 	rs.AddLocalFunc("check_account_status", ussdHandlers.CheckAccountStatus) | ||||
| 	rs.AddLocalFunc("authorize_account", ussdHandlers.Authorize) | ||||
| 	rs.AddLocalFunc("quit", ussdHandlers.Quit) | ||||
| 	rs.AddLocalFunc("check_balance", ussdHandlers.CheckBalance) | ||||
| 	rs.AddLocalFunc("validate_recipient", ussdHandlers.ValidateRecipient) | ||||
| 	rs.AddLocalFunc("transaction_reset", ussdHandlers.TransactionReset) | ||||
| 	rs.AddLocalFunc("max_amount", ussdHandlers.MaxAmount) | ||||
| 	rs.AddLocalFunc("validate_amount", ussdHandlers.ValidateAmount) | ||||
| 	rs.AddLocalFunc("reset_transaction_amount", ussdHandlers.ResetTransactionAmount) | ||||
| 	rs.AddLocalFunc("get_recipient", ussdHandlers.GetRecipient) | ||||
| 	rs.AddLocalFunc("get_sender", ussdHandlers.GetSender) | ||||
| 	rs.AddLocalFunc("get_amount", ussdHandlers.GetAmount) | ||||
| 	rs.AddLocalFunc("reset_incorrect", ussdHandlers.ResetIncorrectPin) | ||||
| 	rs.AddLocalFunc("save_firstname", ussdHandlers.SaveFirstname) | ||||
| 	rs.AddLocalFunc("save_familyname", ussdHandlers.SaveFamilyname) | ||||
| 	rs.AddLocalFunc("save_gender", ussdHandlers.SaveGender) | ||||
| 	rs.AddLocalFunc("save_location", ussdHandlers.SaveLocation) | ||||
| 	rs.AddLocalFunc("save_yob", ussdHandlers.SaveYob) | ||||
| 	rs.AddLocalFunc("save_offerings", ussdHandlers.SaveOfferings) | ||||
| 	rs.AddLocalFunc("quit_with_balance", ussdHandlers.QuitWithBalance) | ||||
| 	rs.AddLocalFunc("reset_account_authorized", ussdHandlers.ResetAccountAuthorized) | ||||
| 	rs.AddLocalFunc("reset_allow_update", ussdHandlers.ResetAllowUpdate) | ||||
| 	rs.AddLocalFunc("get_profile_info", ussdHandlers.GetProfileInfo) | ||||
| 	rs.AddLocalFunc("verify_yob", ussdHandlers.VerifyYob) | ||||
| 	rs.AddLocalFunc("reset_incorrect_date_format", ussdHandlers.ResetIncorrectYob) | ||||
| 	rs.AddLocalFunc("set_reset_single_edit", ussdHandlers.SetResetSingleEdit) | ||||
| 	rs.AddLocalFunc("initiate_transaction", ussdHandlers.InitiateTransaction) | ||||
| 
 | ||||
| 	return ussdHandlers, nil | ||||
| } | ||||
| 
 | ||||
| func ensureDbDir(dbDir string) error { | ||||
| 	err := os.MkdirAll(dbDir, 0700) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("state dir create exited with error: %v\n", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func getStateStore(dbDir string, ctx context.Context) (db.Db, error) { | ||||
| 	store := gdbmdb.NewGdbmDb() | ||||
| 	storeFile := path.Join(dbDir, "state.gdbm") | ||||
| 	store.Connect(ctx, storeFile) | ||||
| 	return store, nil | ||||
| } | ||||
| 
 | ||||
| func getUserdataDb(dbDir string, ctx context.Context) db.Db { | ||||
| 	store := gdbmdb.NewGdbmDb() | ||||
| 	storeFile := path.Join(dbDir, "userdata.gdbm") | ||||
| 	store.Connect(ctx, storeFile) | ||||
| 	 | ||||
| 	return store | ||||
| } | ||||
| 
 | ||||
| func getResource(resourceDir string, ctx context.Context) (resource.Resource, error) { | ||||
| 	store := fsdb.NewFsDb() | ||||
| 	err := store.Connect(ctx, resourceDir) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	rfs := resource.NewDbResource(store) | ||||
| 	return rfs, nil | ||||
| } | ||||
| 
 | ||||
| func main() { | ||||
| 	var dbDir string | ||||
| 	var resourceDir string | ||||
| 	var size uint | ||||
| 	var engineDebug bool | ||||
| 	var stateDebug bool | ||||
| 	var host string | ||||
| 	var port uint | ||||
| 	flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") | ||||
| 	flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") | ||||
| 	flag.BoolVar(&engineDebug, "engine-debug", false, "use engine debug output") | ||||
| 	flag.BoolVar(&stateDebug, "state-debug", false, "use engine debug output") | ||||
| 	flag.UintVar(&size, "s", 160, "max size of output") | ||||
| 	flag.StringVar(&host, "h", "127.0.0.1", "http host") | ||||
| 	flag.UintVar(&port, "p", 7123, "http port") | ||||
| 	flag.Parse() | ||||
| 
 | ||||
| 	logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir,  "outputsize", size) | ||||
| 
 | ||||
| 	ctx := context.Background() | ||||
| 	pfp := path.Join(scriptDir, "pp.csv") | ||||
| 	flagParser, err := getFlags(pfp, true) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	cfg := engine.Config{ | ||||
| 		Root:       "root", | ||||
| 		OutputSize: uint32(size), | ||||
| 		FlagCount:  uint32(16), | ||||
| 	} | ||||
| 	if stateDebug { | ||||
| 		cfg.StateDebug = true | ||||
| 	} | ||||
| 	if engineDebug { | ||||
| 		cfg.EngineDebug = true | ||||
| 	} | ||||
| 
 | ||||
| 	rs, err := getResource(resourceDir, ctx) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	err = ensureDbDir(dbDir) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	userdataStore := getUserdataDb(dbDir, ctx) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 	defer userdataStore.Close() | ||||
| 
 | ||||
| 	dbResource, ok := rs.(*resource.DbResource) | ||||
| 	if !ok { | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	hl, err := getHandler(flagParser, dbResource, userdataStore) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	stateStore, err := getStateStore(dbDir, ctx) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 	defer stateStore.Close() | ||||
| 
 | ||||
| 	rp := &httpserver.DefaultRequestParser{} | ||||
| 	//sh := httpserver.NewSessionHandler(cfg, rs, stateStore, userdataStore, rp, hl.Init)
 | ||||
| 	sh := httpserver.NewSessionHandler(cfg, rs, stateStore, userdataStore, rp, hl) | ||||
| 	s := &http.Server{ | ||||
| 		Addr: fmt.Sprintf("%s:%s", host, strconv.Itoa(int(port))), | ||||
| 		Handler: sh, | ||||
| 	} | ||||
| 	s.RegisterOnShutdown(sh.Shutdown) | ||||
| 
 | ||||
| 	cint := make(chan os.Signal) | ||||
| 	cterm := make(chan os.Signal) | ||||
| 	signal.Notify(cint, os.Interrupt, syscall.SIGINT) | ||||
| 	signal.Notify(cterm, os.Interrupt, syscall.SIGTERM) | ||||
| 	go func() { | ||||
| 		select { | ||||
| 		case _ = <-cint: | ||||
| 		case _ = <-cterm: | ||||
| 		} | ||||
| 		s.Shutdown(ctx) | ||||
| 	}() | ||||
| 	err = s.ListenAndServe() | ||||
| 	if err != nil { | ||||
| 		logg.Infof("Server closed with error", "err", err) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										22
									
								
								cmd/main.go
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								cmd/main.go
									
									
									
									
									
								
							| @ -34,10 +34,11 @@ func getParser(fp string, debug bool) (*asm.FlagParser, error) { | ||||
| 
 | ||||
| func getHandler(appFlags *asm.FlagParser, rs *resource.DbResource, pe *persist.Persister, userdataStore db.Db) (*ussd.Handlers, error) { | ||||
| 
 | ||||
| 	ussdHandlers, err := ussd.NewHandlers(appFlags, pe, userdataStore) | ||||
| 	ussdHandlers, err := ussd.NewHandlers(appFlags, userdataStore) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	ussdHandlers = ussdHandlers.WithPersister(pe) | ||||
| 	rs.AddLocalFunc("select_language", ussdHandlers.SetLanguage) | ||||
| 	rs.AddLocalFunc("create_account", ussdHandlers.CreateAccount) | ||||
| 	rs.AddLocalFunc("save_pin", ussdHandlers.SavePin) | ||||
| @ -74,10 +75,18 @@ func getHandler(appFlags *asm.FlagParser, rs *resource.DbResource, pe *persist.P | ||||
| 	return ussdHandlers, nil | ||||
| } | ||||
| 
 | ||||
| func getPersister(dbDir string, ctx context.Context) (*persist.Persister, error) { | ||||
| func ensureDbDir(dbDir string) error { | ||||
| 	err := os.MkdirAll(dbDir, 0700) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("state dir create exited with error: %v\n", err) | ||||
| 		return fmt.Errorf("state dir create exited with error: %v\n", err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func getPersister(dbDir string, ctx context.Context) (*persist.Persister, error) { | ||||
| 	err := ensureDbDir(dbDir) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	store := gdbmdb.NewGdbmDb() | ||||
| 	storeFile := path.Join(dbDir, "state.gdbm") | ||||
| @ -145,7 +154,7 @@ func main() { | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	pr, err := getPersister(dbDir, ctx) | ||||
| 	pe, err := getPersister(dbDir, ctx) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| @ -159,16 +168,17 @@ func main() { | ||||
| 
 | ||||
| 	dbResource, ok := rs.(*resource.DbResource) | ||||
| 	if !ok { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	hl, err := getHandler(flagParser, dbResource, pr, store) | ||||
| 	hl, err := getHandler(flagParser, dbResource, pe, store) | ||||
| 	if err != nil { | ||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| 
 | ||||
| 	en := getEngine(cfg, rs, pr) | ||||
| 	en := getEngine(cfg, rs, pe) | ||||
| 	en = en.WithFirst(hl.Init) | ||||
| 	if debug { | ||||
| 		en = en.WithDebug(nil) | ||||
|  | ||||
							
								
								
									
										13
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								go.mod
									
									
									
									
									
								
							| @ -2,6 +2,12 @@ module git.grassecon.net/urdt/ussd | ||||
| 
 | ||||
| go 1.22.6 | ||||
| 
 | ||||
| require ( | ||||
| 	git.defalsify.org/vise.git v0.1.0-rc.3.0.20240911162138-1f2af8672dc7 | ||||
| 	github.com/alecthomas/assert/v2 v2.2.2 | ||||
| 	gopkg.in/leonelquinteros/gotext.v1 v1.3.1 | ||||
| ) | ||||
| 
 | ||||
| require ( | ||||
| 	github.com/alecthomas/participle/v2 v2.0.0 // indirect | ||||
| 	github.com/alecthomas/repr v0.2.0 // indirect | ||||
| @ -17,10 +23,3 @@ require ( | ||||
| 	github.com/x448/float16 v0.8.4 // indirect | ||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||
| ) | ||||
| 
 | ||||
| require ( | ||||
| 	git.defalsify.org/vise.git v0.1.0-rc.1.0.20240906020635-400f69d01a89 | ||||
| 	github.com/alecthomas/assert/v2 v2.2.2 | ||||
| 	github.com/peteole/testdata-loader v0.3.0 | ||||
| 	gopkg.in/leonelquinteros/gotext.v1 v1.3.1 | ||||
| ) | ||||
|  | ||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| git.defalsify.org/vise.git v0.1.0-rc.1.0.20240906020635-400f69d01a89 h1:YyQODhMwSM5YD9yKHM5jCF0HC0RQtE3MkVXcTnOhXJo= | ||||
| git.defalsify.org/vise.git v0.1.0-rc.1.0.20240906020635-400f69d01a89/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= | ||||
| git.defalsify.org/vise.git v0.1.0-rc.3.0.20240911162138-1f2af8672dc7 h1:embPZDx0Sgpq6jp9vcZ1GVI0eum3PsPCmAfxAa/1KLI= | ||||
| git.defalsify.org/vise.git v0.1.0-rc.3.0.20240911162138-1f2af8672dc7/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= | ||||
| github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= | ||||
| github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= | ||||
| github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= | ||||
|  | ||||
| @ -66,20 +66,16 @@ type Handlers struct { | ||||
| 	accountService server.AccountServiceInterface | ||||
| } | ||||
| 
 | ||||
| func NewHandlers(parser *asm.FlagParser, pe *persist.Persister, userdataStore db.Db) (*Handlers, error) { | ||||
| 	userDb := utils.UserDataStore{ | ||||
| 		Db: userdataStore, | ||||
| 	} | ||||
| 	if pe == nil { | ||||
| 		return nil, fmt.Errorf("cannot create handler with nil persister") | ||||
| 	} | ||||
| func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db) (*Handlers, error) { | ||||
| 	if userdataStore == nil { | ||||
| 		return nil, fmt.Errorf("cannot create handler with nil userdata store") | ||||
| 	} | ||||
| 	userDb := &utils.UserDataStore{ | ||||
| 		Db: userdataStore, | ||||
| 	} | ||||
| 	h := &Handlers{ | ||||
| 		pe:             pe, | ||||
| 		userdataStore:  &userDb, | ||||
| 		flagManager:    parser, | ||||
| 		userdataStore:      userDb, | ||||
| 		flagManager:        appFlags, | ||||
| 		accountService:     &server.AccountService{}, | ||||
| 	} | ||||
| 	return h, nil | ||||
| @ -94,6 +90,14 @@ func isValidPIN(pin string) bool { | ||||
| 	return match | ||||
| } | ||||
| 
 | ||||
| func (h *Handlers) WithPersister(pe *persist.Persister) *Handlers { | ||||
| 	if h.pe != nil { | ||||
| 		panic("persister already set") | ||||
| 	} | ||||
| 	h.pe = pe | ||||
| 	return h | ||||
| } | ||||
| 
 | ||||
| func (h *Handlers) Init(ctx context.Context, sym string, input []byte) (resource.Result, error) { | ||||
| 	var r resource.Result | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										150
									
								
								internal/http/server.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								internal/http/server.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,150 @@ | ||||
| package http | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"git.defalsify.org/vise.git/db" | ||||
| 	"git.defalsify.org/vise.git/engine" | ||||
| 	"git.defalsify.org/vise.git/logging" | ||||
| 	"git.defalsify.org/vise.git/persist" | ||||
| 	"git.defalsify.org/vise.git/resource" | ||||
| 
 | ||||
| 	"git.grassecon.net/urdt/ussd/internal/handlers/ussd" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	logg = logging.NewVanilla().WithDomain("httpserver") | ||||
| ) | ||||
| 
 | ||||
| type RequestParser interface { | ||||
| 	GetSessionId(rq *http.Request) (string, error) | ||||
| 	GetInput(rq *http.Request) ([]byte, error) | ||||
| } | ||||
| 
 | ||||
| type DefaultRequestParser struct { | ||||
| } | ||||
| 
 | ||||
| func(rp *DefaultRequestParser) GetSessionId(rq *http.Request) (string, error) { | ||||
| 	v := rq.Header.Get("X-Vise-Session") | ||||
| 	if v == "" { | ||||
| 		return "", fmt.Errorf("no session found") | ||||
| 	} | ||||
| 	return v, nil | ||||
| } | ||||
| 
 | ||||
| func(rp *DefaultRequestParser) GetInput(rq *http.Request) ([]byte, error) { | ||||
| 	defer rq.Body.Close() | ||||
| 	v, err := ioutil.ReadAll(rq.Body) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return v, nil | ||||
| } | ||||
| 
 | ||||
| type SessionHandler struct { | ||||
| 	cfgTemplate engine.Config | ||||
| 	rp RequestParser | ||||
| 	rs resource.Resource | ||||
| 	//first resource.EntryFunc
 | ||||
| 	hn *ussd.Handlers | ||||
| 	provider StorageProvider | ||||
| } | ||||
| 
 | ||||
| //func NewSessionHandler(cfg engine.Config, rs resource.Resource, stateDb db.Db, userdataDb db.Db, rp RequestParser, first resource.EntryFunc) *SessionHandler {
 | ||||
| func NewSessionHandler(cfg engine.Config, rs resource.Resource, stateDb db.Db, userdataDb db.Db, rp RequestParser, hn *ussd.Handlers) *SessionHandler { | ||||
| 	return &SessionHandler{ | ||||
| 		cfgTemplate: cfg, | ||||
| 		rs: rs, | ||||
| 		//first: first,
 | ||||
| 		hn: hn, | ||||
| 		rp: rp, | ||||
| 		provider: NewSimpleStorageProvider(stateDb, userdataDb), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func(f *SessionHandler) writeError(w http.ResponseWriter, code int, msg string, err error) { | ||||
| 	w.Header().Set("X-Vise", msg + ": " + err.Error()) | ||||
| 	w.Header().Set("Content-Length", "0") | ||||
| 	w.WriteHeader(code) | ||||
| 	_, err = w.Write([]byte{}) | ||||
| 	if err != nil { | ||||
| 		w.WriteHeader(500) | ||||
| 		w.Header().Set("X-Vise", err.Error()) | ||||
| 	} | ||||
| 	return  | ||||
| } | ||||
| 
 | ||||
| func(f* SessionHandler) Shutdown() { | ||||
| 	err := f.provider.Close() | ||||
| 	if err != nil { | ||||
| 		logg.Errorf("handler shutdown error", "err", err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func(f *SessionHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||||
| 	var r bool | ||||
| 	sessionId, err := f.rp.GetSessionId(req) | ||||
| 	if err != nil { | ||||
| 		f.writeError(w, 400, "Session missing", err) | ||||
| 		return | ||||
| 	} | ||||
| 	input, err := f.rp.GetInput(req) | ||||
| 	if err != nil { | ||||
| 		f.writeError(w, 400, "Input read fail", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx := req.Context() | ||||
| 	cfg := f.cfgTemplate | ||||
| 	cfg.SessionId = sessionId | ||||
| 
 | ||||
| 	logg.InfoCtxf(ctx, "new request",  "session", cfg.SessionId, "input", input) | ||||
| 
 | ||||
| 	storage, err := f.provider.Get(cfg.SessionId) | ||||
| 	if err != nil { | ||||
| 		f.writeError(w, 500, "Storage retrieval fail", err) | ||||
| 		return | ||||
| 	} | ||||
| 	f.hn = f.hn.WithPersister(storage.Persister) | ||||
| 	defer f.provider.Put(cfg.SessionId, storage) | ||||
| 	en := getEngine(cfg, f.rs, storage.Persister) | ||||
| 	en = en.WithFirst(f.hn.Init) | ||||
| 	if cfg.EngineDebug { | ||||
| 		en = en.WithDebug(nil) | ||||
| 	} | ||||
| 
 | ||||
| 	r, err = en.Init(ctx) | ||||
| 	if err != nil { | ||||
| 		f.writeError(w, 500, "Engine init fail", err) | ||||
| 		return | ||||
| 	} | ||||
| 	if r && len(input) > 0 { | ||||
| 		r, err = en.Exec(ctx, input) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		f.writeError(w, 500, "Engine exec fail", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	w.WriteHeader(200) | ||||
| 	w.Header().Set("Content-Type", "text/plain") | ||||
| 	_, err = en.WriteResult(ctx, w) | ||||
| 	if err != nil { | ||||
| 		f.writeError(w, 500, "Write result fail", err) | ||||
| 		return | ||||
| 	} | ||||
| 	err = en.Finish() | ||||
| 	if err != nil { | ||||
| 		f.writeError(w, 500, "Engine finish fail", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	_ = r | ||||
| } | ||||
| 
 | ||||
| func getEngine(cfg engine.Config, rs resource.Resource, pr *persist.Persister) *engine.DefaultEngine { | ||||
| 	en := engine.NewEngine(cfg, rs) | ||||
| 	en = en.WithPersister(pr) | ||||
| 	return en | ||||
| } | ||||
							
								
								
									
										44
									
								
								internal/http/storage.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								internal/http/storage.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| package http | ||||
| 
 | ||||
| import ( | ||||
| 	"git.defalsify.org/vise.git/db" | ||||
| 	"git.defalsify.org/vise.git/persist" | ||||
| ) | ||||
| 
 | ||||
| type Storage struct { | ||||
| 	Persister *persist.Persister | ||||
| 	UserdataDb db.Db	 | ||||
| } | ||||
| 
 | ||||
| type StorageProvider interface { | ||||
| 	Get(sessionId string) (Storage, error) | ||||
| 	Put(sessionId string, storage Storage) error | ||||
| 	Close() error | ||||
| } | ||||
| 
 | ||||
| type SimpleStorageProvider struct { | ||||
| 	Storage | ||||
| } | ||||
| 
 | ||||
| func NewSimpleStorageProvider(stateStore db.Db, userdataStore db.Db) StorageProvider { | ||||
| 	pe := persist.NewPersister(stateStore) | ||||
| 	pe = pe.WithFlush() | ||||
| 	return &SimpleStorageProvider{ | ||||
| 		Storage: Storage{ | ||||
| 			Persister: pe, | ||||
| 			UserdataDb: userdataStore, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *SimpleStorageProvider) Get(sessionId string) (Storage, error) { | ||||
| 	return p.Storage, nil | ||||
| } | ||||
| 
 | ||||
| func (p *SimpleStorageProvider) Put(sessionId string, storage Storage) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (p *SimpleStorageProvider) Close() error { | ||||
| 	return p.Storage.UserdataDb.Close() | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user