Skip to content

Conversation

@QuintenQVD0
Copy link
Contributor

@QuintenQVD0 QuintenQVD0 commented Jan 17, 2025

Changes

  • allow for custom headers
  • Note: still needs testing from someone

Summary by CodeRabbit

  • New Features
    • Added support for configuring custom HTTP headers for remote requests. Users can now specify additional headers in configuration to be included with outgoing requests; reserved core headers remain protected to avoid unintended overrides.

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

@QuintenQVD0 QuintenQVD0 requested a review from a team as a code owner April 15, 2025 08:01
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for custom headers to be used in remote HTTP requests.

  • Introduces a customHeaders field and a corresponding ClientOption in remote/http.go.
  • Updates the configuration to allow specifying custom headers and passes them via cmd/root.go.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
remote/http.go Adds customHeaders field and WithCustomHeader option, and applies headers in requestOnce.
config/config.go Adds YAML configuration for custom headers.
cmd/root.go Passes custom headers from config into the remote client.
Comments suppressed due to low confidence (2)

remote/http.go:74

  • Consider renaming WithCustomHeader to WithCustomHeaders for consistency with the underlying field name and to accurately reflect that multiple headers may be provided.
func WithCustomHeader(headers map[string]string) ClientOption {

remote/http.go:122

  • Please add unit tests to ensure that custom headers are correctly applied to outgoing requests when provided via the ClientOption.
	for cHeaderKey, cHeaderValue  := range c.customHeaders {

rmartinoscar
rmartinoscar previously approved these changes Jun 28, 2025
Copy link
Member

@rmartinoscar rmartinoscar left a comment

Choose a reason for hiding this comment

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

I agree with AI WithCustomHeader should be plural for consistency sake other then that LGTM

@NaysKutzu
Copy link
Contributor

Been using this for a while and I have no problem with this patch :)

@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Walkthrough

Adds configurable custom HTTP headers for remote queries: new CustomHeaders field in config, a WithCustomHeaders(...) client option passed in cmd/root.go, and logic in the remote HTTP client to apply those headers to outgoing requests while protecting standard headers.

Changes

Cohort / File(s) Summary
Configuration
config/config.go
Adds CustomHeaders map[string]string to RemoteQueryConfiguration with YAML tag custom_headers.
CLI / Initialization
cmd/root.go
Passes remote.WithCustomHeaders(config.Get().RemoteQuery.CustomHeaders) into remote.New(...) when constructing the remote client.
Remote HTTP client
remote/http.go
Adds customHeaders field to client struct, implements func WithCustomHeaders(headers map[string]string) ClientOption, and applies entries from customHeaders to requests in requestOnce, excluding critical headers (Authorization, User-Agent, Accept, Content-Type).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User as User / Config
  participant CLI as rootCmd
  participant Remote as remote.New (client)
  participant HTTP as Panel/API

  Note over User: config supplies custom_headers map
  User->>CLI: read config.RemoteQuery.CustomHeaders
  CLI->>Remote: remote.New(..., WithCustomHeaders(headers), ...)
  Remote->>Remote: client.customHeaders = headers
  Remote->>HTTP: client.requestOnce(...) sets standard headers
  Remote->>HTTP: client iterates client.customHeaders and sets allowed headers
  HTTP-->>Remote: response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Attention points:
    • Ensure nil-safe handling of customHeaders.
    • Verify header key normalization/casing and no accidental overwrite of protected headers.
    • Confirm YAML tag/name and that config load flows into cmd/root.go as expected.

Poem

🐰 I tuck new headers in my satchel tight,

small keys that hop into the light.
From config burrow to HTTP lane,
each gentle header joins the train.
Tiny maps, big network delight.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Custom headers' directly and concisely summarizes the main change across all modified files—adding custom headers support to the remote client configuration.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@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

♻️ Duplicate comments (1)
remote/http.go (1)

73-78: Function name should be plural to match its behavior.

The function accepts a map of multiple headers but uses a singular name. As already noted in previous review comments, this should be WithCustomHeaders (plural) for clarity and consistency.

🧹 Nitpick comments (1)
config/config.go (1)

130-134: Fix comment formatting to follow Go conventions.

The comment block should have a space after // on each line for proper Go formatting.

Apply this diff to fix the formatting:

-	//When using services like Cloudflare Access to manage access to 
-	//a specific system via an external authentication system, 
-	//it is possible to add special headers to bypass authentication. 
-	//The mentioned headers can be appended to queries sent from Wings to the panel.
+	// When using services like Cloudflare Access to manage access to
+	// a specific system via an external authentication system,
+	// it is possible to add special headers to bypass authentication.
+	// The mentioned headers can be appended to queries sent from Wings to the panel.
 	CustomHeaders map[string]string `yaml:"custom_headers"`
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96a1251 and 835b068.

📒 Files selected for processing (3)
  • cmd/root.go (1 hunks)
  • config/config.go (1 hunks)
  • remote/http.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
remote/http.go (1)
remote/types.go (1)
  • ClientOption (29-29)
cmd/root.go (2)
remote/http.go (1)
  • WithCustomHeader (74-78)
config/config.go (1)
  • Get (427-435)
⏰ 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). (3)
  • GitHub Check: Build and Test (ubuntu-22.04, 1.24.7, linux, amd64)
  • GitHub Check: Build and Test (ubuntu-22.04, 1.25.1, linux, amd64)
  • GitHub Check: Analyze (go)
