// auth (orize) the user to use the API service. func auth( handler func(*web.Context), ) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() ctx := web.NewContext(w, r) // Retrieve username and password from headers. username, password, ok := r.BasicAuth() if !ok { if 0 == len(username) { username = "******" } log.For("/ROUTER(AUTH)", username).Warning().Print("Unknown user and/or password") ctx.Reply().Status(http.StatusUnauthorized).Do() return } // Perform authorization check. if id, err := user.Authorize(username, password); nil != err { // FAILED log.For("/ROUTER(AUTH)", username).Warning().Print("Authentication failed") ctx.Reply().Status(http.StatusUnauthorized).With(err.Error()).Do() } else { // SUCCESS ctx.User = username ctx.UserID = id handler(ctx) } } }
// Route request based on method. func Route(ctx *web.Context) { switch ctx.R.Method { case "GET": get(ctx) case "PUT": put(ctx) case "DELETE": del(ctx) default: log.For("/API/FILE(ROUTE)", ctx.User).Warning().Printf("Unimplemented method: %s", ctx.R.Method) ctx.Reply().Status(http.StatusNotImplemented).Do() } }
// put file into storage. func put(ctx *web.Context) { lg := log.For("/API/FILE(PUT)", ctx.User) path := strings.Replace(ctx.R.URL.Path, "/api/file/", "", 1) lg.Debug().Print("Attempting to put ", path) if 0 == len(path) { msg := "Format should be /api/file/path/to/my.file" lg.Warning().Print(msg) ctx.Reply().Status(http.StatusBadRequest).With(msg).Do() return } if err := file.Upload(path, ctx.R.Body); nil != err { lg.Warning().Print(err) ctx.Reply().Status(http.StatusInternalServerError).With(err.Error()).Do() return } ctx.Reply().Status(http.StatusOK).Do() }
// get file from storage. func get(ctx *web.Context) { lg := log.For("/API/FILE(GET)", ctx.User) path := strings.Replace(ctx.R.URL.Path, "/api/file/", "", 1) lg.Debug().Print("Attempting to get ", path) if 0 == len(path) { msg := "Format should be /api/file/path/to/my.file" lg.Warning().Print(msg) ctx.Reply().Status(http.StatusBadRequest).With(msg).Do() return } if err := file.Download(path, ctx.W); nil != err { lg.Warning().Print(err) ctx.Reply().Status(http.StatusNotFound).With(err.Error()).Do() return } // Explicit response not required. }
// del (ete) file from storage. func del(ctx *web.Context) { lg := log.For("/API/FILE(DELETE)", ctx.User) path := strings.Replace(ctx.R.URL.Path, "/api/file/", "", 1) lg.Debug().Print("Attempting to delete ", path) if 0 == len(path) { msg := "Format should be /api/file/path/to/my.file" lg.Warning().Print(msg) ctx.Reply().Status(http.StatusBadRequest).With(msg).Do() return } if err := file.Delete(path); nil != err { lg.Warning().Print(err) ctx.Reply().Status(http.StatusNotFound).With(err.Error()).Do() return } ctx.Reply().Status(http.StatusOK).Do() }