go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

main.go (4922B)


      1 // Example: HTTP server wrapper (to be used with manual client).
      2 package main
      3 
      4 import (
      5 	"context"
      6 	"flag"
      7 	"fmt"
      8 	"io/ioutil"
      9 	"net/http"
     10 	"os"
     11 	"path"
     12 
     13 	"git.defalsify.org/vise.git/engine"
     14 	"git.defalsify.org/vise.git/persist"
     15 	"git.defalsify.org/vise.git/resource"
     16 	"git.defalsify.org/vise.git/logging"
     17 	fsdb "git.defalsify.org/vise.git/db/fs"
     18 )
     19 
     20 var (
     21 	logg logging.Logger = logging.NewVanilla().WithDomain("http")
     22 )
     23 
     24 type LocalHandler struct {
     25 	sessionId string
     26 }	
     27 
     28 func NewLocalHandler() *LocalHandler {
     29 	return &LocalHandler{
     30 		sessionId: "",
     31 	}
     32 }
     33 
     34 func(h* LocalHandler) SetSession(sessionId string) {
     35 	h.sessionId = sessionId
     36 }
     37 
     38 func(h* LocalHandler) AddSession(ctx context.Context, sym string, input []byte) (resource.Result, error) {
     39 	return resource.Result{
     40 		Content: h.sessionId + ":" + string(input),
     41 	}, nil
     42 }
     43 
     44 type RequestParser interface {
     45 	GetSessionId(*http.Request) (string, error)
     46 	GetInput(*http.Request) ([]byte, error)
     47 }
     48 
     49 type DefaultRequestParser struct {
     50 }
     51 
     52 func(rp *DefaultRequestParser) GetSessionId(rq *http.Request) (string, error) {
     53 	v := rq.Header.Get("X-Vise-Session")
     54 	if v == "" {
     55 		return "", fmt.Errorf("no session found")
     56 	}
     57 	return v, nil
     58 }
     59 
     60 func(rp *DefaultRequestParser) GetInput(rq *http.Request) ([]byte, error) {
     61 	defer rq.Body.Close()
     62 	v, err := ioutil.ReadAll(rq.Body)
     63 	if err != nil {
     64 		return nil, err
     65 	}
     66 	return v, nil
     67 }
     68 
     69 type DefaultSessionHandler struct {
     70 	cfgTemplate engine.Config
     71 	rp RequestParser
     72 	rs resource.Resource
     73 	rh *LocalHandler
     74 	peBase string
     75 }
     76 
     77 func NewDefaultSessionHandler(ctx context.Context, persistBase string, resourceBase string, rp RequestParser, outputSize uint32, cacheSize uint32, flagCount uint32) *DefaultSessionHandler {
     78 	store := fsdb.NewFsDb()
     79 	err := store.Connect(ctx, resourceBase)
     80 	if err != nil {
     81 		panic(err)
     82 	}
     83 	rs := resource.NewDbResource(store)
     84 	rh := NewLocalHandler()
     85 	rs.AddLocalFunc("echo", rh.AddSession)
     86 	return &DefaultSessionHandler{
     87 		cfgTemplate: engine.Config{
     88 			OutputSize: outputSize,
     89 			Root: "root",
     90 			FlagCount: flagCount,
     91 			CacheSize: cacheSize,
     92 		},
     93 		rs: rs,
     94 		rh: rh,
     95 		rp: rp,
     96 	}
     97 }
     98 
     99 func(f *DefaultSessionHandler) GetEngine(ctx context.Context, sessionId string) (engine.Engine, error) {
    100 	cfg := f.cfgTemplate
    101 	cfg.SessionId = sessionId
    102 	
    103 	//persistPath := path.Join(f.peBase, sessionId)
    104 	persistPath := path.Join(f.peBase)
    105 	if persistPath == "" {
    106 		persistPath = ".state"
    107 	}
    108 	store := fsdb.NewFsDb()
    109 	err := store.Connect(ctx, persistPath)
    110 	if err != nil {
    111 		return nil, err
    112 	}
    113 	store.SetSession(cfg.SessionId)
    114 	f.rh.SetSession(cfg.SessionId)
    115 
    116 	pe := persist.NewPersister(store)
    117 	en := engine.NewEngine(cfg, f.rs)
    118 	en = en.WithPersister(pe)
    119 
    120 	return en, err
    121 }
    122 
    123 func(f *DefaultSessionHandler) writeError(w http.ResponseWriter, code int, msg string, err error) {
    124 	w.Header().Set("X-Vise", msg + ": " + err.Error())
    125 	w.Header().Set("Content-Length", "0")
    126 	w.WriteHeader(code)
    127 	_, err = w.Write([]byte{})
    128 	if err != nil {
    129 		w.WriteHeader(500)
    130 		w.Header().Set("X-Vise", err.Error())
    131 	}
    132 	return 
    133 }
    134 
    135 func(f *DefaultSessionHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    136 	var r bool
    137 	sessionId, err := f.rp.GetSessionId(req)
    138 	if err != nil {
    139 		f.writeError(w, 400, "Session missing", err)
    140 		return
    141 	}
    142 	input, err := f.rp.GetInput(req)
    143 	if err != nil {
    144 		f.writeError(w, 400, "Input read fail", err)
    145 		return
    146 	}
    147 	ctx := req.Context()
    148 	en, err := f.GetEngine(ctx, sessionId)
    149 	if err != nil {
    150 		f.writeError(w, 400, "Engine start fail", err)
    151 		return
    152 	}
    153 
    154 	//if len(input) == 0 {
    155 	//	r, err = en.Init(ctx)
    156 	//} else {
    157 	r, err = en.Exec(ctx, input)
    158 	//}
    159 	if err != nil {
    160 		f.writeError(w, 500, "Engine exec fail", err)
    161 		return
    162 	}
    163 	w.WriteHeader(200)
    164 	w.Header().Set("Content-Type", "text/plain")
    165 	_, err = en.Flush(ctx, w)
    166 	if err != nil {
    167 		f.writeError(w, 500, "Write result fail", err)
    168 		return
    169 	}
    170 	err = en.Finish()
    171 	if err != nil {
    172 		f.writeError(w, 500, "Engine finish fail", err)
    173 		return
    174 	}
    175 	_ = r
    176 }
    177 
    178 func main() {
    179 	var host string
    180 	var port string
    181 	var peDir string
    182 	var rsDir string
    183 	var outSize uint
    184 	var flagCount uint
    185 	var cacheSize uint
    186 	flag.StringVar(&rsDir, "r", ".", "resource dir")
    187 	flag.StringVar(&host, "h", "127.0.0.1", "http host")
    188 	flag.StringVar(&port, "p", "7123", "http port")
    189 	flag.StringVar(&peDir, "d", ".state", "persistance dir")
    190 	flag.UintVar(&flagCount, "f", 0, "flag count")
    191 	flag.UintVar(&cacheSize, "c", 1024 * 1024, "cache size")
    192 	flag.UintVar(&outSize, "s", 160, "max size of output")
    193 	flag.Parse()
    194 	fmt.Fprintf(os.Stderr, "starting server:\n\tpersistence dir: %s\n\tresource dir: %s\n", rsDir, peDir)
    195 
    196 	ctx := context.Background()
    197 	rp := &DefaultRequestParser{}
    198 	h := NewDefaultSessionHandler(ctx, peDir, rsDir, rp, uint32(outSize), uint32(cacheSize), uint32(flagCount))
    199 	s := &http.Server{
    200 		Addr: fmt.Sprintf("%s:%s", host, port),
    201 		Handler: h,
    202 	}
    203 	err := s.ListenAndServe()
    204 	if err != nil {
    205 		fmt.Fprintf(os.Stderr, "Server error: %s", err)
    206 		os.Exit(1)
    207 	}
    208 }