Skip to content

Post empty body#2558

Merged
rrayst merged 8 commits into
masterfrom
post-empty-body
Jan 12, 2026
Merged

Post empty body#2558
rrayst merged 8 commits into
masterfrom
post-empty-body

Conversation

@predic8
Copy link
Copy Markdown
Member

@predic8 predic8 commented Jan 7, 2026

Summary by CodeRabbit

  • Bug Fixes

    • POST requests now correctly allow optional request bodies, improving handling of requests without bodies.
  • Tests

    • Refactored tests to use cleaner fixtures and builders for request/response creation.
    • Added a utility to convert raw HTTP message strings into input streams for easier test construction.

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

christiangoerdes and others added 4 commits December 22, 2025 15:51
- Simplified creation of HTTP requests in tests with utility methods (`HttpTestUtil`).
- Consolidated HTTP test resources into reusable format using `convertMessage`.
- Refactored `Request` logic for better readability and modularity.
- Enhanced test coverage and code quality across various HTTP-related test classes (`RequestTest`, `MessageAnalyserTest`, etc.).
- Removed redundant `create` method from `Request` class in favor of streamlined implementations.
…n test classes

- Enhanced return type descriptions in `HttpTestUtil` Javadoc.
- Cleaned up unused `@throws` annotations in `RequestTest`.
- Removed redundant `@SuppressWarnings` in `HttpUtilTest`.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 7, 2026

📝 Walkthrough

Walkthrough

The PR removes a public create(...) initializer from Request, adds METHOD_POST to the set of methods that may have an optional body, refactors multiple tests to use a fluent builder API and an HTTP message test utility, and deletes legacy test resource fixtures.

Changes

Cohort / File(s) Summary
Core Request class modifications
core/src/main/java/com/predic8/membrane/core/http/Request.java
Removed public create(String method, String uri, String protocol, Header header, InputStream in); added METHOD_POST to methodsWithOptionalBody; minor whitespace change.
New test utility
core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java
Added HttpTestUtil.convertMessage(String) to normalize HTTP message strings and return an InputStream.
Request tests refactor
core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
Large rewrite: embedded request fixtures, setup/teardown lifecycle, helper create(...) for tests, many test updates for chunked/empty bodies and read/write semantics.
Test files switched to builder API
core/src/test/java/com/predic8/membrane/core/exchangestore/LimitedMemoryExchangeStoreTest.java, core/src/test/java/com/predic8/membrane/core/interceptor/MessageAnalyserTest.java, core/src/test/java/com/predic8/membrane/core/interceptor/soap/SoapOperationExtractorTest.java
Replaced manual Exchange/Request construction with fluent builders (e.g., post(...).body(...).buildExchange()), adjusted imports and exception signatures.
New/placeholder tests
core/src/test/java/com/predic8/membrane/core/transport/http/HttpServerHandlerTest.java
Added new test class with TODO placeholders.
Test visibility & input changes
core/src/test/java/com/predic8/membrane/core/util/HttpUtilTest.java
Reduced visibility of lifecycle/tests to package-private; replaced resource-based fixture with convertMessage(POST_REQUEST).
Removed test resources
core/src/test/resources/request-chunked-soap.msg, core/src/test/resources/request-post.msg
Deleted legacy HTTP request fixture files.

Sequence Diagram(s)

(omitted — changes are focused on API/test refactor and do not introduce new multi-component control flow)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • refactor code #2033: Refactors Request class logic (e.g., shouldNotContainBody / builder-related changes) touching the same core Request behavior.

Suggested labels

7.x

Suggested reviewers

  • rrayst
  • t-burch

Poem

🐰 I hopped through tests and cleaned the trail,
Builders bloom where old paths once did fail,
A POST may skip its body now and then,
Messages normalized, then built again,
Hooray — a tidy hop, from me to you!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Post empty body' is vague and does not clearly convey the specific changes made in this PR, which involve removing a public create() method, adding POST to methods with optional body, refactoring tests to use fixtures and builders, and removing test resource files. Consider a more specific title that describes the main objective, such as 'Refactor Request creation and test fixtures for POST with optional body' or 'Remove public Request.create() and migrate tests to builder pattern'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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
Copy Markdown
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: 2

🤖 Fix all issues with AI agents
In
@core/src/test/java/com/predic8/membrane/core/transport/http/HttpServerHandlerTest.java:
- Around line 7-8: Fix the typos in the TODO comment inside the
HttpServerHandlerTest class: replace "emty" with "empty" and correct "body.k" to
a proper phrase such as "body." so the comment reads clearly (e.g., "TODO: Start
Router. RESTAssured post empty body."). Update the comment text near the
class/method where the TODO appears so it accurately documents the test intent.

In @core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java:
- Around line 14-16: convertMessage currently calls getBytes() which uses the
platform default charset; update convertMessage to call getBytes with an
explicit charset to ensure consistent test behavior (e.g., use
StandardCharsets.ISO_8859_1 for HTTP message bytes) by replacing getBytes() with
getBytes(StandardCharsets.ISO_8859_1) in the convertMessage method and add the
necessary import or fully-qualified reference to StandardCharsets.
🧹 Nitpick comments (1)
core/src/test/java/com/predic8/membrane/core/http/RequestTest.java (1)

119-149: Consider simplifying tearDown with a helper method.

The manual null checks and close calls are correct but verbose. Consider extracting a helper method to reduce duplication.

♻️ Proposed refactor

Add a helper method and simplify tearDown:

+    private void closeQuietly(AutoCloseable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (Exception e) {
+                // Ignore cleanup exceptions in tests
+            }
+        }
+    }
+
     @AfterEach
     public void tearDown() throws Exception {
-        if (getReq != null) {
-            getReq.close();
-        }
-        if (inPost != null) {
-            inPost.close();
-        }
-        if (inEmptyBody != null) {
-            inEmptyBody.close();
-        }
-        if (inEmptyBodyContentLength != null) {
-            inEmptyBodyContentLength.close();
-        }
-        if (inEmptyBodyContentType != null) {
-            inEmptyBodyContentType.close();
-        }
-        if (inNoChunks != null) {
-            inNoChunks.close();
-        }
-        if (inChunked != null) {
-            inChunked.close();
-        }
-        if (tempIn != null) {
-            tempIn.close();
-        }
-        if (tempOut != null) {
-            tempOut.close();
-        }
-
+        closeQuietly(getReq);
+        closeQuietly(inPost);
+        closeQuietly(inEmptyBody);
+        closeQuietly(inEmptyBodyContentLength);
+        closeQuietly(inEmptyBodyContentType);
+        closeQuietly(inNoChunks);
+        closeQuietly(inChunked);
+        closeQuietly(tempIn);
+        closeQuietly(tempOut);
     }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 225752e and 7df945e.

📒 Files selected for processing (10)
  • core/src/main/java/com/predic8/membrane/core/http/Request.java
  • core/src/test/java/com/predic8/membrane/core/exchangestore/LimitedMemoryExchangeStoreTest.java
  • core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
  • core/src/test/java/com/predic8/membrane/core/interceptor/MessageAnalyserTest.java
  • core/src/test/java/com/predic8/membrane/core/interceptor/soap/SoapOperationExtractorTest.java
  • core/src/test/java/com/predic8/membrane/core/transport/http/HttpServerHandlerTest.java
  • core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java
  • core/src/test/java/com/predic8/membrane/core/util/HttpUtilTest.java
  • core/src/test/resources/request-chunked-soap.msg
  • core/src/test/resources/request-post.msg
💤 Files with no reviewable changes (2)
  • core/src/test/resources/request-post.msg
  • core/src/test/resources/request-chunked-soap.msg
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-06-18T12:03:09.931Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1906
File: core/src/test/java/com/predic8/membrane/core/openapi/validators/JsonSchemaTestSuiteTests.java:0-0
Timestamp: 2025-06-18T12:03:09.931Z
Learning: The mediaType method in the Message class (which Request extends) throws jakarta.mail.internet.ParseException because it creates a ContentType object for parsing MIME media types. The jakarta.mail.internet.ParseException import is correct and necessary in test files that call mediaType().

Applied to files:

  • core/src/test/java/com/predic8/membrane/core/interceptor/MessageAnalyserTest.java
