Skip to content

Dev - #8

Merged
milinsky merged 59 commits into
mainfrom
dev
May 21, 2026
Merged

Dev#8
milinsky merged 59 commits into
mainfrom
dev

Conversation

@milinsky

@milinsky milinsky commented May 19, 2026

Copy link
Copy Markdown
Member

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Checklist

  • I have read the CONTRIBUTING.md
  • My code follows the code style of this project
  • I have added tests to cover my changes
  • All new and existing tests passed
  • I have updated the documentation
  • My changes generate no new warnings
  • I have added changelog entry

Test Coverage

Screenshots (if applicable)

Additional Notes

milinsky added 25 commits May 19, 2026 21:04
- Create readonly CorsService with origin whitelist, wildcard support,
  credentials handling, Vary headers for CDN/proxy cache safety
- Add 7 CORS parameters to ServerConfig with validation
  (wildcard+credentials blocked per spec)
- Integrate preflight at Server level before processor queue
- Add CORS headers to regular responses via HttpRequestProcessor
- Add host validation in ServerConfig (FILTER_VALIDATE_IP + DOMAIN)
- Add 25 tests (22 CorsService + 3 ServerConfig CORS)
- Add CSP generation with directive array, nonce support, report-only mode
- Replace X-XSS-Protection: 1; mode=block with 0 (deprecated header)
- Add Permissions-Policy array-based builder with format validation
- Make HSTS fully configurable (max-age, includeSubDomains, preload)
- Add hstsMaxAge validation in ServerConfig (non-negative when enabled)
- Optimize nonce generation (only when CSP is configured)
- Add 18 new tests (CSP, HSTS, Permissions-Policy, hstsMaxAge)
- Add consumeBuffer() to Connection/ConnectionInterface for pipelining support
- Fix pipelining: consume exact request bytes, preserve remainder for next
- Pass only first request data to RequestParser (prevent body contamination)
- Fix rate limit path: consume buffer to prevent infinite 429 loop
- Fix CORS preflight: use consumeBuffer instead of clearBuffer
- Integrate AuditLogger in HttpRequestProcessor (timeout, too large, rate limit)
- Add Date header in RFC 7231 format via ResponseWriter
- Add SSL error logging in SslSocket bind() and accept()
- Add 7 new tests (consumeBuffer, Date, pipelining, AuditLogger)
- Replace N per-connection socket_select calls with single batched select
- Add stream_select for resource-based connections (mixed Socket/resource)
- Add readFromConnectionDirect() and processWebSocketDataDirect() for
  post-select data reading without redundant select
- Implement IteratorAggregate on ConnectionPool for lazy iteration
- Remove array_values() from fibers hot path (sparse keys OK with foreach)
- Preserve original methods for backward compatibility
… HttpRequestProcessor

- Extract RequestQueue + RequestQueueInterface (SplQueue + contexts, orphan-safe dequeue)
- Extract ResponseSender + ResponseSenderInterface (readonly, send/sendError)
- Extract ClientIpResolver utility (right-to-left XFF walking, trusted proxy support)
- Add StreamSocketResource::select() for socket_select/stream_select encapsulation
- Refactor HttpRequestProcessor as coordinator delegating to queue + sender
- ServerInterface unchanged (worker-pool contract preserved)
- 1104 tests, Psalm level 1 clean, cs-fix clean
…eplacement

- Replace callable params in HttpRequestProcessor with typed interfaces
- Add WebSocketUpgradeHandlerInterface + EventLoopNotifierInterface
- Add adapter classes wrapping callables behind interfaces (readonly)
- Logger injected through constructors (NullLogger default)
- Server::setLogger() propagates to all sub-components
- setLogger() preserved on Server + WebSocketServer (backward compat)
- Removed setLogger() from HttpRequestProcessor, ConnectionManager, WebSocketHandler
  (re-added as package-internal methods for Server propagation)
- 1104 tests, Psalm level 1 clean, cs-fix clean
- Create RequestLifecycleInterface (5 methods: hasRequest, getRequest, respond, hasPendingResponse, getPendingRequestId)
- Create ServerLifecycleInterface (5 methods: start, stop, reset, restart, shutdown)
- Create WorkerPoolIntegrationInterface (16 methods: worker pool, fibers, notification, socket resources)
- Create MetricsInterface (1 method: getMetrics)
- ServerInterface now extends all 4 sub-interfaces
- setLogger() and attachWebSocket() remain directly on ServerInterface (cross-cutting)
- Server implementation unchanged — backward compatible with worker-pool
- Add instanceof compliance tests for each sub-interface
- Replace callable params with typed interfaces (WebSocketUpgradeHandler, EventLoopNotifier)
- Logger injection via constructors with NullLogger default
- 1109 tests, Psalm level 1 clean, cs-fix clean
…, HTTPS, KeepAlive)

- FullRequestCycleTest: GET, POST, multipart, large body (256KB), sequential requests (8 tests)
- WebSocketCycleTest: upgrade handshake, text/binary/ping/pong/close frames, RFC 6455 encode/decode (12 tests)
- WorkerPoolModeTest: setWorkerId, addExternalConnection via stream_socket_pair, fiber registration, event loop (11 tests)
- HttpsTest: TLS handshake with self-signed cert, GET/POST over SSL (2 tests)
- KeepAliveTest: multiple requests per connection, max requests, Connection: close (5 tests)
- ShutdownHandlerStubTest: ProductionErrorHandler signal/shutdown/error/exception stubs (17 tests)
- All tests use random ports via findAvailablePort(), proper tearDown cleanup
- 1164 tests total, Psalm level 1 clean, cs-fix clean
Security tests (47 tests):
- PathTraversalTest: ../etc/passwd, double encoding, null byte, backslash (10 tests)
- RequestSmugglingTest: CL/TE mismatch, double CL, chunked, pipelining (6 tests)
- RateLimitBypassTest: 429 on excess, X-Forwarded-For spoofing, shared counter (6 tests)
- WebSocketOriginTest: whitelist, empty origin, validation disabled (10 tests)
- DosProtectionTest: oversized body (413), maxConnections enforcement (4 tests)

Performance tests (11 tests):
- ThroughputTest: 1000 req/sec baseline via keep-alive (2 tests)
- MemoryUsageTest: 10K requests <1MB growth, bounded cache (3 tests)
- ConnectionPoolTest: max connections, excess rejection, cleanup (6 tests)

Naming audit:
- Renamed 925 methods to snake_case with #[Test] attribute
- Removed 17 assertTrue(true) anti-patterns
- Replaced @ operator with error_reporting() pattern
- 1209 tests, Psalm level 1 clean, cs-fix clean
…t coverage

- Add Security Configuration section: CORS, CSP, HSTS, Permissions-Policy
- Add Architecture Overview with ASCII diagrams
- Update ServerConfig options with all new parameters
- Add unit tests for ExistingSocket, StreamSocket, WebSocketHandler
- Add ServerConfigValidationTest, ConnectionPoolExtendedTest
- Add StaticFileHandlerCoverageTest, TempFileManagerCoverageTest
- Line coverage: 82% (socket operations not mockable without wrappers)
milinsky added 4 commits May 20, 2026 17:03
Add two new methods to the socket resource interface for peer address resolution and stream export capability.
Implement peer address resolution via socket_getpeername/stream_socket_get_name and stream export via socket_export_stream with proper error handling.
…lasses

Add getPeerName() and exportStream() implementations to StreamSocket, ExistingSocket, and SslSocket with unified error handling patterns.
milinsky added 27 commits May 20, 2026 19:53
…getPeerName() in ConnectionManager

Remove direct socket_* calls from ConnectionManager::acceptFromServerSocket(). Uses getPeerName() interface method instead. 9 new tests, 100% coverage of changed method.
… Server

Replace socket_getpeername(), socket_strerror(), socket_last_error(), stream_socket_get_name() with StreamSocketResource::getPeerName() in addExternalConnection(). Replace socket_set_block(), socket_export_stream(), socket_set_nonblock() with StreamSocketResource::exportStream() in exportToStream(). 15 new tests, 100% coverage on changed methods.
… in NotificationManager

