Skip to content

Convert HttpRequest/HttpResponse from static to instance-based #454

Description

@armanist

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

  1. Convert all static properties in HttpRequest, HttpResponse, and their traits to instance properties
  2. Convert static methods that access these properties to instance methods
  3. Register Request and Response instances in DI during the boot pipeline
  4. Update all consumers (helpers, adapters, router, middleware, LangFactory, etc.) to resolve Request/Response from DI instead of calling static methods
  5. 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.

Metadata

Metadata

Assignees

Labels

Type

No fields configured for Task.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions