package apiServer import ( "encoding/json" "fmt" "io" "log" "net/http" "path" "strconv" "dread.land/deepgram-demo/internal/audio" "dread.land/deepgram-demo/internal/metadata" "github.com/go-chi/chi/v5" ) type ApiServer struct { Audio *audio.AudioServer Metadata *metadata.MetadataServer } func (apiServer *ApiServer) chunkHandler(w http.ResponseWriter, r *http.Request) { // chunkIndex starts at 0 chunkIndexString := r.URL.Query().Get("chunkindex") chunkSizeString := r.URL.Query().Get("chunksize") chunkIndex := 0 var err error if chunkIndexString != "" { chunkIndex, err = strconv.Atoi(chunkIndexString) } if err != nil { http.Error(w, fmt.Sprint(err), http.StatusBadRequest) } chunkSize := 0 if chunkSizeString != "" { chunkSize, err = strconv.Atoi(chunkSizeString) } if err != nil { http.Error(w, fmt.Sprint(err), http.StatusBadRequest) } filename := path.Base(path.Dir(r.URL.Path)) contents, err := apiServer.Audio.Download(filename) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusNotFound) return } startIndex := chunkIndex * chunkSize if startIndex > len(contents) { http.Error(w, "index out of bounds", http.StatusBadRequest) } endIndex := startIndex + chunkSize if endIndex > len(contents) { endIndex = len(contents) } w.Write(contents[startIndex:endIndex]) } func (apiServer *ApiServer) filesHandler(w http.ResponseWriter, r *http.Request) { filename := path.Base(r.URL.Path) switch r.Method { case "GET": // get file contents, err := apiServer.Audio.Download(filename) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusNotFound) return } w.Write(contents) return case "POST": // save file contents, err := io.ReadAll(r.Body) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusBadRequest) } err = apiServer.Audio.Upload(filename, contents) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusConflict) } return default: // error unsupported http.Error(w, "unsupported", http.StatusMethodNotAllowed) return } } func (apiServer *ApiServer) metadataHandler(w http.ResponseWriter, r *http.Request) { filename := path.Base(path.Dir(r.URL.Path)) switch r.Method { case "GET": // get metadata meta, err := apiServer.Metadata.Info(filename) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusNotFound) return } response, err := json.Marshal(meta) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } fmt.Fprint(w, string(response)) return default: http.Error(w, "unsupported", http.StatusMethodNotAllowed) return } } func (apiServer *ApiServer) listHandler(w http.ResponseWriter, r *http.Request) { maxdurationString := r.URL.Query().Get("maxduration") maxduration := 0 var err error if maxdurationString != "" { maxduration, err = strconv.Atoi(maxdurationString) } if err != nil { http.Error(w, fmt.Sprint(err), http.StatusBadRequest) return // error Bad Request } list := apiServer.Metadata.List(maxduration) response, err := json.Marshal(list) if err != nil { http.Error(w, fmt.Sprint(err), http.StatusInternalServerError) return } fmt.Fprint(w, string(response)) } func (apiServer *ApiServer) Serve() { r := chi.NewRouter() r.Get("/files", apiServer.listHandler) r.Get("/files/{filename}", apiServer.filesHandler) r.Post("/files/{filename}", apiServer.filesHandler) r.Get("/files/{filename}/metadata", apiServer.metadataHandler) // chunkNumber r.Get("/files/{filename}/chunk", apiServer.chunkHandler) log.Fatal(http.ListenAndServe(":3030", r)) }