Skip to content

write-tee: add HTTPgRPC support#14507

Merged
pracucci merged 7 commits intowrite-teefrom
write-tee-httpgrpc
Feb 27, 2026
Merged

write-tee: add HTTPgRPC support#14507
pracucci merged 7 commits intowrite-teefrom
write-tee-httpgrpc

Conversation

@pracucci
Copy link
Collaborator

What this PR does

Add HTTPgRPC support.

Which issue(s) this PR fixes or relates to

Fixes #

Checklist

  • Tests updated.
  • Documentation added.
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX]. If changelog entry is not needed, please add the changelog-not-needed label to the PR.
  • about-versioning.md updated with experimental features.

Signed-off-by: Marco Pracucci <marco@pracucci.com>
@pracucci pracucci added the changelog-not-needed PRs that don't need a CHANGELOG.md entry label Feb 26, 2026
pracucci and others added 3 commits February 26, 2026 18:44
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Signed-off-by: Marco Pracucci <marco@pracucci.com>
@pracucci pracucci marked this pull request as ready for review February 27, 2026 11:22
@pracucci pracucci requested a review from a team as a code owner February 27, 2026 11:22
Signed-off-by: Marco Pracucci <marco@pracucci.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Autofix Details

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Backends closed before async requests finish draining
    • Moved backend Close() calls from Stop() to Await(), after async dispatcher drains in-flight requests, preventing gRPC connections from being closed while still in use.
  • ✅ Fixed: Query parameters dropped in gRPC request URL
    • Added RawQuery appending to the request URL in createGRPCRequest to preserve query parameters, matching HTTP backend behavior and HTTPgRPC protocol expectations.

Create PR

Or push these changes by commenting:

@cursor push de6bbf260e
Preview (de6bbf260e)
diff --git a/tools/writetee/proxy.go b/tools/writetee/proxy.go
--- a/tools/writetee/proxy.go
+++ b/tools/writetee/proxy.go
@@ -379,13 +379,6 @@
 		p.asyncDispatcher.Stop()
 	}
 
-	// Close all backends (important for gRPC backends to close connections).
-	for _, backend := range p.backends {
-		if err := backend.Close(); err != nil {
-			level.Warn(p.logger).Log("msg", "failed to close backend", "backend", backend.Name(), "err", err)
-		}
-	}
-
 	return nil
 }
 
@@ -397,4 +390,13 @@
 	if p.asyncDispatcher != nil {
 		p.asyncDispatcher.Await()
 	}
+
+	// Close all backends (important for gRPC backends to close connections).
+	// This must happen after async dispatcher has drained to avoid closing
+	// connections while in-flight requests are still using them.
+	for _, backend := range p.backends {
+		if err := backend.Close(); err != nil {
+			level.Warn(p.logger).Log("msg", "failed to close backend", "backend", backend.Name(), "err", err)
+		}
+	}
 }

diff --git a/tools/writetee/proxy_backend_grpc.go b/tools/writetee/proxy_backend_grpc.go
--- a/tools/writetee/proxy_backend_grpc.go
+++ b/tools/writetee/proxy_backend_grpc.go
@@ -123,6 +123,10 @@
 
 	// Build the URL path with endpoint path prefix.
 	reqPath := path.Join(b.endpoint.Path, orig.URL.Path)
+	// Append query string if present
+	if orig.URL.RawQuery != "" {
+		reqPath = reqPath + "?" + orig.URL.RawQuery
+	}
 
 	// Clone headers for the gRPC request.
 	headers := make(http.Header)

Signed-off-by: Marco Pracucci <marco@pracucci.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Shallow header copy shares slices with original request
    • Replaced shallow header copy loop with orig.Header.Clone() to ensure independent header value slices, aligning with the HTTP backend's approach.

Create PR

Or push these changes by commenting:

@cursor push 053b06a86c
Preview (053b06a86c)
diff --git a/tools/writetee/proxy_backend_grpc.go b/tools/writetee/proxy_backend_grpc.go
--- a/tools/writetee/proxy_backend_grpc.go
+++ b/tools/writetee/proxy_backend_grpc.go
@@ -128,10 +128,7 @@
 	}
 
 	// Clone headers for the gRPC request.
-	headers := make(http.Header)
-	for k, v := range orig.Header {
-		headers[k] = v
-	}
+	headers := orig.Header.Clone()
 
 	// Remove headers that are not relevant for HTTPgRPC backends.
 	headers.Del("Authorization")

Signed-off-by: Marco Pracucci <marco@pracucci.com>
@pracucci pracucci merged commit 272cb4f into write-tee Feb 27, 2026
45 checks passed
@pracucci pracucci deleted the write-tee-httpgrpc branch February 27, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-not-needed PRs that don't need a CHANGELOG.md entry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants