forked from wgroeneveld/go-jamming
revert to embedded anonymous images if downloading pictures fails
parent
64c6065d74
commit
00f927886d
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -2,22 +2,47 @@ package pictures
|
|||
|
||||
import (
|
||||
"brainbaking.com/go-jamming/db"
|
||||
_ "embed"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/zerolog/log"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
//go:embed anonymous.jpg
|
||||
var anonymous []byte
|
||||
|
||||
const (
|
||||
Anonymous = "anonymous"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if anonymous == nil {
|
||||
log.Fatal().Msg("embedded anonymous image missing?")
|
||||
}
|
||||
}
|
||||
|
||||
// Handle handles picture GET calls.
|
||||
// It does not validate the picture query as it's part of a composite key anyway.
|
||||
func Handle(repo db.MentionRepo) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
picDomain := mux.Vars(r)["picture"]
|
||||
if picDomain == Anonymous {
|
||||
servePicture(w, anonymous)
|
||||
return
|
||||
}
|
||||
|
||||
picData := repo.GetPicture(picDomain)
|
||||
if picData == nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
// TODO response headers? is this a jpeg, png, gif, webm? should we?
|
||||
w.Write(picData)
|
||||
servePicture(w, picData)
|
||||
}
|
||||
}
|
||||
|
||||
// servePicture writes an OK and raw bytes.
|
||||
// For some reason, headers - although they should be there - aren't needed?
|
||||
func servePicture(w http.ResponseWriter, bytes []byte) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write(bytes)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package recv
|
|||
|
||||
import (
|
||||
"brainbaking.com/go-jamming/app/mf"
|
||||
"brainbaking.com/go-jamming/app/pictures"
|
||||
"brainbaking.com/go-jamming/common"
|
||||
"brainbaking.com/go-jamming/db"
|
||||
"brainbaking.com/go-jamming/rest"
|
||||
|
@ -97,16 +98,22 @@ func (recv *Receiver) parseBodyAsNonIndiewebSite(body string, wm mf.Mention) *mf
|
|||
}
|
||||
}
|
||||
|
||||
// saveAuthorPictureLocally tries to download the author picture.
|
||||
// If it succeeds, it alters the picture path to a local /pictures/x one.
|
||||
// If it fails, it falls back to a local default image.
|
||||
// This *should* also validate image byte headers, like https://stackoverflow.com/questions/670546/determine-if-file-is-an-image
|
||||
func (recv *Receiver) saveAuthorPictureLocally(indieweb *mf.IndiewebData) {
|
||||
_, picData, err := recv.RestClient.GetBody(indieweb.Author.Picture)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("url", indieweb.Author.Picture).Msg("Unable to download author picture. Ignoring.")
|
||||
log.Warn().Err(err).Str("url", indieweb.Author.Picture).Msg("Unable to download author picture. Reverting to anonymous.")
|
||||
indieweb.Author.Picture = fmt.Sprintf("/pictures/%s", pictures.Anonymous)
|
||||
return
|
||||
}
|
||||
srcDomain := rest.Domain(indieweb.Source)
|
||||
_, dberr := recv.Repo.SavePicture(picData, srcDomain)
|
||||
if dberr != nil {
|
||||
log.Warn().Err(err).Str("url", indieweb.Author.Picture).Msg("Unable to save downloaded author picture. Ignoring.")
|
||||
log.Warn().Err(err).Str("url", indieweb.Author.Picture).Msg("Unable to save downloaded author picture. Reverting to anonymous.")
|
||||
indieweb.Author.Picture = fmt.Sprintf("/pictures/%s", pictures.Anonymous)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,48 @@ var conf = &common.Config{
|
|||
ConString: ":memory:",
|
||||
}
|
||||
|
||||
func TestSaveAuthorPictureLocally(t *testing.T) {
|
||||
cases := []struct {
|
||||
label string
|
||||
pictureUrl string
|
||||
expectedPictureUrl string
|
||||
}{
|
||||
{
|
||||
"Absolute URL gets 'downloaded' and replaced by relative",
|
||||
"https://brainbaking.com/picture.jpg",
|
||||
"/pictures/brainbaking.com",
|
||||
},
|
||||
{
|
||||
"Absolute URL gets replaced by anonymous if download fails",
|
||||
"https://brainbaking.com/thedogatemypic-nowitsmissing-shiii.png",
|
||||
"/pictures/anonymous",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.label, func(t *testing.T) {
|
||||
repo := db.NewMentionRepo(conf)
|
||||
recv := &Receiver{
|
||||
Conf: conf,
|
||||
Repo: repo,
|
||||
RestClient: &mocks.RestClientMock{
|
||||
GetBodyFunc: mocks.RelPathGetBodyFunc(t, "../../../mocks/"),
|
||||
},
|
||||
}
|
||||
|
||||
indieweb := &mf.IndiewebData{
|
||||
Source: "https://brainbaking.com",
|
||||
Author: mf.IndiewebAuthor{
|
||||
Picture: tc.pictureUrl,
|
||||
},
|
||||
}
|
||||
recv.saveAuthorPictureLocally(indieweb)
|
||||
|
||||
assert.Equal(t, tc.expectedPictureUrl, indieweb.Author.Picture)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReceive(t *testing.T) {
|
||||
cases := []struct {
|
||||
label string
|
||||
|
|
|
@ -50,7 +50,7 @@ func RelPathGetBodyFunc(t *testing.T, relPath string) func(string) (http.Header,
|
|||
mockfile := relPath + strings.ReplaceAll(url, "https://brainbaking.com/", "")
|
||||
html, err := ioutil.ReadFile(mockfile)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
headerData, headerFileErr := ioutil.ReadFile(strings.ReplaceAll(mockfile, ".html", "-headers.json"))
|
||||
|
|
Loading…
Reference in New Issue