Skip to content

Conversation

@Useinovski
Copy link
Contributor

@Useinovski Useinovski commented Jan 16, 2026

Description

If the feature flag for query-limit bypass is enabled and the incoming request includes the header wait: -1, we should skip all query-limit checks and allow the request to execute without restriction.

We set in the configuration parameter in build.config.json '"disable_timeout_limit" : true' which will allow the user to bypass query limits on all end points.

Motivation and Context

Resolves BED-6991

To be able to bypass query limits for longer running queries that would be timed out with the default timeout set from the UI.

How Has This Been Tested?

Tested in Bruno, with all cases of the Prefer header value. When using the UI, we have a default prefer header set by client.ts which will be handled in future PR to be removed (BED-6985). Unit tests have also been created and or modified.

This default value is only applied in the search endpoint via the explore page.

"disable_timeout_limit" : true

Values tested: Corresponding Status code:
Prefer : "wait=40" 200/201 - Sets timeout of 40 seconds
Prefer : "wait=0" 200/201 - Bypasses query Limits (current behavior)
Prefer : "wait=-1" 200/201 - Bypasses query limits
Prefer : "wait=-30" 400 - Do not allow for negative values < -1

"disable_timeout_limit" : false

Values tested: Corresponding Status code:
Prefer : "wait=40" 200/201 - Sets timeout of 40 seconds
Prefer : "wait=0" 200/201 - Bypasses query Limits (current behavior)
Prefer : "wait=-1" 400 - Failed to bypass limits
Prefer : "wait=-30" 400 - Do not allow for negative values < -1

Screenshots (optional):

"disable_timeout_limit" : true
Screenshot 2026-01-15 at 11 56 40 AM
Screenshot 2026-01-15 at 11 57 23 AM
Screenshot 2026-01-15 at 11 57 39 AM
Screenshot 2026-01-15 at 11 57 55 AM
Screenshot 2026-01-16 at 10 32 12 AM

"disable_timeout_limit" : false
Screenshot 2026-01-15 at 11 50 59 AM
Screenshot 2026-01-15 at 11 52 46 AM
Screenshot 2026-01-15 at 11 53 57 AM
Screenshot 2026-01-15 at 11 54 19 AM
Screenshot 2026-01-16 at 10 30 58 AM

From UI
Screenshot 2026-01-16 at 9 52 53 AM

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist:

Summary by CodeRabbit

  • New Features

    • Prefer header can request a bypass for request duration limits; invalid bypass values return errors.
    • Loaded configuration is now exposed for programmatic access.
  • Improvements

    • Request timeout normalization updated to treat the bypass sentinel consistently and signal bypass-enabled in response headers.
  • Tests

    • Added unit tests covering prefer-header parsing, negative waits, and timeout normalization.

✏️ Tip: You can customize this high-level summary in your review settings.

@Useinovski Useinovski self-assigned this Jan 16, 2026
@Useinovski Useinovski added the api A pull request containing changes affecting the API code. label Jan 16, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

Walkthrough

Adds bypass-limit validation and timeout normalization for Prefer header handling in API middleware, exposes the loaded configuration via a new getter, adds related unit tests, and performs a small whitespace cleanup in logging middleware.

Changes

Cohort / File(s) Summary
Middleware Bypass-Limit Logic
cmd/api/src/api/middleware/middleware.go
Adds canBypassLimits flag and bypassLimit constant, enforces bypass value >= limit, returns specific errors when invalid, emits PreferenceApplied header when bypass enabled, and replaces direct per-request timeout assignment with setUserTimeout normalization.
Middleware Tests
cmd/api/src/api/middleware/middleware_internal_test.go
Adds tests for negative wait handling, expands parsePreferHeaderWait cases (including wait=-1, invalid formats), and tests setUserTimeout behavior with bypass-limit normalization.
Configuration Exposure
cmd/api/src/config/config.go
Introduces package-level loadedConfig and public GetLoadedConfig(); populates loadedConfig inside GetConfiguration after env application.
Logging Whitespace Cleanup
cmd/api/src/api/middleware/logging.go
Removed an extra blank line between timeout handling and request body wrapping (whitespace-only change).

Sequence Diagram(s)

(Skipped — the changes are middleware-level validations and small config/test edits that do not introduce a multi-component sequential flow warranting a diagram.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • stephanieslamb

Poem

🐰
Hopping through headers, gentle and spry,
I check each bypass with one careful eye.
Timeouts tuck close, normalized and neat,
Config sits ready — a cozy retreat.
Tests clap their paws for this tidy new feat. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main feature being added: supporting query limit bypass when prefer:wait=-1 header is provided, directly matching the core functionality implemented across middleware, config, and test files.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering all required sections with detailed information about the feature, testing approach, and configuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@cmd/api/src/api/middleware/middleware_internal_test.go`:
- Around line 126-135: In the test cases where only the error is being asserted,
avoid ineffectual assignments by replacing the left-hand variable with the blank
identifier; specifically, change assignments like `duration, err =
parsePreferHeaderWait("5")` and `duration, err = parsePreferHeaderWait("five")`
to `_ , err = parsePreferHeaderWait("5")` and `_ , err =
parsePreferHeaderWait("five")` respectively so only `err` is used; the other
assertions (e.g., the valid parse using `duration, err =
parsePreferHeaderWait("wait=-1")`) should remain unchanged and still reference
`duration` and `err`.
🧹 Nitpick comments (1)
cmd/api/src/config/config.go (1)

173-175: Guard loadedConfig access if configuration can reload after startup.
GetLoadedConfig() is read per request; if GetConfiguration() is ever called concurrently, this introduces a data race. Please confirm initialization order or add synchronization.

🛠️ Example with atomic.Value
+import "sync/atomic"
...
-var (
-	loadedConfig Configuration
-)
+var loadedConfig atomic.Value // stores Configuration
...
-func GetLoadedConfig() Configuration {
-	return loadedConfig
-}
+func GetLoadedConfig() Configuration {
+	if cfg, ok := loadedConfig.Load().(Configuration); ok {
+		return cfg
+	}
+	return Configuration{}
+}
...
-		loadedConfig = cfg
+		loadedConfig.Store(cfg)

Also applies to: 283-295

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 648bb17 and bcb8e1b.

📒 Files selected for processing (4)
  • cmd/api/src/api/middleware/logging.go
  • cmd/api/src/api/middleware/middleware.go
  • cmd/api/src/api/middleware/middleware_internal_test.go
  • cmd/api/src/config/config.go
💤 Files with no reviewable changes (1)
  • cmd/api/src/api/middleware/logging.go
🧰 Additional context used
🧬 Code graph analysis (2)
cmd/api/src/api/middleware/middleware.go (2)
cmd/api/src/config/config.go (1)
  • GetLoadedConfig (283-285)
cmd/api/src/ctx/ctx.go (3)
  • Get (75-85)
  • Set (88-90)
  • RequestID (93-95)
cmd/api/src/api/middleware/middleware_internal_test.go (1)
cmd/api/src/api/middleware/middleware.go (1)
  • RequestWaitDuration (86-104)
🪛 golangci-lint (2.5.0)
cmd/api/src/api/middleware/middleware_internal_test.go

[major] 130-130: ineffectual assignment to duration

(ineffassign)


[major] 133-133: ineffectual assignment to duration

(ineffassign)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Build BloodHound Container Image / Build and Package Container
  • GitHub Check: build-ui
  • GitHub Check: run-tests
  • GitHub Check: run-analysis
🔇 Additional comments (5)
cmd/api/src/api/middleware/middleware_internal_test.go (2)

66-77: Good negative-wait coverage.
Covers invalid negative wait values and asserts zero duration on error.


137-143: Nice coverage for bypass timeout normalization.
The test clearly verifies the bypass and normal paths for setUserTimeout.

cmd/api/src/api/middleware/middleware.go (3)

86-103: Bypass validation for Prefer wait looks solid.
The guardrails for < -1 and config-gated -1 behavior are clear.


110-152: Preference-Applied header + timeout normalization are consistent.
The bypass signaling and normalized timeout in context align with the new semantics.


167-173: Helper is clear and focused.
setUserTimeout cleanly normalizes the bypass value.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api A pull request containing changes affecting the API code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants