| 239 | } |
| 240 | |
| 241 | func (f *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
| 242 | var ( |
| 243 | stats *querier_stats.QueryStats |
| 244 | queryString url.Values |
| 245 | ) |
| 246 | |
| 247 | tenantIDs, err := users.TenantIDs(r.Context()) |
| 248 | if err != nil { |
| 249 | http.Error(w, err.Error(), http.StatusBadRequest) |
| 250 | return |
| 251 | } |
| 252 | |
| 253 | userID := users.JoinTenantIDs(tenantIDs) |
| 254 | source := tripperware.GetSource(r) |
| 255 | |
| 256 | if f.tenantFederationCfg.Enabled { |
| 257 | maxTenant := f.tenantFederationCfg.MaxTenant |
| 258 | if maxTenant > 0 && len(tenantIDs) > maxTenant { |
| 259 | if f.cfg.QueryStatsEnabled { |
| 260 | f.rejectedQueries.WithLabelValues(reasonTooManyTenants, source, userID).Inc() |
| 261 | } |
| 262 | http.Error(w, fmt.Errorf(tenantfederation.ErrTooManyTenants, maxTenant, len(tenantIDs)).Error(), http.StatusBadRequest) |
| 263 | return |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | // Initialise the stats in the context and make sure it's propagated |
| 268 | // down the request chain. |
| 269 | if f.cfg.QueryStatsEnabled { |
| 270 | // Check if querier stats is enabled in the context. |
| 271 | stats = querier_stats.FromContext(r.Context()) |
| 272 | if stats == nil { |
| 273 | var ctx context.Context |
| 274 | stats, ctx = querier_stats.ContextWithEmptyStats(r.Context()) |
| 275 | r = r.WithContext(ctx) |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | defer func() { |
| 280 | _ = r.Body.Close() |
| 281 | }() |
| 282 | |
| 283 | // Buffer the body for later use to track slow queries. |
| 284 | var buf bytes.Buffer |
| 285 | r.Body = http.MaxBytesReader(w, r.Body, f.cfg.MaxBodySize) |
| 286 | r.Body = io.NopCloser(io.TeeReader(r.Body, &buf)) |
| 287 | // We parse form here so that we can use buf as body, in order to |
| 288 | // prevent https://github.com/cortexproject/cortex/issues/5201. |
| 289 | // Exclude remote read here as we don't have to buffer its body. |
| 290 | isRemoteRead := strings.Contains(r.URL.Path, "api/v1/read") |
| 291 | if !isRemoteRead { |
| 292 | if err := r.ParseForm(); err != nil { |
| 293 | statusCode := http.StatusBadRequest |
| 294 | if util.IsRequestBodyTooLarge(err) { |
| 295 | statusCode = http.StatusRequestEntityTooLarge |
| 296 | } |
| 297 | http.Error(w, err.Error(), statusCode) |
| 298 | if f.cfg.QueryStatsEnabled && util.IsRequestBodyTooLarge(err) { |