Skip to content

S1: PSR-Compliant HTTP Layer #80

Description

@derpixler

As a developer I want the HTTP transport to implement PSR-18/17 so I can swap Guzzle for any HTTP client and get typed exceptions instead of hasError() checks So that I'm not locked into a single HTTP library and I know exactly what went wrong (401 vs 404 vs 422 vs 429)

Acceptance Criteria

  • RequestHandlerInterface defines request(), get(), post(), put(), delete(), getLastResponse(), setOnBehalfOfUser()
  • RequestHandler accepts PSR-18 ClientInterface + PSR-17 factories + $baseUrl
  • Status codes mapped to typed exceptions: 401→AuthenticationException, 404→NotFoundException, 422→ValidationException (with $errors), 429→RateLimitException (with $retryAfterSeconds), 5xx→ServerErrorException
  • NetworkException on transport errors (DNS, timeout, connection refused)
  • RetryAfterMiddleware as PSR-18 decorator: catches 429, reads Retry-After header, sleeps, retries (max 3x)
  • ZammadException interface — all 6 exception classes implement it
  • Unit tests: RequestHandlerTest (7 mapping tests) + RetryAfterMiddlewareTest (retry, pass-through, exhaustion)
  • Cast utility: dateTime(), string(), intOrNull(), boolOrNull() for scalar coercion
  • PSR-12 clean, phpstan level=max, tests green

Metadata

Metadata

Assignees

Labels

Type

Fields

No fields configured for Story.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions