package main import ( _ "embed" "encoding/json" "fmt" "io" "io/ioutil" "gogs.inhome.blapointe.com/local/args" "gogs.inhome.blapointe.com/local/gziphttp" "gogs.inhome.blapointe.com/local/logb" "gogs.inhome.blapointe.com/local/storage" "net/http" ) //go:embed nullboard.html var nullboard string type server struct { db storage.DBStream debug bool crud bool } func main() { as := args.NewArgSet() as.Append(args.INT, "p", "port", 8121) as.Append(args.STRING, "db", "db type", "mapstream") as.Append(args.STRING, "dbaddr", "db addr", "/tmp/db") as.Append(args.STRING, "level", "debug level", "info") as.Append(args.BOOL, "nocrud", "no support CRUD api", false) as.Append(args.BOOL, "debug", "debug mode", false) if err := as.Parse(); err != nil { panic(err) } logb.Set(logb.LevelFromString(as.GetString("level"))) logb.Debugf("nullboard=%v", len(nullboard)) db, err := storage.New(storage.TypeFromString(as.GetString("db")), as.GetString("dbaddr")) if err != nil { panic(err) } dbs := db.(storage.DBStream) server := server{ db: dbs, crud: !as.GetBool("nocrud"), debug: as.GetBool("debug"), } addr := fmt.Sprintf(":%d", as.GetInt("p")) logb.Infof("listening: %s with %+v", addr, server) if err := http.ListenAndServe(addr, server); err != nil { panic(err) } } func (server server) ServeHTTP(w http.ResponseWriter, r *http.Request) { if gziphttp.Can(r) { w2 := gziphttp.New(w) defer w2.Close() w = w2 } switch r.URL.Path { case "/api": if server.crud { logb.Debug("serving api", r.URL.Path, r.URL.Query()) if err := server.apiHandler(w, r); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } return } default: if server.debug { logb.Debug("serving ./nullboard.html", r.URL.Path) b, err := ioutil.ReadFile("./nullboard.html") if err != nil { fmt.Fprintln(w, err.Error()) } else { fmt.Fprintf(w, "%s", b) } } else { logb.Debug("serving nullboard.html", r.URL.Path) fmt.Fprintln(w, nullboard) return } } logb.Debug("404", r.URL.Path) http.NotFound(w, r) } func (server server) apiHandler(w http.ResponseWriter, r *http.Request) error { key := r.URL.Query().Get("key") switch r.Method { case http.MethodGet: switch key { case "": db := server.db.(storage.DB) keys, err := db.List(nil) if err != nil { return err } return json.NewEncoder(w).Encode(keys) default: v, err := server.db.GetStream(key) if err == storage.ErrNotFound { return json.NewEncoder(w).Encode(nil) } if err != nil { return err } _, err = io.Copy(w, v) return err } case http.MethodPost: if err := server.db.SetStream(key, r.Body); err != nil { return err } return json.NewEncoder(w).Encode(nil) case http.MethodDelete: if err := server.db.SetStream(key, nil); err != nil { return err } return json.NewEncoder(w).Encode(nil) default: http.NotFound(w, r) } return nil }