Conversation
- Enables $request->getPort() for non-standard ports (8080, 8443) - Falls back to port 80 when connection is not available - Add CHANGELOG entry requirement to CONTRIBUTING.md
- Add SERVER_NAME to server bag to fix getPort() and getSchemeAndHttpHost() - Extract createMockConnection() helper method to avoid DRY violation - Add test for Host header without port scenario
- Add SERVER_NAME from getLocalIp() to fix getPort() when Host header has no port - Add getLocalIp() to mock connection in tests - Update CHANGELOG entry
- Detect HTTPS from connection port 443 - Detect HTTPS from X-Forwarded-Proto header - Set HTTPS=on for HTTPS requests - Add tests for HTTPS detection and URL generation This fixes getScheme() returning 'http' for HTTPS requests.
- Added testHttpsE2E to verify HTTPS detection from port 443 - Added testXForwardedProtoHttpsE2E to verify X-Forwarded-Proto header detection - Updated CHANGELOG with E2E tests entry for #64
s2x
left a comment
There was a problem hiding this comment.
Code Review
Strengths
- Full-stack E2E approach: Tests exercise the complete path (Workerman Request → SymfonyController → RequestConverter → SymfonyRequest), not just unit-level mocks
- Both detection paths covered: Port 443 and X-Forwarded-Proto header each have dedicated tests
- Multi-assertion validation: Each test verifies
HTTPSserver var,isSecure(), andgetScheme()— catching regressions at multiple levels - Clean mock connections: Anonymous classes properly implement required methods (
getLocalPort,getRemoteIp, etc.) withreadonlytyped properties - Follows existing conventions: Matches the established
TestRequestTrackingKernelpattern used by other E2E tests in the file - CHANGELOG updated: Proper entry with issue link
Issues
Important (Should Fix)
1. No negative test for plain HTTP
- Files:
tests/SymfonyControllerTest.php - Problem: There is no test verifying that a regular HTTP request (port 80, no
X-Forwarded-Proto) correctly returnsisSecure() === falseandgetScheme() === 'http'. - Why it matters: Without a negative test, a regression that unconditionally sets
HTTPS = 'on'(e.g. from an overeager refactor) would go undetected — all existing tests would still pass because they only assert the positive path. - How to fix: Add
testHttpE2E()with a connection on port 80 and no forwarded header:$this->assertNull($symfonyRequest->server->get('HTTPS')); $this->assertFalse($symfonyRequest->isSecure()); $this->assertSame('http', $symfonyRequest->getScheme());
2. No test for case-insensitive X-Forwarded-Proto
- File:
tests/SymfonyControllerTest.php:770 - Problem: The implementation lowercases the header value (
strtoloweratRequestConverter.php:35), but there is no test confirming this works with values like"HTTPS"or"Https". - Why it matters: Some reverse proxies (e.g. older HAProxy configs, custom middleware) send uppercase values. Without a test, someone could remove the
strtolowercall and the test suite would not catch it. - How to fix: Either add a dedicated test case with
X-Forwarded-Proto: HTTPS, or add an additional assertion in the existing test with a mixed-case value.
Minor (Nice to Have)
3. Duplicated mock connection classes
- Files:
tests/SymfonyControllerTest.php:726-748,tests/SymfonyControllerTest.php:776-798, andtests/RequestConverterTest.php:344-362 - Problem: The anonymous
TcpConnectionsubclass is copy-pasted across two tests in this file and a third time inRequestConverterTest.php. - Why it matters: If
TcpConnectiongains a new abstract method or changes its constructor signature, all three copies need updating. This is a maintenance burden and a source of future test breakage. - How to fix: Extract to a private helper method
createMockConnection(int \$port): TcpConnectionin each test class, or better — share it via a trait or a common base test class.RequestConverterTest.phpalready has acreateMockConnection()helper that could be reused.
4. No E2E verification of SERVER_PORT value
- Files:
RequestConverter.php:44,tests/SymfonyControllerTest.php - Problem: The converter sets
SERVER_PORTbased on the HTTPS detection logic (\$localPort ?? (\$isHttps ? 443 : 80)). Unit tests inRequestConverterTestcover this, but the E2E tests do not verify it propagates through the full stack. - Why it matters:
getPort()is used bygetSchemeAndHttpHost()and URL generation. If the port mapping breaks somewhere betweenRequestConverterand the finalRequestobject, the E2E tests would not catch it. - How to fix: Add assertions to the HTTPS E2E tests:
\$this->assertSame(443, \$symfonyRequest->getPort()); \$this->assertSame(80, \$symfonyRequest->getPort()); // in the HTTP negative test
Assessment
Ready to merge: No — with fixes
Reasoning: The implementation is solid and the positive-path E2E tests are well-written. The missing negative test (plain HTTP should stay HTTP) is a genuine test gap that could mask a regression where all requests are incorrectly marked as HTTPS. The case-insensitivity test is lower priority but still valuable for defense-in-depth.
s2x
left a comment
There was a problem hiding this comment.
Code Review
Strengths
- Full-stack E2E approach: Tests exercise the complete path (Workerman Request → SymfonyController → RequestConverter → SymfonyRequest), not just unit-level mocks
- Both detection paths covered: Port 443 and X-Forwarded-Proto header each have dedicated tests
- Multi-assertion validation: Each test verifies
HTTPSserver var,isSecure(), andgetScheme()— catching regressions at multiple levels - Clean mock connections: Anonymous classes properly implement required methods (
getLocalPort,getRemoteIp, etc.) withreadonlytyped properties - Follows existing conventions: Matches the established
TestRequestTrackingKernelpattern used by other E2E tests in the file - CHANGELOG updated: Proper entry with issue link
Issues
Important (Should Fix)
1. No negative test for plain HTTP
- Files:
tests/SymfonyControllerTest.php - Problem: There is no test verifying that a regular HTTP request (port 80, no
X-Forwarded-Proto) correctly returnsisSecure() === falseandgetScheme() === 'http'. - Why it matters: Without a negative test, a regression that unconditionally sets
HTTPS = 'on'(e.g. from an overeager refactor) would go undetected — all existing tests would still pass because they only assert the positive path. - How to fix: Add
testHttpE2E()with a connection on port 80 and no forwarded header:$this->assertNull($symfonyRequest->server->get('HTTPS')); $this->assertFalse($symfonyRequest->isSecure()); $this->assertSame('http', $symfonyRequest->getScheme());
2. No test for case-insensitive X-Forwarded-Proto
- File:
tests/SymfonyControllerTest.php:770 - Problem: The implementation lowercases the header value (
strtoloweratRequestConverter.php:35), but there is no test confirming this works with values like"HTTPS"or"Https". - Why it matters: Some reverse proxies (e.g. older HAProxy configs, custom middleware) send uppercase values. Without a test, someone could remove the
strtolowercall and the test suite would not catch it. - How to fix: Either add a dedicated test case with
X-Forwarded-Proto: HTTPS, or add an additional assertion in the existing test with a mixed-case value.
Minor (Nice to Have)
3. Duplicated mock connection classes
- Files:
tests/SymfonyControllerTest.php:726-748,tests/SymfonyControllerTest.php:776-798, andtests/RequestConverterTest.php:344-362 - Problem: The anonymous
TcpConnectionsubclass is copy-pasted across two tests in this file and a third time inRequestConverterTest.php. - Why it matters: If
TcpConnectiongains a new abstract method or changes its constructor signature, all three copies need updating. This is a maintenance burden and a source of future test breakage. - How to fix: Extract to a private helper method
createMockConnection(int \$port): TcpConnectionin each test class, or better — share it via a trait or a common base test class.RequestConverterTest.phpalready has acreateMockConnection()helper that could be reused.
4. No E2E verification of SERVER_PORT value
- Files:
RequestConverter.php:44,tests/SymfonyControllerTest.php - Problem: The converter sets
SERVER_PORTbased on the HTTPS detection logic (\$localPort ?? (\$isHttps ? 443 : 80)). Unit tests inRequestConverterTestcover this, but the E2E tests do not verify it propagates through the full stack. - Why it matters:
getPort()is used bygetSchemeAndHttpHost()and URL generation. If the port mapping breaks somewhere betweenRequestConverterand the finalRequestobject, the E2E tests would not catch it. - How to fix: Add assertions to the HTTPS E2E tests:
\$this->assertSame(443, \$symfonyRequest->getPort()); \$this->assertSame(80, \$symfonyRequest->getPort()); // in the HTTP negative test
Assessment
Ready to merge: No — with fixes
Reasoning: The implementation is solid and the positive-path E2E tests are well-written. The missing negative test (plain HTTP should stay HTTP) is a genuine test gap that could mask a regression where all requests are incorrectly marked as HTTPS. The case-insensitivity test is lower priority but still valuable for defense-in-depth.
- Added testHttpE2E() for plain HTTP (port 80, no HTTPS) - Added testXForwardedProtoCaseInsensitiveE2E() for uppercase header values - Added createMockConnection() helper to reduce duplication - Added SERVER_PORT assertions to verify getPort() works through full stack
Summary
isSecure(),getScheme()return correct valuesChanges
tests/SymfonyControllerTest.php: AddedtestHttpsE2E()andtestXForwardedProtoHttpsE2E()CHANGELOG.md: Updated with E2E tests entry for RequestConverter — Missing HTTPS flag breaks isSecure(), getScheme(), and URL generation #64Issue
Closes #64