noindex for requireauth pages
This commit is contained in:
@@ -43,6 +43,13 @@ func extractJSONLD(t *testing.T, html string) string {
|
|||||||
return strings.TrimSpace(m[1])
|
return strings.TrimSpace(m[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRenderBase_NoindexMeta(t *testing.T) {
|
||||||
|
html := renderTemplate(t, "base.html", pongo2.Context{"noindex": true, "nofollow": true})
|
||||||
|
if !strings.Contains(html, `<meta name="robots" content="noindex, nofollow">`) {
|
||||||
|
t.Errorf("expected combined noindex,nofollow meta; got:\n%s", html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRenderPost_EmitsJSONLD(t *testing.T) {
|
func TestRenderPost_EmitsJSONLD(t *testing.T) {
|
||||||
pv := makePostView("alice.bsky.social", "did:plc:alice", "abc123", "hello")
|
pv := makePostView("alice.bsky.social", "did:plc:alice", "abc123", "hello")
|
||||||
ld, err := buildPostJSONLD(pv, nil, "https://bsky.app/profile/alice.bsky.social/post/abc123", hideEmbedLabels, hideReplyLabels)
|
ld, err := buildPostJSONLD(pv, nil, "https://bsky.app/profile/alice.bsky.social/post/abc123", hideEmbedLabels, hideReplyLabels)
|
||||||
@@ -209,3 +216,50 @@ func TestRenderPost_VideoWithoutThumbnailEmitsOGVideo(t *testing.T) {
|
|||||||
t.Errorf("og:video:type should emit even without imgThumbUrls; got:\n%s", html)
|
t.Errorf("og:video:type should emit even without imgThumbUrls; got:\n%s", html)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auth-required posts must emit noindex,nofollow so the stub page (no body
|
||||||
|
// text, no comments) is not indexed.
|
||||||
|
func TestRenderPost_AuthRequiredNoindex(t *testing.T) {
|
||||||
|
html := renderTemplate(t, "post.html", pongo2.Context{
|
||||||
|
"requiresAuth": true,
|
||||||
|
"profileHandle": "alice.bsky.social",
|
||||||
|
"requestURI": "https://bsky.app/profile/alice.bsky.social/post/abc123",
|
||||||
|
"canonicalURL": "https://bsky.app/profile/alice.bsky.social/post/abc123",
|
||||||
|
"noindex": true,
|
||||||
|
"nofollow": true,
|
||||||
|
})
|
||||||
|
if !strings.Contains(html, `<meta name="robots" content="noindex, nofollow">`) {
|
||||||
|
t.Errorf("auth-required post should emit noindex,nofollow; got:\n%s", html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auth-required profiles must emit noindex,nofollow.
|
||||||
|
func TestRenderProfile_AuthRequiredNoindex(t *testing.T) {
|
||||||
|
pv := newProfileViewDetailed()
|
||||||
|
html := renderTemplate(t, "profile.html", pongo2.Context{
|
||||||
|
"profileView": pv,
|
||||||
|
"requestURI": "https://bsky.app/profile/alice.bsky.social",
|
||||||
|
"requiresAuth": true,
|
||||||
|
"noindex": true,
|
||||||
|
"nofollow": true,
|
||||||
|
})
|
||||||
|
if !strings.Contains(html, `<meta name="robots" content="noindex, nofollow">`) {
|
||||||
|
t.Errorf("auth-required profile should emit noindex,nofollow; got:\n%s", html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public posts must NOT emit a robots meta tag. Guards against an accidental
|
||||||
|
// flip of the noindex flag for indexable pages.
|
||||||
|
func TestRenderPost_PublicNoNoindex(t *testing.T) {
|
||||||
|
pv := makePostView("alice.bsky.social", "did:plc:alice", "abc123", "hello")
|
||||||
|
ld, _ := buildPostJSONLD(pv, nil, "https://bsky.app/profile/alice.bsky.social/post/abc123", hideEmbedLabels, hideReplyLabels)
|
||||||
|
html := renderTemplate(t, "post.html", pongo2.Context{
|
||||||
|
"postView": pv,
|
||||||
|
"requestURI": "https://bsky.app/profile/alice.bsky.social/post/abc123",
|
||||||
|
"canonicalURL": "https://bsky.app/profile/alice.bsky.social/post/abc123",
|
||||||
|
"postJSONLD": ld,
|
||||||
|
})
|
||||||
|
if strings.Contains(html, `<meta name="robots"`) {
|
||||||
|
t.Errorf("public post should not emit robots meta; got:\n%s", html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -499,24 +499,22 @@ type renderOptions struct {
|
|||||||
|
|
||||||
// webGeneric returns a handler that renders the base SPA shell with the given
|
// webGeneric returns a handler that renders the base SPA shell with the given
|
||||||
// render options applied to the template context.
|
// render options applied to the template context.
|
||||||
func (srv *Server) webGeneric(o renderOptions) echo.HandlerFunc {
|
func (srv *Server) webGeneric(c echo.Context, o renderOptions) error {
|
||||||
return func(c echo.Context) error {
|
data := srv.NewTemplateContext()
|
||||||
data := srv.NewTemplateContext()
|
data["noindex"] = o.noindex
|
||||||
data["noindex"] = o.noindex
|
data["nofollow"] = o.nofollow
|
||||||
data["nofollow"] = o.nofollow
|
return c.Render(http.StatusOK, "base.html", data)
|
||||||
return c.Render(http.StatusOK, "base.html", data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// handler for endpoint that have no specific server-side handling
|
// handler for endpoint that have no specific server-side handling
|
||||||
func (srv *Server) WebGeneric(c echo.Context) error {
|
func (srv *Server) WebGeneric(c echo.Context) error {
|
||||||
return srv.webGeneric(renderOptions{})(c)
|
return srv.webGeneric(c, renderOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// handler for routes that should not be indexed by search engines
|
// handler for routes that should not be indexed by search engines
|
||||||
// (e.g. auth-only user-state surfaces, internal/debug pages, action/intent dispatch URLs, search results)
|
// (e.g. auth-only user-state surfaces, internal/debug pages, action/intent dispatch URLs, search results)
|
||||||
func (srv *Server) WebGenericNoindex(c echo.Context) error {
|
func (srv *Server) WebGenericNoindex(c echo.Context) error {
|
||||||
return srv.webGeneric(renderOptions{noindex: true})(c)
|
return srv.webGeneric(c, renderOptions{noindex: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
// handler for action/intent dispatch URLs (e.g. /intent/compose). These accept
|
// handler for action/intent dispatch URLs (e.g. /intent/compose). These accept
|
||||||
@@ -524,7 +522,7 @@ func (srv *Server) WebGenericNoindex(c echo.Context) error {
|
|||||||
// them as link-graph dead-ends in addition to noindex. Anything legitimately
|
// them as link-graph dead-ends in addition to noindex. Anything legitimately
|
||||||
// reachable from a hydrated intent page is also reachable via its canonical URL.
|
// reachable from a hydrated intent page is also reachable via its canonical URL.
|
||||||
func (srv *Server) WebGenericNoindexNofollow(c echo.Context) error {
|
func (srv *Server) WebGenericNoindexNofollow(c echo.Context) error {
|
||||||
return srv.webGeneric(renderOptions{noindex: true, nofollow: true})(c)
|
return srv.webGeneric(c, renderOptions{noindex: true, nofollow: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) WebHome(c echo.Context) error {
|
func (srv *Server) WebHome(c echo.Context) error {
|
||||||
@@ -599,6 +597,8 @@ func (srv *Server) WebPost(c echo.Context) error {
|
|||||||
data["canonicalURL"] = canonicalURL
|
data["canonicalURL"] = canonicalURL
|
||||||
}
|
}
|
||||||
data["requiresAuth"] = true
|
data["requiresAuth"] = true
|
||||||
|
data["noindex"] = true
|
||||||
|
data["nofollow"] = true
|
||||||
data["profileHandle"] = pv.Handle
|
data["profileHandle"] = pv.Handle
|
||||||
if pv.DisplayName != nil {
|
if pv.DisplayName != nil {
|
||||||
data["profileDisplayName"] = *pv.DisplayName
|
data["profileDisplayName"] = *pv.DisplayName
|
||||||
@@ -793,6 +793,8 @@ func (srv *Server) WebProfile(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data["requiresAuth"] = true
|
data["requiresAuth"] = true
|
||||||
|
data["noindex"] = true
|
||||||
|
data["nofollow"] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if jsonld, err := buildProfileJSONLD(pv, recentPosts, hideEmbedLabels, hideReplyLabels); err == nil {
|
if jsonld, err := buildProfileJSONLD(pv, recentPosts, hideEmbedLabels, hideReplyLabels); err == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user