diff --git a/handle.go b/handle.go index 1e5e8f6..99c23ae 100644 --- a/handle.go +++ b/handle.go @@ -721,6 +721,10 @@ func (h *Handler) handleHTTPError(w http.ResponseWriter, r *http.Request, err er return } else if err.Status == http.StatusNotFound { w.WriteHeader(err.Status) + if strings.Contains(r.Header.Get("Accept"), "application/activity+json") { + // This is a fediverse request; simply return the header + return + } h.errors.NotFound.ExecuteTemplate(w, "base", pageForReq(h.app.App(), r)) return } else if err.Status == http.StatusInternalServerError { diff --git a/posts.go b/posts.go index 07902ce..ca1be25 100644 --- a/posts.go +++ b/posts.go @@ -1295,14 +1295,32 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error coll.Owner = owner } + postFound := true p, err := app.db.GetPost(slug, coll.ID) if err != nil { - if err == ErrCollectionPageNotFound && slug == "feed" { - // User tried to access blog feed without a trailing slash, and - // there's no post with a slug "feed" - return impart.HTTPError{http.StatusFound, c.CanonicalURL() + "/feed/"} + if err == ErrCollectionPageNotFound { + postFound = false + + if slug == "feed" { + // User tried to access blog feed without a trailing slash, and + // there's no post with a slug "feed" + return impart.HTTPError{http.StatusFound, c.CanonicalURL() + "/feed/"} + } + + po := &Post{ + Slug: null.NewString(slug, true), + Font: "norm", + Language: zero.NewString("en", true), + RTL: zero.NewBool(false, true), + Content: `

This page is missing.

+ +Are you sure it was ever here?`, + } + pp := po.processPost() + p = &pp + } else { + return err } - return err } p.IsOwner = owner != nil && p.OwnerID.Valid && owner.ID == p.OwnerID.Int64 p.Collection = coll @@ -1324,11 +1342,20 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error contentType = "text/markdown" } w.Header().Set("Content-Type", fmt.Sprintf("%s; charset=utf-8", contentType)) + if !postFound { + w.WriteHeader(http.StatusNotFound) + fmt.Fprintf(w, "Post not found.") + // TODO: return error instead, so status is correctly reflected in logs + return nil + } if isMarkdown && p.Title.String != "" { fmt.Fprintf(w, "# %s\n\n", p.Title.String) } fmt.Fprint(w, p.Content) } else if strings.Contains(r.Header.Get("Accept"), "application/activity+json") { + if !postFound { + return ErrCollectionPageNotFound + } p.extractData() ap := p.ActivityObject() ap.Context = []interface{}{activitystreams.Namespace} @@ -1345,14 +1372,20 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error IsPinned bool IsCustomDomain bool PinnedPosts *[]PublicPost + IsFound bool }{ PublicPost: p, StaticPage: pageForReq(app, r), IsOwner: cr.isCollOwner, IsCustomDomain: cr.isCustomDomain, + IsFound: postFound, } tp.PinnedPosts, _ = app.db.GetPinnedPosts(coll) tp.IsPinned = len(*tp.PinnedPosts) > 0 && PostsContains(tp.PinnedPosts, p) + + if !postFound { + w.WriteHeader(http.StatusNotFound) + } if err := templates["collection-post"].ExecuteTemplate(w, "post", tp); err != nil { log.Error("Error in collection-post template: %v", err) } diff --git a/templates/collection-post.tmpl b/templates/collection-post.tmpl index 06bfa67..7075226 100644 --- a/templates/collection-post.tmpl +++ b/templates/collection-post.tmpl @@ -8,6 +8,7 @@ + {{ if .IsFound }} @@ -29,6 +30,7 @@ {{range .Images}}{{else}}{{end}} + {{ end }} {{if .Collection.StyleSheet}}{{end}} {{if .Collection.RenderMathJax}} @@ -50,14 +52,14 @@ {{if .PinnedPosts}} {{range .PinnedPosts}}{{.PlainDisplayTitle}}{{end}} {{end}} - {{ if .IsOwner }}{{largeNumFmt .Views}} {{pluralize "view" "views" .Views}} + {{ if and .IsOwner .IsFound }}{{largeNumFmt .Views}} {{pluralize "view" "views" .Views}} Edit {{if .IsPinned}}Unpin{{end}} {{ end }} -
{{if .IsScheduled}}

Scheduled

{{end}}{{if .Title.String}}

{{.FormattedDisplayTitle}}

{{end}}
{{.HTMLContent}}
+
{{if .IsScheduled}}

Scheduled

{{end}}{{if .Title.String}}

{{.FormattedDisplayTitle}}

{{end}}
{{.HTMLContent}}
{{ if .Collection.ShowFooterBranding }}