123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- package main
- import (
- "encoding/json"
- "errors"
- "io"
- "net/http"
- "os"
- "path"
- "strings"
- "github.com/labstack/echo/v4"
- "github.com/nyudlts/bytemath"
- )
- // GET /
- func MainHandle(c echo.Context) error {
- m := map[string]any{
- "cod": 200,
- "id": "JGoServer",
- "version": "1.0-dev",
- }
- ents, err := os.ReadDir("storage")
- if errors.Is(err, os.ErrNotExist) {
- err2 := os.Mkdir("storage", 0775)
- if err2 != nil {
- m["cod"] = 500
- m["dirs"] = nil // This is what we were trying to populate
- m["err"] = err2.Error()
- m["cause"] = err.Error()
- return c.JSON(m["cod"].(int), m)
- }
- } else if err != nil {
- m["cod"] = 500
- m["dirs"] = nil // This is what we were trying to populate
- m["err"] = err.Error()
- return c.JSON(m["cod"].(int), m)
- }
- dirs := []string{}
- for _, e := range ents {
- if e.IsDir() {
- dirs = append(dirs, e.Name())
- }
- }
- m["dirs"] = dirs
- return c.JSON(m["cod"].(int), m)
- }
- // Sanitizes directory name so it's a little safe
- func CleanDirName(raw string) string {
- return strings.ToLower(strings.Trim(raw, " .\r\n\t"))
- }
- // GET /dir?q=<dir>
- func GetDirHandle(c echo.Context) error {
- m := map[string]any{
- "cod": 200,
- }
- target := CleanDirName(c.QueryParam("q")) // Directory to list
- if len(target) == 0 || target == "" {
- // Nothing todo?
- m["cod"] = http.StatusBadRequest
- m["q"] = c.QueryParam("q")
- return c.JSON(m["cod"].(int), m)
- }
- // Verify the directory at least exists
- _, err := os.Stat(path.Join("storage", target))
- if errors.Is(err, os.ErrNotExist) {
- err2 := os.MkdirAll(path.Join("storage", target), 0775)
- if err2 != nil {
- m["cod"] = 500
- m["files"] = nil
- m["dirs"] = nil
- m["err"] = err2.Error()
- m["cause"] = err.Error()
- return c.JSON(m["cod"].(int), m)
- }
- } else if err != nil {
- m["cod"] = 500
- m["files"] = nil
- m["dirs"] = nil
- m["err"] = err.Error()
- return c.JSON(m["cod"].(int), m)
- }
- // Scan the dirs looking for files (won't include ones that start with .)
- var scanDir func(string) ([]string, []string, error)
- scanDir = func(dir string) ([]string, []string, error) {
- ents, err := os.ReadDir(dir)
- if err != nil {
- return nil, nil, err
- }
- fs := []string{}
- ds := []string{}
- for _, e := range ents {
- if strings.HasPrefix(e.Name(), ".") { // Keep hidden files/dirs hidden
- continue
- }
- if e.IsDir() {
- ds = append(ds, path.Join(dir, e.Name()))
- f, d, err := scanDir(path.Join(dir, e.Name()))
- if err != nil {
- return nil, nil, err
- }
- fs = append(fs, f...)
- ds = append(ds, d...)
- } else {
- fs = append(fs, path.Join(dir, e.Name()))
- }
- }
- return fs, ds, nil
- }
- files, dirs, err2 := scanDir(path.Join("storage", target))
- if err2 != nil {
- m["cod"] = 500
- m["files"] = nil
- m["dirs"] = nil
- m["err"] = err.Error()
- return c.JSON(m["cod"].(int), m)
- }
- m["files"] = files
- m["dirs"] = dirs
- return c.JSON(m["cod"].(int), m)
- }
- // POST/PUT /up?q=<filepath>
- func UploadJData(c echo.Context) error {
- // e.g. test/dir1/pkt001.json
- targetDir := CleanDirName(path.Dir(c.QueryParam("q"))) // e.g. test/dir1
- targetName := path.Base(c.QueryParam("q")) // e.g. pkt001.json
- _, err := os.Stat(path.Join("storage", targetDir))
- if errors.Is(err, os.ErrNotExist) {
- err2 := os.MkdirAll(path.Join("storage", targetDir), 0775)
- if err2 != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err2.Error(),
- "cause": err.Error(),
- })
- }
- } else if err != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err.Error(),
- })
- }
- fh, err := os.Create(path.Join("storage", targetDir, targetName))
- if err != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err.Error(),
- })
- }
- body := c.Request().Body
- defer body.Close()
- written, err := io.Copy(fh, body)
- fh.Close()
- if err != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err.Error(),
- })
- }
- // Check that it is in fact really JSON
- data, err := os.ReadFile(path.Join("storage", targetDir, targetName))
- if err != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err.Error(),
- })
- }
- var test any
- err = json.Unmarshal(data, &test)
- if err != nil {
- // Not json!
- err2 := os.Remove(path.Join("storage", targetDir, targetName))
- if err2 != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err2.Error(),
- "cause": err.Error(),
- })
- }
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err.Error(),
- })
- }
- // Ok we're good
- return c.JSON(200, map[string]any{
- "cod": 200,
- "size": bytemath.ConvertBytesToHumanReadable(written),
- })
- }
- // GET /down?q=<filepath>
- func DownloadJData(c echo.Context) error {
- // e.g. test/dir1/pkt001.json
- targetDir := CleanDirName(path.Dir(c.QueryParam("q"))) // e.g. test/dir1
- targetName := path.Base(c.QueryParam("q")) // e.g. pkt001.json
- _, err := os.ReadDir(path.Join("storage", targetDir))
- if errors.Is(err, os.ErrNotExist) {
- err2 := os.MkdirAll(path.Join("storage", targetDir), 0775)
- if err2 != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err2.Error(),
- "cause": err.Error(),
- })
- }
- } else if err != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": err.Error(),
- })
- }
- // File contents must be JSON, we live in JSON so it must be JSON data
- fh, err := os.ReadFile(path.Join("storage", targetDir, targetName))
- if err != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": "ReadFile: " + err.Error(),
- "data": nil,
- })
- }
- var data any
- err = json.Unmarshal(fh, &data)
- if err != nil {
- return c.JSON(500, map[string]any{
- "cod": 500,
- "err": "json.Unmarshal: " + err.Error(),
- "data": nil,
- })
- }
- return c.JSON(200, map[string]any{
- "cod": 200,
- "data": data,
- "size": bytemath.ConvertBytesToHumanReadable(int64(len(fh))),
- })
- }
|