add documentation

This commit is contained in:
Acconut 2015-02-01 16:17:56 +01:00
parent f628342b82
commit f513d02938
3 changed files with 44 additions and 1 deletions

View File

@ -8,13 +8,28 @@ type MetaData map[string]string
type FileInfo struct {
Id string
// Total file size in bytes specified in the NewUpload call
Size int64
// Offset in bytes (zero-based)
Offset int64
MetaData MetaData
}
type DataStore interface {
NewUpload(size int64, metaData MetaData) (string, error)
// Create a new upload using the size as the file's length. The method must
// return an unique id which is used to identify the upload. If no backend
// (e.g. Riak) specifes the id you may want to use the uid package to
// generate one.
NewUpload(size int64, metaData MetaData) (id string, err error)
// Write the chunk read from src into the file specified by the id at the
// given offset. The handler will take care of validating the offset and
// limiting the size of the src to not overflow the file's size. It may
// return an os.ErrNotExist which will be interpretet as a 404 Not Found.
// It will also lock resources while they are written to ensure only one
// write happens per time.
WriteChunk(id string, offset int64, src io.Reader) error
// Read the fileinformation used to validate the offset and respond to HEAD
// requests. It may return an os.ErrNotExist which will be interpretet as a
// 404 Not Found.
GetInfo(id string) (FileInfo, error)
}

View File

@ -1,3 +1,9 @@
// FileStore is a storage backend used as a tusd.DataStore in tusd.NewHandler.
// It stores the uploads in a directory specified in two different files: The
// `[id].info` files are used to store the fileinfo in JSON format. The
// `[id].bin` files contain the raw binary data uploaded.
// No cleanup is performed so you may want to run a cronjob to ensure your disk
// is not filled up with old and finished uploads.
package filestore
import (
@ -12,7 +18,11 @@ import (
var defaultFilePerm = os.FileMode(0666)
// See the tusd.DataStore interface for documentation about the different
// methods.
type FileStore struct {
// Relative or absolute path to store files in. FileStore does not check
// whether the path exists, you os.MkdirAll in this case on your own.
Path string
}
@ -63,14 +73,17 @@ func (store FileStore) GetInfo(id string) (tusd.FileInfo, error) {
return info, err
}
// Return the path to the .bin storing the binary data
func (store FileStore) binPath(id string) string {
return store.Path + "/" + id + ".bin"
}
// Return the path to the .info file storing the file's info
func (store FileStore) infoPath(id string) string {
return store.Path + "/" + id + ".info"
}
// Update the entire information. Everything will be overwritten.
func (store FileStore) writeInfo(id string, info tusd.FileInfo) error {
data, err := json.Marshal(info)
if err != nil {
@ -79,6 +92,7 @@ func (store FileStore) writeInfo(id string, info tusd.FileInfo) error {
return ioutil.WriteFile(store.infoPath(id), data, defaultFilePerm)
}
// Update the .info file using the new upload.
func (store FileStore) setOffset(id string, offset int64) error {
info, err := store.GetInfo(id)
if err != nil {

View File

@ -25,6 +25,7 @@ var (
ErrSizeExceeded = errors.New("resource's size exceeded")
)
// HTTP status codes sent in the response when the specific error is returned.
var ErrStatusCodes = map[error]int{
ErrUnsupportedVersion: http.StatusPreconditionFailed,
ErrMaxSizeExceeded: http.StatusRequestEntityTooLarge,
@ -37,6 +38,8 @@ var ErrStatusCodes = map[error]int{
}
type Config struct {
// DataStore implementation used to store and retrieve the single uploads.
// Must no be nil.
DataStore DataStore
// MaxSize defines how many bytes may be stored in one single upload. If its
// value is is 0 or smaller no limit will be enforced.
@ -56,6 +59,7 @@ type Handler struct {
locks map[string]bool
}
// Create a new handler using the given configuration.
func NewHandler(config Config) (*Handler, error) {
base := config.BasePath
uri, err := url.Parse(base)
@ -91,6 +95,7 @@ func NewHandler(config Config) (*Handler, error) {
return handler, nil
}
// Implement the http.Handler interface.
func (handler *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
go logger.Println(r.Method, r.URL.Path)
@ -138,6 +143,8 @@ func (handler *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
handler.routeHandler.ServeHTTP(w, r)
}
// Create a new file upload using the datastore after validating the length
// and parsing the metadata.
func (handler *Handler) postFile(w http.ResponseWriter, r *http.Request) {
size, err := strconv.ParseInt(r.Header.Get("Entity-Length"), 10, 64)
if err != nil || size < 0 {
@ -165,6 +172,7 @@ func (handler *Handler) postFile(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
}
// Returns the length and offset for the HEAD request
func (handler *Handler) headFile(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get(":id")
info, err := handler.dataStore.GetInfo(id)
@ -182,6 +190,8 @@ func (handler *Handler) headFile(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}
// Add a chunk to an upload. Only allowed if the upload is not locked and enough
// space is left.
func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get(":id")
@ -246,6 +256,8 @@ func (handler *Handler) patchFile(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}
// Send the error in the response body. The status code will be looked up in
// ErrStatusCodes. If none is found 500 Internal Error will be used.
func (handler *Handler) sendError(w http.ResponseWriter, err error) {
status, ok := ErrStatusCodes[err]
if !ok {
@ -256,6 +268,8 @@ func (handler *Handler) sendError(w http.ResponseWriter, err error) {
w.Write([]byte(err.Error() + "\n"))
}
// Make an absolute URLs to the given upload id. If the base path is absolute
// it will be prepended else the host and protocol from the request is used.
func (handler *Handler) absFileUrl(r *http.Request, id string) string {
if handler.isBasePathAbs {
return handler.basePath + id