dndex/server/files.go

154 lines
3.2 KiB
Go

package server
import (
"io"
"io/ioutil"
"local/dndex/config"
"local/simpleserve/simpleserve"
"net/http"
"os"
"path"
"strings"
"github.com/google/uuid"
)
func (rest *REST) files(w http.ResponseWriter, r *http.Request) {
if len(r.URL.Path) < 2 {
switch r.Method {
case http.MethodPost:
rest.filesCreate(w, r)
default:
rest.respNotFound(w)
}
} else {
switch r.Method {
case http.MethodPut:
rest.filesUpdate(w, r)
case http.MethodGet:
rest.filesGet(w, r)
case http.MethodDelete:
rest.filesDelete(w, r)
default:
rest.respNotFound(w)
}
}
}
func (rest *REST) filesCreate(w http.ResponseWriter, r *http.Request) {
id := uuid.New().String()
r.URL.Path = "/" + id
localPath := rest.filesPath(r)
if stat, err := os.Stat(localPath); !os.IsNotExist(err) || (stat != nil && stat.IsDir()) {
rest.respConflict(w)
return
}
if err := os.MkdirAll(path.Dir(localPath), os.ModePerm); err != nil {
rest.respError(w, err)
return
}
f, err := os.Create(localPath)
if err != nil {
rest.respError(w, err)
return
}
defer f.Close()
if err := rest.filesStream(r, f); err != nil {
rest.respError(w, err)
return
}
w.Write([]byte(id))
}
func (rest *REST) filesStream(r *http.Request, f io.Writer) error {
var reader io.Reader = r.Body
_, direct := r.URL.Query()["direct"]
if direct {
target, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}
resp, err := http.Get(string(target))
if err != nil {
return err
}
defer resp.Body.Close()
reader = resp.Body
}
if _, err := io.Copy(f, reader); err != nil {
return err
}
return nil
}
func (rest *REST) filesDelete(w http.ResponseWriter, r *http.Request) {
localPath := rest.filesPath(r)
if stat, err := os.Stat(localPath); os.IsNotExist(err) {
rest.respOK(w)
return
} else if err != nil || stat.IsDir() {
rest.respConflict(w)
return
}
if err := os.Remove(localPath); err != nil {
rest.respError(w, err)
}
rest.respOK(w)
}
func (rest *REST) filesGet(w http.ResponseWriter, r *http.Request) {
simpleserve.SetContentTypeIfMedia(w, r)
r.URL.Path = strings.TrimSuffix(r.URL.Path, path.Ext(r.URL.Path))
localPath := rest.filesPath(r)
if stat, err := os.Stat(localPath); os.IsNotExist(err) {
rest.respNotFound(w)
return
} else if err != nil || stat.IsDir() {
rest.respConflict(w)
return
}
f, err := os.Open(localPath)
if err != nil {
rest.respError(w, err)
return
}
defer f.Close()
if _, err := io.Copy(w, f); err != nil {
rest.respError(w, err)
}
}
func (rest *REST) filesUpdate(w http.ResponseWriter, r *http.Request) {
localPath := rest.filesPath(r)
if stat, err := os.Stat(localPath); os.IsNotExist(err) {
rest.respNotFound(w)
return
} else if err != nil || stat.IsDir() {
rest.respConflict(w)
return
}
f, err := os.Create(localPath + ".tmp")
if err != nil {
rest.respError(w, err)
return
}
defer f.Close()
if err := rest.filesStream(r, f); err != nil {
rest.respError(w, err)
return
}
if err := os.Rename(localPath+".tmp", localPath); err != nil {
rest.respError(w, err)
return
}
rest.respOK(w)
}
func (rest *REST) filesPath(r *http.Request) string {
scope := rest.scope(r)
localPath := path.Join(config.New().FileRoot, scope.Namespace, r.URL.Path)
return localPath
}