📚 Learning: 2025-06-18T12:03:09.931Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1906
File: core/src/test/java/com/predic8/membrane/core/openapi/validators/JsonSchemaTestSuiteTests.java:0-0
Timestamp: 2025-06-18T12:03:09.931Z
Learning: The mediaType method in the Request class throws jakarta.mail.internet.ParseException, not java.text.ParseException, making the jakarta.mail.internet.ParseException import necessary and correct in JsonSchemaTestSuiteTests.java.

Applied to files:

  • core/src/test/java/com/predic8/membrane/core/interceptor/MessageAnalyserTest.java
  • core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
  • core/src/test/java/com/predic8/membrane/core/util/HttpUtilTest.java
📚 Learning: 2025-09-19T11:12:26.787Z
Learnt from: predic8
Repo: membrane/api-gateway PR: 2156
File: core/src/main/java/com/predic8/membrane/core/openapi/validators/QueryParameterValidator.java:129-131
Timestamp: 2025-09-19T11:12:26.787Z
Learning: Request.get().path() in com.predic8.membrane.core.openapi.model.Request preserves the query string portion of the path, so URIFactory.createWithoutException(request.getPath()).getQuery() correctly extracts query parameters.

Applied to files:

  • core/src/test/java/com/predic8/membrane/core/interceptor/MessageAnalyserTest.java
  • core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
  • core/src/main/java/com/predic8/membrane/core/http/Request.java
🧬 Code graph analysis (4)
core/src/test/java/com/predic8/membrane/core/exchangestore/LimitedMemoryExchangeStoreTest.java (2)
core/src/main/java/com/predic8/membrane/core/http/Response.java (1)
  • Response (38-500)
core/src/main/java/com/predic8/membrane/core/http/Request.java (1)
  • Request (32-357)
core/src/test/java/com/predic8/membrane/core/interceptor/MessageAnalyserTest.java (1)
core/src/main/java/com/predic8/membrane/core/http/Request.java (1)
  • Request (32-357)
core/src/test/java/com/predic8/membrane/core/interceptor/soap/SoapOperationExtractorTest.java (1)
core/src/main/java/com/predic8/membrane/core/http/Request.java (1)
  • Request (32-357)
core/src/test/java/com/predic8/membrane/core/util/HttpUtilTest.java (1)
core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java (1)
  • HttpTestUtil (7-17)
⏰ 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). (1)
  • GitHub Check: Analyze (java)
🔇 Additional comments (12)
core/src/test/java/com/predic8/membrane/core/exchangestore/LimitedMemoryExchangeStoreTest.java (2)

17-23: LGTM!

The migration to wildcard imports and static imports for Response.ok() improves test code readability and aligns with the broader test suite migration to fluent builder patterns.


61-66: LGTM!

The migration to the fluent builder pattern (Request.get("/test").buildExchange() and ok().body(...).build()) simplifies test setup and aligns with the new API design. The broadened exception signature is acceptable for test code.

core/src/test/java/com/predic8/membrane/core/interceptor/soap/SoapOperationExtractorTest.java (2)

16-22: LGTM!

The migration to wildcard imports and static imports for Request.post() and SoapOperationExtractor constants improves test code readability and consistency with the broader test suite refactoring.


69-71: LGTM!

The migration to the fluent builder pattern (post("/test").body(...).buildExchange()) simplifies test setup and correctly passes the resource stream to the body builder. The broadened exception signature is acceptable for test code.

core/src/test/java/com/predic8/membrane/core/interceptor/MessageAnalyserTest.java (3)

23-24: LGTM!

The addition of static imports for Request.post and Response.ok improves test code readability and aligns with the broader test suite refactoring to use fluent builder patterns.


65-69: LGTM!

The migration to the static import ok() improves readability. Note that getResponse() manually creates an Exchange while getRequest() uses buildExchange() — this difference appears intentional since response-only exchanges don't need the full exchange setup with destinations and original URI.


71-73: LGTM!

The migration to the fluent builder pattern (post("/test").body(...).buildExchange()) simplifies test setup and aligns with the new API design. The broadened exception signature is acceptable for test code.

core/src/main/java/com/predic8/membrane/core/http/Request.java (1)

49-59: POST requests can now have optional bodies.

The implementation is correct: METHOD_POST joins METHOD_DELETE and WebDAV methods in methodsWithOptionalBody, allowing POST requests to omit bodies when Content-Length: 0 or when neither Content-Length nor Transfer-Encoding headers are present. The shouldNotContainBody() logic properly handles all cases, and existing tests comprehensively cover empty POST body scenarios (including Content-Length: 0, Transfer-Encoding presence, and implicit empty body). No validation logic in the codebase requires POST to have a body, and this aligns with HTTP specifications.

core/src/test/java/com/predic8/membrane/core/util/HttpUtilTest.java (1)

28-28: LGTM: Clean migration to in-test HTTP construction.

The refactoring to use HttpTestUtil.convertMessage() with an inline POST_REQUEST constant is cleaner and more maintainable than loading from external resource files. The test logic remains correct.

Also applies to: 37-62

core/src/test/java/com/predic8/membrane/core/http/RequestTest.java (3)

48-105: LGTM: Well-structured test fixtures.

The inline HTTP message constants with text blocks are clear and maintainable. The @SuppressWarnings annotation for trailing whitespace in NO_CHUNKS is appropriately documented and necessary for chunked parsing.


151-369: LGTM: Comprehensive test coverage with clean implementation.

The test methods effectively cover various HTTP request scenarios (GET, POST, chunked encoding, empty bodies, OPTIONS, CONNECT). The refactoring to use the new fixture-based approach maintains correctness while improving maintainability.


203-207: LGTM: Well-designed test helper methods.

The helper methods effectively reduce duplication and improve test readability. The create() method provides a test-specific alternative to the removed production initializer and is appropriately scoped for test usage.

Also applies to: 336-340, 365-369, 371-382

Comment thread core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java
@membrane-ci-server
Copy link
Copy Markdown

This pull request needs "/ok-to-test" from an authorized committer.

…ests

- Updated `convertMessage` in `HttpTestUtil` to use UTF-8 encoding explicitly.
- Simplified resource cleanup in `RequestTest` with `closeQuietly`.
- Refactored `shouldBodyBeRead` to clarify logic and improve readability.
Copy link
Copy Markdown
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: 2

🤖 Fix all issues with AI agents
In @core/src/test/java/com/predic8/membrane/core/http/RequestTest.java:
- Around line 204-222: The tests isHTTP11Chunked and isKeepAliveChunked
currently assert on the default request (variable request) but their names imply
they should use chunked input; fix by either (A) creating a chunked request
instance and asserting against it (e.g., build a chunkedRequest with
Transfer-Encoding: chunked or use the existing helper that produces chunked
input, then call chunkedRequest.isHTTP11() and chunkedRequest.isKeepAlive()), or
(B) if the intent was to test default behavior, rename the test methods to
remove the "Chunked" suffix (rename isHTTP11Chunked -> isHTTP11 and
isKeepAliveChunked -> isKeepAlive) and update any duplicated test names to avoid
conflicts; ensure you update assertions to reference the correct variable
(request vs chunkedRequest) and keep method names consistent with the input
used.
- Around line 341-352: The test's create(...) helper directly mutates Request's
internal fields (method, uri, version, header) and calls createBody(in); replace
this with Request's public construction API (e.g., a builder, factory or public
constructor) or add a package-visible factory on Request that accepts method,
uri, protocol and InputStream and performs initialization/validation internally;
update the create(...) method to call that public/factory method instead of
setting fields and invoking createBody(in) so the test relies only on Request's
public behavior.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7df945e and 8ec96d2.

📒 Files selected for processing (2)
  • core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
  • core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-06-18T12:03:09.931Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1906
File: core/src/test/java/com/predic8/membrane/core/openapi/validators/JsonSchemaTestSuiteTests.java:0-0
Timestamp: 2025-06-18T12:03:09.931Z
Learning: The mediaType method in the Request class throws jakarta.mail.internet.ParseException, not java.text.ParseException, making the jakarta.mail.internet.ParseException import necessary and correct in JsonSchemaTestSuiteTests.java.

Applied to files:

  • core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
📚 Learning: 2025-09-19T11:12:26.787Z
Learnt from: predic8
Repo: membrane/api-gateway PR: 2156
File: core/src/main/java/com/predic8/membrane/core/openapi/validators/QueryParameterValidator.java:129-131
Timestamp: 2025-09-19T11:12:26.787Z
Learning: Request.get().path() in com.predic8.membrane.core.openapi.model.Request preserves the query string portion of the path, so URIFactory.createWithoutException(request.getPath()).getQuery() correctly extracts query parameters.