Inject NotificationSocketPairInterface via constructor DI. Replace socket_create_pair, socket_close, socket_write with interface methods. Update Server constructor to inject SocketNotificationPair. 12 new tests, 100% coverage.
…ethod

- Extract resolveKeepAlive() in HttpRequestProcessor (3 duplicate blocks → 1 method)
- Server::handleCorsPreflight() delegates to processor
- Behavioral fix: block 2 now uses opt-out logic (HTTP/1.1 compliant, RFC 7230 §6.3)
- Add 13 unit tests covering all resolveKeepAlive scenarios
Add closeConnectionWithMetrics() to ConnectionManagerInterface.
HttpRequestProcessor now delegates close connection via setter-injected
ConnectionManagerInterface, eliminating duplicate close logic.
Restore debug-mode logging in closeConnectionWithMetrics() for
observability parity.
After task 03 changed keep-alive from opt-in to opt-out, requests
without Connection header now get keepAlive=true. This caused
stream_get_contents to block waiting for EOF, spacing requests beyond
the rate limit window (10s) and allowing all requests through.
Removed 205 calls across 10 test files. All methods and properties
are accessible by default via Reflection in PHP 8.1+.
…(0) in tests

Replace 53 inline error_reporting(0)/restore patterns with a reusable
trait that guarantees error level restoration via try/finally. Applied
across 21 test files.
…ions

Replaced 36 no-op assertion stubs across 14 test files with actual
behavior verification: connection counts, state checks, mock verify,
and exception expectations.
Add #[Group("ev")] to 14 ev-dependent methods and #[Group("pcntl")]
to 16 pcntl-dependent methods. Update phpunit.xml.dist with
failOnRisky, failOnWarning, failOnNotice, stopOnSkipped and exclude
ev/pcntl groups from default runs.
Replace real socket_create_pair with mock NotificationSocketPairInterface.
11 tests cover all branches: enable/disable/notify/reset/exception propagation.
100% coverage achieved. PSR-3 mock logger verifies logging.
Add unit tests for acceptFromServerSocket, readFromConnectionDirect,
closeConnectionWithMetrics, cleanupTimedOut, and pool operations.
All via mock SocketResourceInterface — no real sockets.
Remove duplicate test and real socket tests after review.
Add unit tests for addExternalConnection and exportToStream using mock
SocketResourceInterface. Refactor Server to accept SocketResourceInterface
alongside Socket for testability (backward compatible union type).
Add WebSocketHandlerFrameLoopTest and WebSocketServerProcessPingsTest.
Cover frame processing, ping/pong lifecycle, connection cleanup,
and error handling — all via mock Connection.
Add tests for socket errors, timeout scenarios, malformed HTTP input,
connection cleanup, response write errors, and server lifecycle edge cases.
All tests use mock connections — no real sockets.

Files: ConnectionEdgeCases, ConnectionManagerEdgeCases, HttpParserEdgeCases,
HttpRequestProcessorEdgeCases, ResponseSenderEdgeCases, ServerEdgeCases.
…ation

Add SocketNotificationPairIntegrationTest (createPair, notify, close,
isEnabled) and SocketResourceIntegrationTest (getPeerName, exportStream).
Fix minor issue in NotificationEdgeCasesTest.

Final metrics: 1363+ tests, 0 setAccessible(true), 0 error_reporting(0)
in tests (except ErrorReportingScope helper), Psalm level 1 pass,
cs-fix clean.
…tions

PHPUnit 13 generates notices for createMock() calls without ->expects().
Replace with createStub() to eliminate 171 PHPUnit notices from test output.

Result: 1344 unit tests, 0 notices, 0 failures.
Add optional $errorOutput Closure to ErrorHandler constructor for
testable STDERR output. Default null preserves production behavior.
Replace error_log() in SslSocket with PSR-3 logger.
Pass no-op closure in ErrorHandlerTest and ShutdownHandlerStubTest.

Result: clean test output without [FATAL], [CRITICAL], [SIGNAL],
SSL accept error messages.
@sonarqubecloud

Copy link
Copy Markdown

@milinsky
milinsky merged commit 360b615 into main May 21, 2026
3 checks passed
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.

1 participant