A fast and simple blog backend.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
mediocre-blog/src/http/assets.go

136 lines
2.8 KiB

package http
import (
"bytes"
"errors"
"fmt"
"net/http"
"path/filepath"
"strings"
"time"
"github.com/mediocregopher/blog.mediocregopher.com/srv/http/apiutil"
"github.com/mediocregopher/blog.mediocregopher.com/srv/post/asset"
)
func (a *api) managePostAssetsHandler() http.Handler {
tpl := a.mustParseBasedTpl("post-assets-manage.html")
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
ids, err := a.params.PostAssetStore.List()
if err != nil {
apiutil.InternalServerError(
rw, r, fmt.Errorf("getting list of asset ids: %w", err),
)
return
}
tplPayload := struct {
IDs []string
}{
IDs: ids,
}
executeTemplate(rw, r, tpl, tplPayload)
})
}
func (a *api) getPostAssetHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
maxWidth, err := apiutil.StrToInt(r.FormValue("w"), 0)
if err != nil {
apiutil.BadRequest(rw, r, fmt.Errorf("invalid w parameter: %w", err))
return
}
var (
path = strings.TrimPrefix(r.URL.Path, "/")
buf = new(bytes.Buffer)
)
err = a.params.PostAssetLoader.Load(
path,
buf,
asset.LoadOpts{
ImageWidth: maxWidth,
},
)
if errors.Is(err, asset.ErrNotFound) {
http.Error(rw, "Asset not found", 404)
return
} else if errors.Is(err, asset.ErrCannotResize) {
http.Error(rw, "Image resizing not supported", 400)
return
} else if err != nil {
apiutil.InternalServerError(
rw, r, fmt.Errorf("fetching asset at path %q: %w", path, err),
)
return
}
http.ServeContent(
rw, r, path, time.Time{}, bytes.NewReader(buf.Bytes()),
)
})
}
func (a *api) postPostAssetHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
id := r.PostFormValue("id")
if id == "" {
apiutil.BadRequest(rw, r, errors.New("id is required"))
return
}
file, _, err := r.FormFile("file")
if err != nil {
apiutil.BadRequest(rw, r, fmt.Errorf("reading multipart file: %w", err))
return
}
defer file.Close()
if err := a.params.PostAssetStore.Set(id, file); err != nil {
apiutil.InternalServerError(rw, r, fmt.Errorf("storing file: %w", err))
return
}
a.executeRedirectTpl(rw, r, a.manageAssetsURL(false))
})
}
func (a *api) deletePostAssetHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
id := filepath.Base(r.URL.Path)
if id == "/" {
apiutil.BadRequest(rw, r, errors.New("id is required"))
return
}
err := a.params.PostAssetStore.Delete(id)
if errors.Is(err, asset.ErrNotFound) {
http.Error(rw, "Asset not found", 404)
return
} else if err != nil {
apiutil.InternalServerError(
rw, r, fmt.Errorf("deleting asset with id %q: %w", id, err),
)
return
}
a.executeRedirectTpl(rw, r, a.manageAssetsURL(false))
})
}