🔇 Additional comments (2)
remote/http.go (1)

45-45: LGTM!

The field declaration is appropriate for storing custom HTTP headers.

cmd/root.go (1)

156-156: LGTM!

The integration correctly passes custom headers from configuration to the remote client. The implementation handles nil maps gracefully.

Copy link

@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: 0

♻️ Duplicate comments (1)
remote/http.go (1)

121-124: Prevent custom headers from overriding critical request headers

Because Header.Set is called after the standard headers, a misconfigured CustomHeaders map can overwrite Authorization (and other important headers), breaking auth or protocol assumptions. It’s safer to explicitly block a small set of protected headers and log that they were ignored.

-	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s.%s", c.tokenId, c.token))
-	
-	for cHeaderKey, cHeaderValue  := range c.customHeaders {
-		req.Header.Set(cHeaderKey, cHeaderValue)
-	} 
+	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s.%s", c.tokenId, c.token))
+
+	// Apply custom headers, but do not allow overriding certain critical ones.
+	protected := map[string]struct{}{
+		"Authorization": {},
+		"Host":          {},
+		// Optionally add: "User-Agent", "Accept", "Content-Type"
+	}
+
+	for key, value := range c.customHeaders {
+		if _, blocked := protected[http.CanonicalHeaderKey(key)]; blocked {
+			log.WithField("header", key).Warn("remote: ignoring custom header attempting to override protected header")
+			continue
+		}
+		req.Header.Set(key, value)
+	}
🧹 Nitpick comments (1)
remote/http.go (1)

39-46: Defensively copy headers in WithCustomHeaders to avoid shared mutable state

Right now you store the caller‑provided map directly on the client. If that map is later mutated (especially from multiple goroutines), the client will see those changes and you can hit data races. Safer to take a shallow copy when the option is created.

-func WithCustomHeaders(headers map[string]string) ClientOption {
-	return func(c *client) {
-		c.customHeaders = headers
-	}
-}
+func WithCustomHeaders(headers map[string]string) ClientOption {
+	// Take a defensive copy so the client has its own immutable view.
+	var copied map[string]string
+	if headers != nil {
+		copied = make(map[string]string, len(headers))
+		for k, v := range headers {
+			copied[k] = v
+		}
+	}
+
+	return func(c *client) {
+		c.customHeaders = copied
+	}
+}

Also applies to: 73-78

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 835b068 and c92a797.

📒 Files selected for processing (2)
  • cmd/root.go (1 hunks)
  • remote/http.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
remote/http.go (1)
remote/types.go (1)
  • ClientOption (29-29)
cmd/root.go (2)
remote/http.go (1)
  • WithCustomHeaders (74-78)
config/config.go (1)
  • Get (427-435)
