Skip to content

Conversation

@nwoolmer
Copy link
Contributor

@nwoolmer nwoolmer commented Nov 13, 2025

Summary by CodeRabbit

  • New Features

    • Added optional gzip compression for HTTP request bodies (configurable, defaults to off).
    • Server now accepts gzip-encoded incoming request bodies.
  • Tests

    • Added tests covering gzip enabled, disabled, and default behaviors.

@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Walkthrough

Adds optional gzip compression for HTTP request bodies: new gzip SenderOptions flag, conditional compression in BufferStreamContent and HttpSender (headers/length behavior), ILP endpoint decompression for requests with Content-Encoding: gzip, and tests for gzip enabled/disabled/default behaviors.

Changes

Cohort / File(s) Summary
Core Configuration
src/net-questdb-client/Utils/SenderOptions.cs
Added public gzip boolean property with parsing from config strings (default false). Expanded allowed keys and included gzip in ToString serialization.
HTTP Content Serialization
src/net-questdb-client/Buffers/BufferStreamContent.cs
Added gzip constructor parameter (default false). When gzip is true, serialization wraps output in GZipStream; TryComputeLength returns false for compressed content.
HTTP Request Generation
src/net-questdb-client/Senders/HttpSender.cs
Passes Options.gzip into BufferStreamContent. When gzip enabled, adds Content-Encoding: gzip and omits Content-Length; when disabled, retains previous behavior.
ILP Endpoint Decompression
src/dummy-http-server/IlpEndpoint.cs
Detects Content-Encoding: gzip on incoming requests and decompresses the request stream using GZipStream before processing.
Feature Tests
src/net-questdb-client-tests/HttpTests.cs
Added tests GzipCompressionEnabled, GzipCompressionDisabled, and GzipCompressionDefault to validate compressed vs uncompressed behavior; incidental formatting adjustments present.
Configuration Tests
src/net-questdb-client-tests/SenderOptionsTests.cs
Added tests for gzip default value, parsing of true/false, and ToString containing gzip=True when set; updated expected serialized option strings.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant HttpSender
    participant BufferStreamContent
    participant GZipStream
    participant HttpRequest
    participant IlpEndpoint

    Client->>HttpSender: GenerateRequest(buffer)
    HttpSender->>HttpSender: Check Options.gzip
    alt gzip enabled
        HttpSender->>BufferStreamContent: new(buffer, gzip=true)
        HttpSender->>HttpRequest: Add header Content-Encoding: gzip
        HttpSender->>HttpRequest: Omit Content-Length
    else gzip disabled
        HttpSender->>BufferStreamContent: new(buffer, gzip=false)
        HttpSender->>HttpRequest: Set Content-Length
    end

    HttpRequest->>BufferStreamContent: SerializeToStreamAsync()
    alt gzip=true
        BufferStreamContent->>GZipStream: wrap output stream and write compressed data
        GZipStream->>HttpRequest: Compressed body
    else gzip=false
        BufferStreamContent->>HttpRequest: Uncompressed body
    end

    HttpRequest->>IlpEndpoint: POST with body
    IlpEndpoint->>IlpEndpoint: Inspect Content-Encoding
    alt Content-Encoding: gzip
        IlpEndpoint->>GZipStream: Decompress request stream
        GZipStream->>IlpEndpoint: Decompressed data
    else none
        IlpEndpoint->>IlpEndpoint: Use original stream
    end
    IlpEndpoint->>IlpEndpoint: Process data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

  • Pay attention to stream lifecycle and disposal in BufferStreamContent (compression path).
  • Verify header/length behavior and HTTP semantics in HttpSender.
  • Confirm safe replacement/seek behavior in IlpEndpoint decompression.
  • Validate SenderOptions parsing/serialization consistency.

Poem

🐰 Hop and nibble, bytes in a line,

gzip hugs them, making them fine.
From Sender to Endpoint they flow,
snugged by compression, ready to go.
Tests hop along — all set to show!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.92% 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 pull request title 'feat: support sending gzip-encoded buffers' directly and accurately summarizes the main change—adding gzip compression support for HTTP request bodies throughout the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-gzip

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 419c7f4 and fca4309.

📒 Files selected for processing (1)
  • src/dummy-http-server/IlpEndpoint.cs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/dummy-http-server/IlpEndpoint.cs

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e68a909 and 419c7f4.

