示例#1
1
func moveFile(db *postgres.DB, repo *data.FileRepo, f data.BackendFile, delete bool) error {
	b := repo.DefaultBackend()
	tx, err := db.Begin()
	if err != nil {
		return err
	}
	stream, err := f.Backend.Open(tx, f.FileInfo, false)
	if err != nil {
		tx.Rollback()
		return err
	}
	if err := b.Put(tx, f.FileInfo, stream, false); err != nil {
		tx.Rollback()
		return err
	}
	if err := repo.SetBackend(tx, f.ID, b.Name()); err != nil {
		tx.Rollback()
		return err
	}
	if delete {
		if err := f.Backend.Delete(tx, f.FileInfo); err != nil {
			// print but don't return error if deletion of old file fails, we don't want to lose files
			log.Printf("Error deleting %s (%s) from %s: %s", f.FileInfo.Name, f.ID, f.Backend.Name(), err)
		}
	}
	return tx.Commit()
}
示例#2
0
func testDelete(r *data.FileRepo, t *testing.T) {
	put := func(path string) {
		if err := r.Put(path, bytes.NewReader([]byte("data")), 0, "text/plain"); err != nil {
			t.Fatal(err)
		}
	}
	del := func(path string) {
		if err := r.Delete(path); err != nil {
			t.Fatal(err)
		}
	}
	assertExists := func(path string) {
		if _, err := r.Get(path, false); err != nil {
			t.Fatal(err)
		}
	}
	assertNotExists := func(path string) {
		if _, err := r.Get(path, false); err != backend.ErrNotFound {
			t.Fatalf("expected path %q to not exist, got err=%v", path, err)
		}
	}

	put("/dir/foo")
	put("/dir/foo.txt")
	put("/dir/bar.txt")
	del("/dir/foo")
	assertNotExists("/dir/foo")
	assertExists("/dir/foo.txt")
	assertExists("/dir/bar.txt")

	del("/dir")
	assertNotExists("/dir/foo")
	assertNotExists("/dir/foo.txt")
	assertNotExists("/dir/bar.txt")
}
示例#3
0
func testExternalBackendReplace(r *data.FileRepo, t *testing.T) {
	put := func(path string) {
		if err := r.Put(path, bytes.NewReader([]byte("data")), 0, "text/plain"); err != nil {
			t.Fatal(err)
		}
	}
	get := func(path string) string {
		file, err := r.Get("/replace.txt", true)
		if err != nil {
			t.Fatal(err)
		}
		redirect, ok := file.FileStream.(backend.Redirector)
		if !ok {
			t.Fatal("file stream is not a redirector")
		}
		url := redirect.RedirectURL()
		res, err := http.Get(url)
		if err != nil {
			t.Fatal(err)
		}
		res.Body.Close()
		if res.StatusCode != 200 {
			t.Fatalf("expected status 200, got %d", res.StatusCode)
		}
		return url
	}

	put("/replace.txt")
	firstURL := get("/replace.txt")

	put("/replace.txt")
	res, err := http.Get(firstURL)
	if err != nil {
		t.Fatal(err)
	}
	res.Body.Close()
	if res.StatusCode == 200 {
		t.Fatal("unexpected status 200")
	}
	get("/replace.txt")
}
示例#4
0
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)
		}
	})
}