⏰ 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). (3)
  • GitHub Check: Build and Test (ubuntu-22.04, 1.24.7, linux, amd64)
  • GitHub Check: Build and Test (ubuntu-22.04, 1.25.1, linux, amd64)
  • GitHub Check: Analyze (go)
🔇 Additional comments (1)
cmd/root.go (1)

152-160: Custom headers wiring into remote client looks correct

Passing config.Get().RemoteQuery.CustomHeaders into remote.WithCustomHeaders cleanly exposes the new configuration without changing existing behavior when the map is empty or omitted.

Copy link

@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: 0

♻️ Duplicate comments (1)
remote/http.go (1)

122-133: Header override guard is bypassed by different casing; canonicalize keys before checking

The criticalHeaders map uses canonical names ("Authorization", "User-Agent", etc.), but the guard checks criticalHeaders[key] using the raw user-supplied key. Because HTTP header names are case-insensitive and http.Header.Set canonicalizes keys internally, a user-provided "authorization" key will:

  1. Not match the guard (since "authorization""Authorization" in the map), and
  2. Still overwrite the canonical "Authorization" header when Set is called.

So the protection against overriding critical headers is currently incomplete, and the risk previously noted about custom headers being able to override auth still exists in a slightly different form.

Canonicalizing before the lookup and before Set closes this hole:

-	// Apply custom headers, but prevent overriding critical headers
-	criticalHeaders := map[string]bool{
-		"Authorization": true,
-		"User-Agent":    true,
-		"Accept":        true,
-		"Content-Type":  true,
-	}
-	for key, value := range c.customHeaders {
-		if !criticalHeaders[key] {
-			req.Header.Set(key, value)
-		}
-	}
+	// Apply custom headers, but prevent overriding critical headers.
+	criticalHeaders := map[string]bool{
+		"Authorization": true,
+		"User-Agent":    true,
+		"Accept":        true,
+		"Content-Type":  true,
+		// Optionally also protect "Host" if overriding it should be disallowed.
+	}
+	for key, value := range c.customHeaders {
+		canonicalKey := http.CanonicalHeaderKey(key)
+		if criticalHeaders[canonicalKey] {
+			continue
+		}
+		req.Header.Set(canonicalKey, value)
+	}

If you also want to forbid overriding Host, add "Host": true to criticalHeaders.

🧹 Nitpick comments (1)
remote/http.go (1)

39-46: Field wiring for customHeaders looks fine; consider defensively copying the map

The new field and WithCustomHeaders option are straightforward, but WithCustomHeaders stores the caller’s map by reference. If the same map is mutated while the client is in use (especially from another goroutine), it can cause surprising header changes or even a concurrent map read/write panic in Go.

A small defensive copy would make the client more robust without affecting callers:

-func WithCustomHeaders(headers map[string]string) ClientOption {
-	return func(c *client) {
-		c.customHeaders = headers
-	}
-}
+func WithCustomHeaders(headers map[string]string) ClientOption {
+	// Nil-safe: ranging over a nil map later is fine.
+	copied := make(map[string]string, len(headers))
+	for k, v := range headers {
+		copied[k] = v
+	}
+
+	return func(c *client) {
+		c.customHeaders = copied
+	}
+}

Also applies to: 73-78

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c92a797 and 8321a88.

📒 Files selected for processing (1)
  • remote/http.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
remote/http.go (1)
remote/types.go (1)
  • ClientOption (29-29)
⏰ 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). (3)
  • GitHub Check: Build and Test (ubuntu-22.04, 1.24.7, linux, amd64)
  • GitHub Check: Build and Test (ubuntu-22.04, 1.25.1, linux, amd64)
  • GitHub Check: Analyze (go)

Copy link
Contributor

@NaysKutzu NaysKutzu left a comment

Choose a reason for hiding this comment

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

Still works in my wings (Im testing using cloudflare access and i have it in the header)

Copy link
Contributor

@parkervcp parkervcp left a comment

Choose a reason for hiding this comment

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

LGTM

@parkervcp parkervcp merged commit d3b0581 into pelican-dev:main Dec 19, 2025
7 checks passed
@QuintenQVD0 QuintenQVD0 deleted the custom_headers branch December 26, 2025 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants