code: func (a *Handler) handleSearch(w http.ResponseWriter, r *http.Request) {
  	if r.Method != http.MethodPost {
  		camhttputil.BadRequestError(w, camhttputil.InvalidMethodError{}.Error())
  		return
  	}
  	if a.sh == nil {
  		http.Error(w, "app proxy has no search handler", 500)
  		return
  	}
  	a.masterQueryMu.RLock()
  	if a.masterQuery == nil {
  		http.Error(w, "search is not allowed", http.StatusForbidden)
  		a.masterQueryMu.RUnlock()
  		return
  	}
  	a.masterQueryMu.RUnlock()
  	var sq search.SearchQuery
  	if err := sq.FromHTTP(r); err != nil {
  		camhttputil.ServeJSONError(w, err)
  		return
  	}
  	sr, err := a.sh.Query(r.Context(), &sq)
  	if err != nil {
  		camhttputil.ServeJSONError(w, err)
  		return
  	}
  	// check this search is in the allowed domain
  	if !a.allowProxySearchResponse(sr) {
  		// there's a chance our domainBlobs cache is expired so let's
  		// refresh it and retry, but no more than once per minute.
  		if err := a.refreshDomainBlobs(); err != nil {
  			http.Error(w, "search scope is forbidden", http.StatusForbidden)
  			return
  		}
  		if !a.allowProxySearchResponse(sr) {
  			http.Error(w, "search scope is forbidden", http.StatusForbidden)
  			return
  		}
  	}
  	camhttputil.ReturnJSON(w, sr)
  }
docs: // handleSearch runs the requested search query against the search handler, and
  // if the results are within the domain allowed by the master query, forwards them
  // back to the client.