88use Psr \Http \Message \ServerRequestInterface as PsrRequest ;
99use Tempest \Container \Container ;
1010use Tempest \Core \AppConfig ;
11- use Tempest \Http \GenericRequest ;
1211use Tempest \Http \Mappers \PsrRequestToGenericRequestMapper ;
13- use Tempest \Http \Mappers \RequestToObjectMapper ;
14- use Tempest \Http \Mappers \RequestToPsrRequestMapper ;
1512use Tempest \Http \Request ;
1613use Tempest \Http \Response ;
17- use Tempest \Http \Responses \Invalid ;
18- use Tempest \Http \Responses \NotFound ;
1914use Tempest \Http \Responses \Ok ;
20- use Tempest \Mapper \ObjectFactory ;
2115use Tempest \Reflection \ClassReflector ;
2216use Tempest \Router \Exceptions \ControllerActionHasNoReturn ;
2317use Tempest \Router \Exceptions \InvalidRouteException ;
24- use Tempest \Router \Exceptions \NotFoundException ;
18+ use Tempest \Router \Exceptions \NoMatchedRoute ;
2519use Tempest \Router \Routing \Construction \DiscoveredRoute ;
2620use Tempest \Router \Routing \Matching \RouteMatcher ;
27- use Tempest \Validation \Exceptions \ValidationException ;
2821use Tempest \View \View ;
2922
3023use function Tempest \map ;
@@ -42,43 +35,28 @@ public function __construct(
4235
4336 public function dispatch (Request |PsrRequest $ request ): Response
4437 {
45- return $ this ->processResponse (
46- $ this ->processRequest ($ request ),
47- );
48- }
49-
50- private function processRequest (Request |PsrRequest $ request ): Response
51- {
52- if (! ($ request instanceof PsrRequest)) {
53- $ request = map ($ request )->with (RequestToPsrRequestMapper::class)->do ();
54- }
55-
56- $ matchedRoute = $ this ->routeMatcher ->match ($ request );
57-
58- if ($ matchedRoute === null ) {
59- return new NotFound ();
38+ if (! ($ request instanceof Request)) {
39+ $ request = map ($ request )->with (PsrRequestToGenericRequestMapper::class)->do ();
6040 }
6141
62- $ this -> container -> singleton (MatchedRoute::class, fn () => $ matchedRoute );
42+ $ callable = $ this -> getCallable ( );
6343
64- try {
65- $ callable = $ this ->getCallable ($ matchedRoute );
66- $ request = $ this ->resolveRequest ($ request , $ matchedRoute );
67- $ response = $ callable ($ request );
68- } catch (NotFoundException ) {
69- return new NotFound ();
70- } catch (ValidationException $ validationException ) {
71- return new Invalid ($ validationException ->subject , $ validationException ->failingRules );
72- }
73-
74- return $ response ;
44+ return $ this ->processResponse ($ callable ($ request ));
7545 }
7646
77- private function getCallable (MatchedRoute $ matchedRoute ): HttpMiddlewareCallable
47+ private function getCallable (): HttpMiddlewareCallable
7848 {
79- $ route = $ matchedRoute ->route ;
49+ $ callControllerAction = function (Request $ _ ) {
50+ $ matchedRoute = $ this ->container ->get (MatchedRoute::class);
51+
52+ if ($ matchedRoute === null ) {
53+ // At this point, the `MatchRouteMiddleware` should have run.
54+ // If that's not the case, then someone messed up by clearing all HTTP middleware
55+ throw new NoMatchedRoute ();
56+ }
57+
58+ $ route = $ matchedRoute ->route ;
8059
81- $ callControllerAction = function (Request $ _ ) use ($ route , $ matchedRoute ) {
8260 $ response = $ this ->container ->invoke (
8361 $ route ->handler ,
8462 ...$ matchedRoute ->params ,
@@ -93,10 +71,7 @@ private function getCallable(MatchedRoute $matchedRoute): HttpMiddlewareCallable
9371
9472 $ callable = new HttpMiddlewareCallable (fn (Request $ request ) => $ this ->createResponse ($ callControllerAction ($ request )));
9573
96- $ middlewareStack = $ this ->routeConfig
97- ->middleware
98- ->clone ()
99- ->add (...$ route ->middleware );
74+ $ middlewareStack = $ this ->routeConfig ->middleware ;
10075
10176 foreach ($ middlewareStack ->unwrap () as $ middlewareClass ) {
10277 $ callable = new HttpMiddlewareCallable (function (Request $ request ) use ($ middlewareClass , $ callable ) {
@@ -194,38 +169,4 @@ private function processResponse(Response $response): Response
194169
195170 return $ response ;
196171 }
197-
198- // TODO: could in theory be moved to a dynamic initializer
199- private function resolveRequest (PsrRequest |ObjectFactory $ psrRequest , MatchedRoute $ matchedRoute ): Request
200- {
201- // Let's find out if our input request data matches what the route's action needs
202- $ requestClass = GenericRequest::class;
203-
204- // We'll loop over all the handler's parameters
205- foreach ($ matchedRoute ->route ->handler ->getParameters () as $ parameter ) {
206- // If the parameter's type is an instance of Request…
207- if ($ parameter ->getType ()->matches (Request::class)) {
208- // We'll use that specific request class
209- $ requestClass = $ parameter ->getType ()->getName ();
210-
211- break ;
212- }
213- }
214-
215- // We map the original request we got into this method to the right request class
216- /** @var \Tempest\Http\GenericRequest $request */
217- $ request = map ($ psrRequest )->with (PsrRequestToGenericRequestMapper::class)->do ();
218-
219- if ($ requestClass !== Request::class && $ requestClass !== GenericRequest::class) {
220- $ request = map ($ request )->with (RequestToObjectMapper::class)->to ($ requestClass );
221- }
222-
223- // Next, we register this newly created request object in the container
224- // This makes it so that RequestInitializer is bypassed entirely when the controller action needs the request class
225- // Making it so that we don't need to set any $_SERVER variables and stuff like that
226- $ this ->container ->singleton (Request::class, fn () => $ request );
227- $ this ->container ->singleton ($ request ::class, fn () => $ request );
228-
229- return $ request ;
230- }
231172}
0 commit comments