Skip to content

Commit dccfc63

Browse files
committed
Adding GraphQLMiddleware
1 parent 83c19ad commit dccfc63

File tree

2 files changed

+178
-1
lines changed

2 files changed

+178
-1
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"youshido/graphql": "^1.4",
1414
"psr/container": "^1.0",
1515
"doctrine/annotations": "^1.2",
16-
"roave/better-reflection": "dev-master"
16+
"roave/better-reflection": "dev-master",
17+
"http-interop/http-middleware": "^0.4"
1718
},
1819
"require-dev": {
1920
"phpunit/phpunit": "^6.1",

src/GraphQLMiddleware.php

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
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

Comments
 (0)