Summary
HttpRequest and HttpResponse currently store all request/response state in ~15+ static properties spread across ~10 traits. This makes it impossible to run two application executions in the same process without state leaking between them, and complicates test isolation.
This ticket converts HttpRequest/HttpResponse (and their traits) from static state to instance-based state, with instances managed by the DI container.
Parent Issue
Subtask of #373 (Refactor App Bootstrapping & DI Ownership Model).
Problem
Current static properties in the HTTP layer:
HttpRequest (src/Http/Request/HttpRequest.php):
$__method, $server, $initialized
Request traits:
- Url:
$__protocol, $__host, $__port, $__uri
- Query:
$__query
- Header:
$__headers
- Body:
$__request
- File:
$__files
- Route:
$route
- Params:
$__contentType
HttpResponse (src/Http/Response/HttpResponse.php):
$xmlRoot, $callbackFunction, $initialized
Response traits:
- Body:
$__response, $formatters
- Header:
$__headers
- Status:
$__statusCode, $texts
All of these are private static or protected static — they survive across executions in the same process, causing state leakage.
Proposed Changes
- Convert all static properties in HttpRequest, HttpResponse, and their traits to instance properties
- Convert static methods that access these properties to instance methods
- Register Request and Response instances in DI during the boot pipeline
- Update all consumers (helpers, adapters, router, middleware, LangFactory, etc.) to resolve Request/Response from DI instead of calling static methods
- Ensure
Di::autowire() continues to inject Request/Response into controller methods
Affected Areas
Core HTTP classes
src/Http/Request/HttpRequest.php
src/Http/Response/HttpResponse.php
src/Http/Traits/Request/Url.php
src/Http/Traits/Request/Query.php
src/Http/Traits/Request/Header.php
src/Http/Traits/Request/Body.php
src/Http/Traits/Request/File.php
src/Http/Traits/Request/Route.php
src/Http/Traits/Request/Params.php
src/Http/Traits/Request/RawInput.php
src/Http/Traits/Request/Internal.php
src/Http/Traits/Response/Body.php
src/Http/Traits/Response/Header.php
src/Http/Traits/Response/Status.php
Consumers that call Request/Response statically
src/Http/Helpers/http.php
src/Router/RouteDispatcher.php
src/Router/RouteFinder.php
src/Router/Helpers/router.php
src/Lang/Factories/LangFactory.php (getLangFromQuery, getLangFromUrlSegment)
src/Middleware/MiddlewareManager.php
src/App/Adapters/WebAppAdapter.php
src/Csrf/Csrf.php
src/View/Helpers/view.php
- Tests across
Unit/Http/, Unit/Router/, Unit/App/
Acceptance Criteria
- No
private static or protected static properties storing request/response state
- Request and Response are DI-managed instances
- All existing tests pass
- Controller autowiring still injects Request/Response correctly
- Helper functions (
redirect(), redirectWith(), old(), get_referrer(), etc.) work unchanged
Context
This is a prerequisite for making AppContext the true execution state holder (#373) and for the Di facade/DiContainer split. Once Request/Response are instance-based and DI-managed, each application execution can have its own isolated HTTP state.
Summary
HttpRequest and HttpResponse currently store all request/response state in ~15+ static properties spread across ~10 traits. This makes it impossible to run two application executions in the same process without state leaking between them, and complicates test isolation.
This ticket converts HttpRequest/HttpResponse (and their traits) from static state to instance-based state, with instances managed by the DI container.
Parent Issue
Subtask of #373 (Refactor App Bootstrapping & DI Ownership Model).
Problem
Current static properties in the HTTP layer:
HttpRequest (
src/Http/Request/HttpRequest.php):$__method,$server,$initializedRequest traits:
$__protocol,$__host,$__port,$__uri$__query$__headers$__request$__files$route$__contentTypeHttpResponse (
src/Http/Response/HttpResponse.php):$xmlRoot,$callbackFunction,$initializedResponse traits:
$__response,$formatters$__headers$__statusCode,$textsAll of these are
private staticorprotected static— they survive across executions in the same process, causing state leakage.Proposed Changes
Di::autowire()continues to inject Request/Response into controller methodsAffected Areas
Core HTTP classes
src/Http/Request/HttpRequest.phpsrc/Http/Response/HttpResponse.phpsrc/Http/Traits/Request/Url.phpsrc/Http/Traits/Request/Query.phpsrc/Http/Traits/Request/Header.phpsrc/Http/Traits/Request/Body.phpsrc/Http/Traits/Request/File.phpsrc/Http/Traits/Request/Route.phpsrc/Http/Traits/Request/Params.phpsrc/Http/Traits/Request/RawInput.phpsrc/Http/Traits/Request/Internal.phpsrc/Http/Traits/Response/Body.phpsrc/Http/Traits/Response/Header.phpsrc/Http/Traits/Response/Status.phpConsumers that call Request/Response statically
src/Http/Helpers/http.phpsrc/Router/RouteDispatcher.phpsrc/Router/RouteFinder.phpsrc/Router/Helpers/router.phpsrc/Lang/Factories/LangFactory.php(getLangFromQuery, getLangFromUrlSegment)src/Middleware/MiddlewareManager.phpsrc/App/Adapters/WebAppAdapter.phpsrc/Csrf/Csrf.phpsrc/View/Helpers/view.phpUnit/Http/,Unit/Router/,Unit/App/Acceptance Criteria
private staticorprotected staticproperties storing request/response stateredirect(),redirectWith(),old(),get_referrer(), etc.) work unchangedContext
This is a prerequisite for making AppContext the true execution state holder (#373) and for the Di facade/DiContainer split. Once Request/Response are instance-based and DI-managed, each application execution can have its own isolated HTTP state.