diff options
| -rw-r--r-- | main.go | 102 |
1 files changed, 89 insertions, 13 deletions
@@ -3,34 +3,67 @@ package main import ( "crypto/rand" "encoding/base64" + "encoding/json" "fmt" "io" "log" "net/http" "os" "path/filepath" + "strings" "github.com/robert-nix/ansihtml" flag "github.com/spf13/pflag" ) -type server struct { +const ( + MetadataExt = ".metadata" +) + +type Server struct { data string } -func (s *server) Post(w http.ResponseWriter, r *http.Request) { +type Metadata struct { + ContentType string `json:"contentType"` +} + +func writeMetadata(filename string, m *Metadata) error { + f, err := os.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o644) + if err != nil { + return err + } + j := json.NewEncoder(f) + return j.Encode(m) +} + +func readMetadata(filename string) (*Metadata, error) { + f, err := os.Open(filename) + if err != nil { + return nil, err + } + var m Metadata + j := json.NewDecoder(f) + if err := j.Decode(&m); err != nil { + return nil, err + } + return &m, nil +} + +func (s *Server) Post(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { return } var random [16]byte _, err := io.ReadFull(rand.Reader, random[:]) if err != nil { + log.Print("io.ReadFull(rand.Reader): ", err) w.WriteHeader(http.StatusInternalServerError) return } - filename := base64.RawURLEncoding.EncodeToString(random[:]) - path := filepath.Join(s.data, filename) - f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o644) + name := base64.RawURLEncoding.EncodeToString(random[:]) + filename := filepath.Join(s.data, name) + f, err := os.OpenFile(filename, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o644) if err != nil { log.Print("OpenFile(): ", err) w.WriteHeader(http.StatusInternalServerError) @@ -38,20 +71,67 @@ func (s *server) Post(w http.ResponseWriter, r *http.Request) { } defer f.Close() if _, err = io.Copy(f, r.Body); err != nil { + log.Print("io.Copy(): ", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + m := Metadata{ + ContentType: r.Header.Get("content-type"), + } + if err = writeMetadata(filename+MetadataExt, &m); err != nil { + log.Print("writeMetadata(): ", err) w.WriteHeader(http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) - fmt.Fprintf(w, "/%s", filename) + fmt.Fprintf(w, "/%s\n", name) } -func (s *server) Get(w http.ResponseWriter, r *http.Request) { +func serveAnsiHtml(w http.ResponseWriter, filename string) { + f, err := os.Open(filename) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.Header().Add("content-type", "text/html") + data, err := io.ReadAll(f) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + data = ansihtml.ConvertToHTML(data) + data = []byte(fmt.Sprintf("<pre>%s</pre>", strings.ReplaceAll(string(data), "\n", "<br>"))) + w.Write(data) +} + +func (s *Server) Get(w http.ResponseWriter, r *http.Request) { path := r.URL.Path + if path == "/" { + w.Header().Add("content-type", "text/plain; charset=UTF-8") + w.Write([]byte("Bin-ки и глогинки")) + return + } filename := filepath.Join(s.data, path) + m, err := readMetadata(filename + MetadataExt) + if err != nil { + log.Print("readMetadata(): ", err) + w.WriteHeader(http.StatusNotFound) + return + } + h := w.Header() + switch m.ContentType { + case "text/x-ansi": + serveAnsiHtml(w, filename) + return + case "": + m.ContentType = "application/octet-stream" + default: + } + h.Add("content-type", m.ContentType) http.ServeFile(w, r, filename) } -func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case "POST": s.Post(w, r) @@ -69,15 +149,11 @@ func main() { flag.StringVarP(&data, "data-path", "d", "./data", "The path to the data") flag.Parse() - html := ansihtml.ConvertToHTML([]byte("\x1b[33mThis text is yellow.\x1b[m")) - // html: `<span style="color:olive;">This text is yellow.</span>` - println(string(html)) - datadir, err := filepath.Abs(data) if err != nil { log.Fatal(err) } - s := &server{ + s := &Server{ data: datadir, } log.Printf("Listening at '%s'...", addr) |
