aboutsummaryrefslogtreecommitdiffstats
path: root/internal/web/handlers_blog.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/web/handlers_blog.go')
-rw-r--r--internal/web/handlers_blog.go14
1 files changed, 13 insertions, 1 deletions
diff --git a/internal/web/handlers_blog.go b/internal/web/handlers_blog.go
index f138c58..55cec2e 100644
--- a/internal/web/handlers_blog.go
+++ b/internal/web/handlers_blog.go
@@ -1,6 +1,7 @@
package web
import (
+ "context"
"encoding/xml"
"errors"
"net/http"
@@ -159,6 +160,9 @@ func (s *Server) handleBlogTag(w http.ResponseWriter, r *http.Request) {
// from every page of the blog. A blank query shows just the box; no matches
// is an ordinary result, not a 404.
func (s *Server) handleBlogSearch(w http.ResponseWriter, r *http.Request) {
+ if !s.throttle(w, r, s.searchLimit, s.clientIP(r)) {
+ return
+ }
q := strings.TrimSpace(r.URL.Query().Get("q"))
if utf8.RuneCountInString(q) > maxSearchRunes {
q = string([]rune(q)[:maxSearchRunes])
@@ -172,7 +176,15 @@ func (s *Server) handleBlogSearch(w http.ResponseWriter, r *http.Request) {
pattern := searchPattern(q)
if pattern != "" {
n := pageNum(r)
- posts, total, err := blogStore(r).SearchPublishedPosts(r.Context(), pattern, searchPerPage, (n-1)*searchPerPage)
+ // Bounded: pgx cancels the statement when the context ends, and the
+ // reader sees "nothing found" rather than an error page.
+ ctx, cancel := context.WithTimeout(r.Context(), searchDeadline)
+ defer cancel()
+ posts, total, err := blogStore(r).SearchPublishedPosts(ctx, pattern, searchPerPage, (n-1)*searchPerPage)
+ if errors.Is(err, context.DeadlineExceeded) || errors.Is(ctx.Err(), context.DeadlineExceeded) {
+ logf("search %q on %s timed out", q, currentBlog(r).Subdomain)
+ posts, total, err = nil, 0, nil
+ }
if err != nil {
s.serverError(w, err)
return