11<?php
22
33/**
4- * High-performance PHP process supervisor and load balancer written in Go. Http core .
4+ * This file is part of RoadRunner package .
55 *
6- * @author Alex Bond
6+ * For the full copyright and license information, please view the LICENSE
7+ * file that was distributed with this source code.
78 */
89
910declare (strict_types=1 );
1011
1112namespace Spiral \RoadRunner \Http ;
1213
14+ use Spiral \RoadRunner \Payload ;
1315use Spiral \RoadRunner \WorkerInterface ;
1416
17+ /**
18+ * @psalm-import-type HeadersList from Request
19+ * @psalm-import-type AttributesList from Request
20+ * @psalm-import-type UploadedFilesList from Request
21+ * @psalm-import-type CookiesList from Request
22+ *
23+ * @psalm-type RequestContext = array {
24+ * remoteAddr: string,
25+ * protocol: string,
26+ * method: string,
27+ * uri: string,
28+ * attributes: AttributesList,
29+ * headers: HeadersList,
30+ * cookies: CookiesList,
31+ * uploads: UploadedFilesList|null,
32+ * rawQuery: string,
33+ * parsed: bool
34+ * }
35+ *
36+ * @see Request
37+ */
1538class HttpWorker implements HttpWorkerInterface
1639{
17- /** @var WorkerInterface */
40+ /**
41+ * @var WorkerInterface
42+ */
1843 private WorkerInterface $ worker ;
1944
2045 /**
@@ -34,73 +59,74 @@ public function getWorker(): WorkerInterface
3459 }
3560
3661 /**
37- * Wait for incoming http request.
38- *
39- * @return Request|null
62+ * {@inheritDoc}
63+ * @throws \JsonException
4064 */
4165 public function waitRequest (): ?Request
4266 {
43- $ payload = $ this ->getWorker ()->waitPayload ();
44- if (empty ($ payload ->body ) && empty ($ payload ->header )) {
45- // termination request
67+ $ payload = $ this ->worker ->waitPayload ();
68+
69+ // Termination request
70+ if ($ payload === null || (!$ payload ->body && !$ payload ->header )) {
4671 return null ;
4772 }
4873
49- $ request = new Request ();
50- $ request -> body = $ payload ->body ;
74+ /** @var RequestContext $context */
75+ $ context = \json_decode ( $ payload ->header , true , 512 , \ JSON_THROW_ON_ERROR ) ;
5176
52- $ context = json_decode ($ payload ->header , true );
53- if ($ context === null ) {
54- // invalid context
55- return null ;
56- }
77+ return $ this ->createRequest ($ payload ->body , $ context );
78+ }
5779
58- $ this ->hydrateRequest ($ request , $ context );
80+ /**
81+ * {@inheritDoc}
82+ * @throws \JsonException
83+ */
84+ public function respond (int $ status , string $ body , array $ headers = []): void
85+ {
86+ $ headers = (string )\json_encode ([
87+ 'status ' => $ status ,
88+ 'headers ' => $ headers ?: (object )[],
89+ ], \JSON_THROW_ON_ERROR );
5990
60- return $ request ;
91+ $ this -> worker -> respond ( new Payload ( $ body , $ headers )) ;
6192 }
6293
6394 /**
64- * Send response to the application server.
95+ * @param string $body
96+ * @param RequestContext $context
97+ * @return Request
6598 *
66- * @param int $status Http status code
67- * @param string $body Body of response
68- * @param string[][] $headers An associative array of the message's headers. Each
69- * key MUST be a header name, and each value MUST be an array of strings
70- * for that header.
99+ * @psalm-suppress InaccessibleProperty
71100 */
72- public function respond ( int $ status , string $ body , array $ headers = [] ): void
101+ private function createRequest ( string $ body , array $ context ): Request
73102 {
74- if ( $ headers === []) {
75- // this is required to represent empty header set as map and not as array
76- $ headers = new \ stdClass ();
77- }
103+ $ request = new Request ();
104+ $ request -> body = $ body ;
105+
106+ $ this -> hydrateRequest ( $ request , $ context );
78107
79- $ this ->getWorker ()->send (
80- $ body ,
81- (string ) json_encode (['status ' => $ status , 'headers ' => $ headers ])
82- );
108+ return $ request ;
83109 }
84110
85111 /**
86112 * @param Request $request
87- * @param array $context
113+ * @param RequestContext $context
114+ *
115+ * @psalm-suppress InaccessibleProperty
116+ * @psalm-suppress MixedPropertyTypeCoercion
88117 */
89118 private function hydrateRequest (Request $ request , array $ context ): void
90119 {
91120 $ request ->remoteAddr = $ context ['remoteAddr ' ];
92121 $ request ->protocol = $ context ['protocol ' ];
93122 $ request ->method = $ context ['method ' ];
94123 $ request ->uri = $ context ['uri ' ];
95- $ request ->attributes = $ context ['attributes ' ] ?? [];
96- $ request ->headers = $ context ['headers ' ];
97- $ request ->cookies = $ context ['cookies ' ] ?? [];
98- $ request ->uploads = $ context ['uploads ' ] ?? [];
99-
100- $ request ->query = [];
101- parse_str ($ context ['rawQuery ' ], $ request ->query );
124+ \parse_str ($ context ['rawQuery ' ], $ request ->query );
102125
103- // indicates that body was parsed
104- $ request ->parsed = $ context ['parsed ' ];
126+ $ request ->attributes = (array )($ context ['attributes ' ] ?? []);
127+ $ request ->headers = (array )($ context ['headers ' ] ?? []);
128+ $ request ->cookies = (array )($ context ['cookies ' ] ?? []);
129+ $ request ->uploads = (array )($ context ['uploads ' ] ?? []);
130+ $ request ->parsed = (bool )$ context ['parsed ' ];
105131 }
106132}
0 commit comments