@@ -88,99 +88,19 @@ private function handleRequestCompat(\React\Http\Message\ServerRequest $reactReq
8888 {
8989 return new Promise (function ($ resolve , $ reject ) use ($ reactRequest ) {
9090 try {
91- // Extract request data without using PSR-7 interfaces
92- $ method = $ reactRequest ->getMethod ();
93- $ uri = (string ) $ reactRequest ->getUri ();
94- $ headers = $ reactRequest ->getHeaders ();
95- $ body = (string ) $ reactRequest ->getBody ();
96-
97- // Parse URI
98- $ parsedUrl = parse_url ($ uri );
99- $ path = $ parsedUrl ['path ' ] ?? '/ ' ;
100- $ query = $ parsedUrl ['query ' ] ?? '' ;
101-
102- // Create PivotPHP Request manually
103- $ pivotRequest = new \PivotPHP \Core \Http \Request ($ method , $ path , $ path );
104-
105- // Set headers
106- foreach ($ headers as $ name => $ values ) {
107- $ headerValue = is_array ($ values ) ? implode (', ' , $ values ) : $ values ;
108- $ pivotRequest = $ pivotRequest ->withHeader ($ name , $ headerValue );
109- }
110-
111- // Parse query params
112- if ($ query !== '' ) {
113- parse_str ($ query , $ queryParams );
114- $ pivotRequest = $ pivotRequest ->withQueryParams ($ queryParams );
115- }
116-
117- // Parse body
118- if ($ body !== '' ) {
119- $ contentType = $ pivotRequest ->getHeaderLine ('Content-Type ' );
120-
121- if (str_contains ($ contentType , 'application/json ' )) {
122- $ parsedBody = json_decode ($ body , true );
123- if (is_array ($ parsedBody )) {
124- $ pivotRequest = $ pivotRequest ->withParsedBody ($ parsedBody );
125- }
126- } elseif (str_contains ($ contentType , 'application/x-www-form-urlencoded ' )) {
127- parse_str ($ body , $ parsedBody );
128- $ pivotRequest = $ pivotRequest ->withParsedBody ($ parsedBody );
129- }
130-
131- // Set body stream
132- $ stream = new \PivotPHP \Core \Http \Psr7 \Stream ($ body );
133- $ pivotRequest = $ pivotRequest ->withBody ($ stream );
134- }
135-
136- // Create PivotPHP Response
137- $ pivotResponse = new \PivotPHP \Core \Http \Response ();
138-
139- // Find and execute route
140- $ route = \PivotPHP \Core \Routing \Router::identify ($ method , $ path );
141-
142- if ($ route !== null ) {
143- // Execute route handler
144- $ handler = $ route ['handler ' ];
145-
146- // Capture output
147- ob_start ();
148- $ handler ($ pivotRequest , $ pivotResponse );
149- $ output = ob_get_clean ();
150-
151- // Create React response manually
152- $ reactResponse = new \React \Http \Message \Response (
153- 200 ,
154- ['Content-Type ' => 'application/json ' ],
155- $ output !== false ? $ output : ''
156- );
157-
158- $ resolve ($ reactResponse );
159- } else {
160- // 404 Not Found
161- $ notFoundBody = json_encode (['error ' => 'Not Found ' ]);
162- $ reactResponse = new \React \Http \Message \Response (
163- 404 ,
164- ['Content-Type ' => 'application/json ' ],
165- $ notFoundBody !== false ? $ notFoundBody : '{"error":"Not Found"} '
166- );
167-
168- $ resolve ($ reactResponse );
169- }
170- } catch (\Exception $ e ) {
171- $ this ->logger ->error ('Error handling request ' , [
172- 'error ' => $ e ->getMessage (),
173- 'trace ' => $ e ->getTraceAsString (),
174- ]);
175-
176- $ errorBody = json_encode (['error ' => 'Internal Server Error ' ]);
177- $ reactResponse = new \React \Http \Message \Response (
178- 500 ,
179- ['Content-Type ' => 'application/json ' ],
180- $ errorBody !== false ? $ errorBody : '{"error":"Internal Server Error"} '
181- );
91+ // Extract basic request data from ReactPHP request
92+ $ requestData = $ this ->extractRequestData ($ reactRequest );
93+
94+ // Create PivotPHP Request from extracted data
95+ $ pivotRequest = $ this ->createPivotRequest ($ requestData );
96+
97+ // Process the request through routing and get response
98+ $ reactResponse = $ this ->processRoute ($ pivotRequest , $ requestData );
18299
183100 $ resolve ($ reactResponse );
101+ } catch (\Exception $ e ) {
102+ $ errorResponse = $ this ->createErrorResponse ($ e );
103+ $ resolve ($ errorResponse );
184104 }
185105 });
186106 }
@@ -238,4 +158,194 @@ public function isRunning(): bool
238158 {
239159 return $ this ->running ;
240160 }
161+
162+ /**
163+ * Extract basic request data from ReactPHP ServerRequest
164+ */
165+ private function extractRequestData (\React \Http \Message \ServerRequest $ reactRequest ): array
166+ {
167+ $ uri = (string ) $ reactRequest ->getUri ();
168+ $ parsedUrl = parse_url ($ uri );
169+
170+ return [
171+ 'method ' => $ reactRequest ->getMethod (),
172+ 'uri ' => $ uri ,
173+ 'path ' => $ parsedUrl ['path ' ] ?? '/ ' ,
174+ 'query ' => $ parsedUrl ['query ' ] ?? '' ,
175+ 'headers ' => $ reactRequest ->getHeaders (),
176+ 'body ' => (string ) $ reactRequest ->getBody (),
177+ ];
178+ }
179+
180+ /**
181+ * Create PivotPHP Request from extracted request data
182+ */
183+ private function createPivotRequest (array $ requestData ): \PivotPHP \Core \Http \Request
184+ {
185+ // Create base PivotPHP Request
186+ $ pivotRequest = new \PivotPHP \Core \Http \Request (
187+ $ requestData ['method ' ],
188+ $ requestData ['path ' ],
189+ $ requestData ['path ' ]
190+ );
191+
192+ // Apply headers
193+ $ pivotRequest = $ this ->applyHeaders ($ pivotRequest , $ requestData ['headers ' ]);
194+
195+ // Apply query parameters
196+ $ pivotRequest = $ this ->applyQueryParameters ($ pivotRequest , $ requestData ['query ' ]);
197+
198+ // Apply body data
199+ $ pivotRequest = $ this ->applyBodyData ($ pivotRequest , $ requestData ['body ' ]);
200+
201+ return $ pivotRequest ;
202+ }
203+
204+ /**
205+ * Apply headers to PivotPHP Request
206+ */
207+ private function applyHeaders (
208+ \PivotPHP \Core \Http \Request $ pivotRequest ,
209+ array $ headers
210+ ): \PivotPHP \Core \Http \Request {
211+ foreach ($ headers as $ name => $ values ) {
212+ $ headerValue = is_array ($ values ) ? implode (', ' , $ values ) : $ values ;
213+ $ pivotRequest = $ pivotRequest ->withHeader ($ name , $ headerValue );
214+ }
215+
216+ return $ pivotRequest ;
217+ }
218+
219+ /**
220+ * Apply query parameters to PivotPHP Request
221+ */
222+ private function applyQueryParameters (
223+ \PivotPHP \Core \Http \Request $ pivotRequest ,
224+ string $ query
225+ ): \PivotPHP \Core \Http \Request {
226+ if ($ query !== '' ) {
227+ parse_str ($ query , $ queryParams );
228+ return $ pivotRequest ->withQueryParams ($ queryParams );
229+ }
230+
231+ return $ pivotRequest ;
232+ }
233+
234+ /**
235+ * Apply body data to PivotPHP Request based on content type
236+ */
237+ private function applyBodyData (\PivotPHP \Core \Http \Request $ pivotRequest , string $ body ): \PivotPHP \Core \Http \Request
238+ {
239+ if ($ body === '' ) {
240+ return $ pivotRequest ;
241+ }
242+
243+ $ contentType = $ pivotRequest ->getHeaderLine ('Content-Type ' );
244+
245+ // Parse body based on content type
246+ if (str_contains ($ contentType , 'application/json ' )) {
247+ $ pivotRequest = $ this ->parseJsonBody ($ pivotRequest , $ body );
248+ } elseif (str_contains ($ contentType , 'application/x-www-form-urlencoded ' )) {
249+ $ pivotRequest = $ this ->parseFormBody ($ pivotRequest , $ body );
250+ }
251+
252+ // Set body stream using StreamFactory for consistency
253+ $ streamFactory = new \PivotPHP \Core \Http \Psr7 \Factory \StreamFactory ();
254+ $ stream = $ streamFactory ->createStream ($ body );
255+ $ pivotRequest = $ pivotRequest ->withBody ($ stream );
256+
257+ return $ pivotRequest ;
258+ }
259+
260+ /**
261+ * Parse JSON body and apply to request
262+ */
263+ private function parseJsonBody (\PivotPHP \Core \Http \Request $ pivotRequest , string $ body ): \PivotPHP \Core \Http \Request
264+ {
265+ $ parsedBody = json_decode ($ body , true );
266+ if (is_array ($ parsedBody )) {
267+ return $ pivotRequest ->withParsedBody ($ parsedBody );
268+ }
269+
270+ return $ pivotRequest ;
271+ }
272+
273+ /**
274+ * Parse form-encoded body and apply to request
275+ */
276+ private function parseFormBody (\PivotPHP \Core \Http \Request $ pivotRequest , string $ body ): \PivotPHP \Core \Http \Request
277+ {
278+ parse_str ($ body , $ parsedBody );
279+ return $ pivotRequest ->withParsedBody ($ parsedBody );
280+ }
281+
282+ /**
283+ * Process route and create ReactPHP response
284+ */
285+ private function processRoute (
286+ \PivotPHP \Core \Http \Request $ pivotRequest ,
287+ array $ requestData
288+ ): \React \Http \Message \Response {
289+ $ route = \PivotPHP \Core \Routing \Router::identify ($ requestData ['method ' ], $ requestData ['path ' ]);
290+
291+ if ($ route !== null ) {
292+ return $ this ->executeRoute ($ route , $ pivotRequest );
293+ }
294+
295+ return $ this ->createNotFoundResponse ();
296+ }
297+
298+ /**
299+ * Execute route handler and create response
300+ */
301+ private function executeRoute (array $ route , \PivotPHP \Core \Http \Request $ pivotRequest ): \React \Http \Message \Response
302+ {
303+ $ handler = $ route ['handler ' ];
304+ $ pivotResponse = new \PivotPHP \Core \Http \Response ();
305+
306+ // Capture output from route handler
307+ ob_start ();
308+ $ handler ($ pivotRequest , $ pivotResponse );
309+ $ output = ob_get_clean ();
310+
311+ // Create ReactPHP response
312+ return new \React \Http \Message \Response (
313+ 200 ,
314+ ['Content-Type ' => 'application/json ' ],
315+ $ output !== false ? $ output : ''
316+ );
317+ }
318+
319+ /**
320+ * Create 404 Not Found response
321+ */
322+ private function createNotFoundResponse (): \React \Http \Message \Response
323+ {
324+ $ notFoundBody = json_encode (['error ' => 'Not Found ' ]);
325+
326+ return new \React \Http \Message \Response (
327+ 404 ,
328+ ['Content-Type ' => 'application/json ' ],
329+ $ notFoundBody !== false ? $ notFoundBody : '{"error":"Not Found"} '
330+ );
331+ }
332+
333+ /**
334+ * Create error response from exception
335+ */
336+ private function createErrorResponse (\Exception $ e ): \React \Http \Message \Response
337+ {
338+ $ this ->logger ->error ('Error handling request ' , [
339+ 'error ' => $ e ->getMessage (),
340+ 'trace ' => $ e ->getTraceAsString (),
341+ ]);
342+
343+ $ errorBody = json_encode (['error ' => 'Internal Server Error ' ]);
344+
345+ return new \React \Http \Message \Response (
346+ 500 ,
347+ ['Content-Type ' => 'application/json ' ],
348+ $ errorBody !== false ? $ errorBody : '{"error":"Internal Server Error"} '
349+ );
350+ }
241351}
0 commit comments