func handler(r *data.FileRepo) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { path := path.Clean(req.URL.Path) if path == "/" { if req.Method == "HEAD" { return } else if req.Method != "GET" { w.WriteHeader(404) return } paths, err := r.List(req.URL.Query().Get("dir")) if err != nil && err != backend.ErrNotFound { errorResponse(w, err) return } if paths == nil { paths = []string{} } sort.Strings(paths) w.WriteHeader(200) json.NewEncoder(w).Encode(paths) return } switch req.Method { case "HEAD", "GET": file, err := r.Get(path, req.Method == "GET") if err != nil { errorResponse(w, err) return } if file.FileStream != nil { defer file.Close() } if r, ok := file.FileStream.(backend.Redirector); ok && req.Method == "GET" { http.Redirect(w, req, r.RedirectURL(), http.StatusFound) return } w.Header().Set("Content-Length", strconv.FormatInt(file.Size, 10)) w.Header().Set("Content-Type", file.Type) w.Header().Set("Etag", file.ETag) http.ServeContent(w, req, path, file.ModTime, file) case "PUT": var err error if src := req.Header.Get("Blobstore-Copy-From"); src != "" { err = r.Copy(path, src) } else { var offset int64 if s := req.Header.Get("Blobstore-Offset"); s != "" { offset, err = strconv.ParseInt(s, 10, 64) if err != nil { errorResponse(w, err) return } } err = r.Put(path, req.Body, offset, req.Header.Get("Content-Type")) } if err != nil { errorResponse(w, err) return } w.WriteHeader(200) case "DELETE": err := r.Delete(path) if err != nil { errorResponse(w, err) return } w.WriteHeader(200) default: w.WriteHeader(http.StatusMethodNotAllowed) } }) }