1+ <?php
2+ namespace TheCodingMachine \GraphQL \Controllers ;
3+
4+ use GraphQL \GraphQL ;
5+ use Mouf \GraphQL \Schema ;
6+ use Psr \Http \Message \ResponseInterface ;
7+ use Psr \Http \Message \ServerRequestInterface ;
8+ use Youshido \GraphQL \Execution \Processor ;
9+ use Zend \Diactoros \Response \JsonResponse ;
10+
11+ class GraphQLMiddleware implements \Interop \Http \ServerMiddleware \MiddlewareInterface
12+ {
13+ /**
14+ * @var string The graphql uri path to match against
15+ */
16+ private $ graphqlUri ;
17+
18+ /**
19+ * @var array The graphql headers
20+ */
21+ private $ graphql_headers = [
22+ "application/graphql "
23+ ];
24+
25+ /**
26+ * @var array Allowed method for a graphql request, default GET, POST
27+ */
28+ private $ allowed_methods = [
29+ "GET " , "POST "
30+ ];
31+
32+ /**
33+ * @var Processor
34+ */
35+ private $ schema ;
36+ /**
37+ * @var null
38+ */
39+ private $ rootUrl ;
40+
41+ /**
42+ * GraphQLMiddleware constructor.
43+ *
44+ * @param Schema $schema
45+ * @param string $graphqlUri
46+ */
47+ public function __construct (Schema $ schema , $ graphqlUri = '/graphql ' , $ rootUrl = null )
48+ {
49+ $ this ->schema = $ schema ;
50+ $ this ->graphqlUri = rtrim ($ rootUrl , '/ ' ).'/ ' . ltrim ($ graphqlUri , '/ ' );
51+ }
52+
53+ /**
54+ * Process an incoming server request and return a response, optionally delegating
55+ * to the next middleware component to create the response.
56+ *
57+ * @param \Psr\Http\Message\ServerRequestInterface $request
58+ * @param \Interop\Http\ServerMiddleware\DelegateInterface $delegate
59+ *
60+ * @return \Psr\Http\Message\ResponseInterface
61+ */
62+ public function process (\Psr \Http \Message \ServerRequestInterface $ request , \Interop \Http \ServerMiddleware \DelegateInterface $ delegate )
63+ {
64+ if (!$ this ->isGraphQLRequest ($ request )) {
65+ return $ delegate ->process ($ request );
66+ }
67+
68+ if (!in_array ($ request ->getMethod (), $ this ->allowed_methods , true )){
69+ return new JsonResponse ([
70+ "Method not allowed. Allowed methods are " . implode (", " , $ this ->allowed_methods )
71+ ], 405 );
72+ }
73+
74+ list ($ query , $ variables ) = $ this ->getPayload ($ request );
75+
76+
77+ $ processor = new Processor ($ this ->schema ->toGraphQLSchema ());
78+ $ processor ->processPayload ($ query , $ variables );
79+ $ res = $ processor ->getResponseData ();
80+ return new JsonResponse ($ res );
81+
82+ /*$res = GraphQL::execute($this->schema->toGraphQLSchema(), $query, null, null, $variables, null);
83+
84+ return new JsonResponse($res);*/
85+ }
86+
87+ private function isGraphQLRequest (ServerRequestInterface $ request )
88+ {
89+ return $ this ->hasUri ($ request ) || $ this ->hasGraphQLHeader ($ request );
90+ }
91+
92+ private function hasUri (ServerRequestInterface $ request )
93+ {
94+ return $ this ->graphqlUri === $ request ->getUri ()->getPath ();
95+ }
96+
97+ private function hasGraphQLHeader (ServerRequestInterface $ request )
98+ {
99+ if (!$ request ->hasHeader ('content-type ' )) {
100+ return false ;
101+ }
102+
103+ $ request_headers = array_map (function ($ header ){
104+ return trim ($ header );
105+ }, explode (", " , $ request ->getHeaderLine ("content-type " )));
106+
107+ foreach ($ this ->graphql_headers as $ allowed_header ) {
108+ if (in_array ($ allowed_header , $ request_headers )){
109+ return true ;
110+ }
111+ }
112+
113+ return false ;
114+ }
115+
116+ private function getPayload (ServerRequestInterface $ request )
117+ {
118+ $ method = $ request ->getMethod ();
119+
120+ switch ($ method ) {
121+ case "GET " :
122+ return $ this ->fromGet ($ request );
123+ case "POST " :
124+ return $ this ->fromPost ($ request );
125+ default :
126+ throw new \RuntimeException ('Unexpected request type. Only support GET and POST. ' );
127+
128+ }
129+ }
130+
131+ private function fromGet (ServerRequestInterface $ request )
132+ {
133+ $ params = $ request ->getQueryParams ();
134+
135+ $ query = isset ($ params ['query ' ]) ? $ params ['query ' ] : null ;
136+ $ variables = isset ($ params ['variables ' ]) ? $ params ['variables ' ] : [];
137+
138+ $ variables = is_string ($ variables ) ? json_decode ($ variables , true ) ?: [] : [];
139+
140+ return [$ query , $ variables ];
141+
142+ }
143+
144+ private function fromPost (ServerRequestInterface $ request )
145+ {
146+ $ content = $ request ->getBody ()->getContents ();
147+
148+ if (empty ($ content )) {
149+ $ params = $ request ->getParsedBody ();
150+ } else {
151+ $ params = json_decode ($ content , true );
152+ }
153+
154+ $ query = $ variables = null ;
155+
156+ if (!empty ($ params )) {
157+ if ($ this ->hasGraphQLHeader ($ request )) {
158+ $ query = $ content ;
159+ } else {
160+ if ($ params ) {
161+ $ query = isset ($ params ['query ' ]) ? $ params ['query ' ] : $ query ;
162+ if (isset ($ params ['variables ' ])) {
163+ if (is_string ($ params ['variables ' ])) {
164+ $ variables = json_decode ($ params ['variables ' ], true ) ?: $ variables ;
165+ } else {
166+ $ variables = $ params ['variables ' ];
167+ }
168+ $ variables = is_array ($ variables ) ? $ variables : [];
169+ }
170+ }
171+ }
172+ }
173+ return [$ query , $ variables ];
174+
175+ }
176+ }
0 commit comments