Applied to files:

  • core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
📚 Learning: 2025-06-18T12:03:09.931Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1906
File: core/src/test/java/com/predic8/membrane/core/openapi/validators/JsonSchemaTestSuiteTests.java:0-0
Timestamp: 2025-06-18T12:03:09.931Z
Learning: The mediaType method in the Message class (which Request extends) throws jakarta.mail.internet.ParseException because it creates a ContentType object for parsing MIME media types. The jakarta.mail.internet.ParseException import is correct and necessary in test files that call mediaType().

Applied to files:

  • core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
🧬 Code graph analysis (1)
core/src/test/java/com/predic8/membrane/core/http/RequestTest.java (4)
core/src/main/java/com/predic8/membrane/core/http/MimeType.java (1)
  • MimeType (31-214)
core/src/main/java/com/predic8/membrane/core/http/Request.java (1)
  • Request (32-357)
core/src/test/java/com/predic8/membrane/core/util/HttpTestUtil.java (1)
  • HttpTestUtil (10-20)
core/src/test/java/com/predic8/membrane/core/util/StringTestUtil.java (1)
  • StringTestUtil (19-24)
⏰ 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). (1)
  • GitHub Check: Analyze (java)
🔇 Additional comments (13)
core/src/test/java/com/predic8/membrane/core/http/RequestTest.java (13)

24-27: LGTM: Test import reorganization.

The shift to wildcard static imports for MimeType and HttpTestUtil is appropriate for test files and improves readability by reducing import clutter.


34-85: LGTM: Comprehensive fixture-based test data.

The refactoring from file-based fixtures to embedded string literals using text blocks significantly improves test maintainability. The variety of test cases (GET, POST, chunked encoding, empty body variants) provides good coverage of different HTTP message formats.


86-126: LGTM: Proper resource management in test lifecycle.

The setUp/tearDown pattern ensures all InputStreams are properly initialized and closed, preventing resource leaks in tests.


97-101: LGTM: Clean helper method for body reading verification.

The helper method appropriately encapsulates the logic for verifying whether a request body should be read based on HTTP message structure.


128-146: LGTM: Start line and chunked encoding tests.

These tests appropriately verify request parsing for GET requests and chunked transfer encoding scenarios.


148-162: LGTM: POST and empty chunked body tests.

Good coverage of POST requests with body content and the edge case of chunked encoding with zero-length body.


164-183: LGTM: Comprehensive empty body test coverage.

The three test variants (no body headers, explicit Content-Length: 0, Content-Type only) provide thorough coverage of empty POST body scenarios.


185-202: LGTM: Write/read roundtrip test.

This test appropriately verifies that Request serialization and deserialization preserves both metadata and body content.


224-234: LGTM: Body emptiness checks.

These tests appropriately verify the isBodyEmpty() method using various construction approaches (empty string, empty bytes, GET request, POST with body).


257-333: LGTM: Comprehensive HTTP semantics tests.

These tests provide good coverage of header manipulation, body replacement behavior, OPTIONS/CONNECT method handling, and content type detection. The tests correctly verify that replacing a body triggers reading of the original body to prevent keep-alive session corruption.


335-339: LGTM: Helper method for body retrieval.

Clean extraction of common test logic for reading a message and obtaining its unread body.


354-361: LGTM: Standard resource cleanup utility.

The closeQuietly helper is a standard pattern for test tearDown methods, ensuring resources are closed without propagating exceptions.


237-254: No action needed. The resource file /getBank.xml exists at core/src/test/resources/getBank.xml and is properly accessible to the tests.

Comment thread core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
Comment thread core/src/test/java/com/predic8/membrane/core/http/RequestTest.java
@christiangoerdes christiangoerdes linked an issue Jan 8, 2026 that may be closed by this pull request
@predic8 predic8 requested a review from rrayst January 9, 2026 11:04
@rrayst rrayst merged commit f7e8a67 into master Jan 12, 2026
4 of 5 checks passed
@rrayst rrayst deleted the post-empty-body branch January 12, 2026 18:03
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.

POST with emtpy Body

3 participants