📒 Files selected for processing (6)
  • src/dummy-http-server/IlpEndpoint.cs (2 hunks)
  • src/net-questdb-client-tests/HttpTests.cs (51 hunks)
  • src/net-questdb-client-tests/SenderOptionsTests.cs (2 hunks)
  • src/net-questdb-client/Buffers/BufferStreamContent.cs (3 hunks)
  • src/net-questdb-client/Senders/HttpSender.cs (1 hunks)
  • src/net-questdb-client/Utils/SenderOptions.cs (4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-17T16:38:52.474Z
Learnt from: RaphDal
Repo: questdb/net-questdb-client PR: 52
File: src/net-questdb-client/Senders/ISender.cs:410-418
Timestamp: 2025-10-17T16:38:52.474Z
Learning: In src/net-questdb-client/Senders/ISender.cs, the decimal type intentionally does not have a NullableColumn overload. This is a deliberate design decision because NullableColumn is deprecated in favor of using the Column method directly with nullable types.

Applied to files:

  • src/net-questdb-client-tests/HttpTests.cs
📚 Learning: 2025-10-17T16:37:03.583Z
Learnt from: RaphDal
Repo: questdb/net-questdb-client PR: 52
File: src/dummy-http-server/DummyHttpServer.cs:228-299
Timestamp: 2025-10-17T16:37:03.583Z
Learning: In src/dummy-http-server/DummyHttpServer.cs, the PrintBuffer() method is a test helper that produces human-readable output from received bytes. Decimal tests use binary representation directly via DecimalTestHelpers and do not call PrintBuffer, so DECIMAL type decoding in PrintBuffer is not required.

Applied to files:

  • src/net-questdb-client-tests/HttpTests.cs
🧬 Code graph analysis (4)
src/net-questdb-client/Buffers/BufferStreamContent.cs (2)
src/net-questdb-client/Buffers/IBuffer.cs (16)
  • IBuffer (66-66)
  • IBuffer (74-74)
  • IBuffer (84-84)
  • IBuffer (97-97)
  • IBuffer (105-105)
  • IBuffer (113-113)
  • IBuffer (121-121)
  • IBuffer (129-129)
  • IBuffer (137-137)
  • IBuffer (145-145)
  • IBuffer (153-153)
  • IBuffer (228-228)
  • IBuffer (235-235)
  • IBuffer (248-248)
  • IBuffer (260-260)
  • WriteToStream (221-221)
src/net-questdb-client/Buffers/BufferV1.cs (1)
  • WriteToStream (224-245)
src/net-questdb-client/Senders/HttpSender.cs (1)
src/net-questdb-client/Buffers/BufferStreamContent.cs (2)
  • BufferStreamContent (34-115)
  • BufferStreamContent (41-45)
src/net-questdb-client-tests/HttpTests.cs (3)
src/dummy-http-server/DummyHttpServer.cs (8)
  • DummyHttpServer (36-306)
  • DummyHttpServer (54-112)
  • Exception (185-188)
  • Task (141-152)
  • Task (157-160)
  • Task (162-165)
  • Task (190-194)
  • PrintBuffer (226-305)
src/net-questdb-client/Buffers/BufferStreamContent.cs (3)
  • Task (51-62)
  • Task (65-76)
  • Task (93-99)
src/net-questdb-client-tests/SenderOptionsTests.cs (12)
  • Test (36-42)
  • Test (44-50)
  • Test (52-59)
  • Test (61-69)
  • Test (71-77)
  • Test (79-87)
  • Test (89-97)
  • Test (99-109)
  • Test (111-116)
  • Test (118-123)
  • Test (125-130)
  • Test (132-137)
src/net-questdb-client-tests/SenderOptionsTests.cs (1)
src/net-questdb-client/Utils/SenderOptions.cs (4)
  • SenderOptions (91-93)
  • SenderOptions (99-125)
  • SenderOptions (684-690)
  • ToString (610-655)
🔇 Additional comments (14)
src/net-questdb-client/Utils/SenderOptions.cs (3)

56-56: LGTM!

The gzip option is correctly added to the allowed keys set and the private field is appropriately initialized to false, ensuring backward compatibility.

Also applies to: 66-66


109-109: LGTM!

The parsing logic correctly uses ParseBoolWithDefault with a false default, maintaining consistency with other boolean configuration options.


220-232: LGTM!

The property is well-documented with clear remarks about HTTP/HTTPS applicability. The implementation follows standard patterns.

src/net-questdb-client/Senders/HttpSender.cs (2)

238-242: LGTM!

The BufferStreamContent is correctly instantiated with the gzip option, and the documentation accurately reflects the optional compression behavior.


245-256: LGTM!

The header handling correctly omits Content-Length when gzip is enabled (since compressed size cannot be known ahead of time) and properly adds the Content-Encoding: gzip header. This follows HTTP standards for compressed content.

src/net-questdb-client-tests/SenderOptionsTests.cs (2)

76-76: LGTM!

Existing tests correctly updated to include gzip=False in the expected ToString() output, maintaining test validity.

Also applies to: 108-108


111-137: LGTM!

Comprehensive test coverage for the new gzip option, verifying default value, parsing of both true/false values, and serialization. Tests follow existing patterns in the file.

src/net-questdb-client-tests/HttpTests.cs (1)

1744-1814: Good test coverage, but depends on buggy server code.

The three new tests provide comprehensive coverage of gzip behavior:

  • Enabled: verifies compressed data is sent and received
  • Disabled: verifies uncompressed data is sent
  • Default: verifies backward compatibility (default is uncompressed)

However, these tests will fail due to the critical bug in IlpEndpoint.cs (lines 65-73) where the decompressed stream is disposed before use. Once that bug is fixed, these tests should work correctly.

src/net-questdb-client/Buffers/BufferStreamContent.cs (6)

40-48: LGTM!

The constructor cleanly accepts an optional gzip parameter with a default of false, maintaining backward compatibility. Documentation is clear.


53-62: LGTM!

Correct implementation using GZipStream with leaveOpen: true to prevent premature disposal of the underlying stream. The conditional logic properly handles both compressed and uncompressed paths.


67-76: LGTM!

Correctly implements the cancellation token overload with the same gzip logic pattern, properly propagating the cancellation token through the call chain.


81-90: LGTM!

Correctly returns false when gzip is enabled since compressed size cannot be determined ahead of time. The comment clearly explains the rationale.


97-97: LGTM!

The Seek to the beginning ensures the content stream is positioned correctly for reading after serialization.


105-114: LGTM!

The synchronous serialization method correctly mirrors the async implementation with proper cancellation token handling and gzip compression logic.

@ideoma ideoma merged commit 79b783c into main Nov 14, 2025
2 checks passed
@ideoma ideoma deleted the feat-gzip branch November 14, 2025 11:18
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.

3 participants