diff --git a/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/Configuration.php b/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/Configuration.php index 2f16740..e16fb0b 100644 --- a/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/Configuration.php +++ b/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/Configuration.php @@ -52,6 +52,11 @@ public function getConfigTreeBuilder() ->arrayNode('json_form_extension') ->canBeEnabled() ->end() + ->arrayNode('http_extension') + ->canBeEnabled() + ->children() + ->scalarNode('path')->end() + ->end() ->end() ; diff --git a/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/MajoraFrameworkExtraExtension.php b/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/MajoraFrameworkExtraExtension.php index 2961c4f..9d2f3a6 100644 --- a/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/MajoraFrameworkExtraExtension.php +++ b/src/Majora/Bundle/FrameworkExtraBundle/DependencyInjection/MajoraFrameworkExtraExtension.php @@ -64,5 +64,17 @@ public function load(array $configs, ContainerBuilder $container) if (!empty($config['json_form_extension']['enabled'])) { $loader->load('json_form_extension.xml'); } + + + // http_extension + if(!empty($config['http_extension']['enabled'])) + { + $loader->load('http_extension.xml'); + new HttpClientFactory($container, $config['http_extension']); + + if ($container->getParameter('kernel.debug')) { + $loader->load('http_datacollector.xml'); + } + } } } diff --git a/src/Majora/Bundle/FrameworkExtraBundle/Resources/config/http_datacollector.xml b/src/Majora/Bundle/FrameworkExtraBundle/Resources/config/http_datacollector.xml new file mode 100644 index 0000000..d387e72 --- /dev/null +++ b/src/Majora/Bundle/FrameworkExtraBundle/Resources/config/http_datacollector.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/src/Majora/Bundle/FrameworkExtraBundle/Resources/config/http_extension.xml b/src/Majora/Bundle/FrameworkExtraBundle/Resources/config/http_extension.xml new file mode 100644 index 0000000..c804c7c --- /dev/null +++ b/src/Majora/Bundle/FrameworkExtraBundle/Resources/config/http_extension.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/Majora/Bundle/FrameworkExtraBundle/Resources/views/Collector/majorahttp.html.twig b/src/Majora/Bundle/FrameworkExtraBundle/Resources/views/Collector/majorahttp.html.twig new file mode 100644 index 0000000..b08a3cf --- /dev/null +++ b/src/Majora/Bundle/FrameworkExtraBundle/Resources/views/Collector/majorahttp.html.twig @@ -0,0 +1,94 @@ +{% extends 'WebProfilerBundle:Profiler:layout.html.twig' %} + +{% block toolbar %} + {% set text %} + {# this is the content displayed when hovering the mouse over + the toolbar panel #} + {% set icon %} + MajoraHttp + {% endset %} +
+ MajoraHttp +
+ + {% endset %} + {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: true }) }} +{% endblock %} + +{% block menu %} + + + Majora HTTP + {{ collector.commands|length }} + +{% endblock %} + +{% block panel %} + + +

Majora HTTP

+ {% for command in collector.commands %} + + Request URI : {{ command.uri }}
+
+ REQUEST + + + + + + {% if command.headers.apiKey is defined %} + + {% endif %} + + + + + {% if command.headers.apiKey is defined %} + + {% endif %} +
MethodContent-TypeHostApiKey
+ {{ command.method }} + + {% if command.headers['Content-Type'][0] is defined %} + {{ command.headers['Content-Type'][0] }} + {% else %} + null + {% endif %} + + {{ command.headers['Host'][0] }} + + {{ command.headers['api_key'][0] }} +
+ + + RESPONSE + + + + + + + + + + + +
Status CodeMessageExecution Time
+ {{ command.statusCode }} + + {{ command.reasonPhrase}} + {{ command.executionTime }} ms +
+ + + + + +
Body
+ {{ command.responseBody|slice(0,100)|json_encode }} +
+


+ {% endfor %} + +{% endblock %} \ No newline at end of file diff --git a/src/Majora/Framework/Http/DataCollector/MajoraHttpDataCollector.php b/src/Majora/Framework/Http/DataCollector/MajoraHttpDataCollector.php new file mode 100644 index 0000000..ebabb92 --- /dev/null +++ b/src/Majora/Framework/Http/DataCollector/MajoraHttpDataCollector.php @@ -0,0 +1,73 @@ +data['majoraHttp'] = [ + 'commands' => new \SplQueue(), + ]; + } + + /** + * @param Request $request + * @param Response $response + * @param \Exception|null $exception + */ + function collect(Request $request, Response $response, \Exception $exception = null) + { + + } + + /** + * @return string + */ + function getName() + { + return "majorahttp"; + } + + /** + * @param MajoraHttpEvent $event + */ + public function onRequest(HttpRequestEvent $event) + { + $request = $event->getRequest(); + $response = $event->getResponse(); + $body = (array) json_decode($response->getBody()); + + $data = array( + 'responseBody' => $body, + 'uri' => $request->getUri(), + 'method' => $request->getMethod(), + 'headers' => $request->getHeaders(), + 'statusCode' => $response->getStatusCode(), + 'reasonPhrase' => $response->getReasonPhrase(), + 'executionTime' => $event->getExecutionTime(), + ); + + $this->data['majoraHttp']['commands']->enqueue($data); + } + + public function getCommands() + { + return $this->data['majoraHttp']['commands']; + } + +} \ No newline at end of file diff --git a/src/Majora/Framework/Http/Event/HttpRequestEvent.php b/src/Majora/Framework/Http/Event/HttpRequestEvent.php new file mode 100644 index 0000000..abef823 --- /dev/null +++ b/src/Majora/Framework/Http/Event/HttpRequestEvent.php @@ -0,0 +1,93 @@ +request= $request; + $this->clientId = $clientId; + } + + /** + * Return request + * + * @return Request + */ + public function getRequest() + { + return $this->request; + } + /** + * Set Response + * + * @param Response $response + * + * @return $this + */ + public function setResponse(ResponseInterface $response) + { + $this->response = $response; + $this->reason = $this->response->getReasonPhrase(); + return $this; + } + /** + * Return response + * + * @return Response + */ + public function getResponse() + { + return $this->response; + } + + + /** + * @return float + */ + public function getExecutionTime() + { + return $this->executionTime; + } + + + public function setExecutionTime($time) + { + $this->executionTime = $time; + } +} \ No newline at end of file diff --git a/src/Majora/Framework/Http/HttpClientFactory.php b/src/Majora/Framework/Http/HttpClientFactory.php new file mode 100644 index 0000000..648f742 --- /dev/null +++ b/src/Majora/Framework/Http/HttpClientFactory.php @@ -0,0 +1,57 @@ +config = $config; + $this->container = $container; + $this->init(); + } + + + public function init() + { + $parser = new Parser(); + if(!empty($this->config['path'])) { + $clients = $parser->parse(file_get_contents($this->container->getParameter('kernel.root_dir').$this->config['path'])); + } + else { + $clients = $parser->parse(file_get_contents($this->container->getParameter('kernel.root_dir').'/majora_client.yml')); + } + + foreach ($clients as $clientId => $clientConfig) + { + $this->createClient($clientConfig, $clientId); + } + } + + public function createClient($clientConfig, $clientId){ + + $this->container->setDefinition(sprintf('majora_http.handler.%s', $clientId), $this->container->getDefinition('guzzle.curl_handler')); + $handlerStackReference = new Reference(sprintf('majora_http.handler.%s', $clientId)); + + $this->container->getDefinition(sprintf('majora_http.handler.%s', $clientId)); + + //Middleware + $eventDispatcher = $this->container->getDefinition('majora.http_eventdispatcher'); + $eventDispatcher->replaceArgument(2, $clientId); + $eventDispatcher->addMethodCall('push', [$handlerStackReference]); + + $clientConfig['handler'] = $handlerStackReference; + $clientConfig['middleware'] = $eventDispatcher; + $guzzleClient= $this->container->getDefinition('guzzle_wrapper'); + $guzzleClient->replaceArgument(0, $clientConfig); + $this->container->setDefinition(sprintf('guzzle_http.%s', $clientId) , $guzzleClient); + } +} + + + diff --git a/src/Majora/Framework/Http/Middleware/MajoraEventDispatcher.php b/src/Majora/Framework/Http/Middleware/MajoraEventDispatcher.php new file mode 100644 index 0000000..8854b91 --- /dev/null +++ b/src/Majora/Framework/Http/Middleware/MajoraEventDispatcher.php @@ -0,0 +1,101 @@ +eventDispatcher = $eventDispatcher; + $this->clientId = $clientId; + $this->stopWatch = $stopWatch; + } + + /** + * @param HandlerStack $stack + * @return HandlerStack + */ + public function push(HandlerStack $stack) + { + $stack->push(Middleware::mapRequest(function (RequestInterface $request) { + $this->initEvent($request); + return $request; + })); + + + $stack->push(function (callable $handler) { + return function ( + RequestInterface $request, + array $options + ) use ($handler) { + + $promise = $handler($request, $options); + + return $promise->then( + function (ResponseInterface $response) use ($request) { + + $this->dispatchEvent($response); + return $response; + }, + function (\Exception $reason) use ($request) { + // impossible to pass \exception to dispatch event + dump($reason); + $this->dispatchEvent($reason); + throw $reason; + } + ); + }; + }); + return $stack; + } + + /** + * @param RequestInterface $request + */ + protected function initEvent(RequestInterface $request) + { + $this->stopWatch->start('majoraEvent.'.$this->clientId); + $event = new HttpRequestEvent($request, $this->clientId); + $this->event = $event; + } + + /** + * @param ResponseInterface $response + */ + protected function dispatchEvent(ResponseInterface $response) + { + $this->event->setResponse($response); + $this->stopWatch->stop('majoraEvent.'.$this->clientId); + $this->event->setExecutionTime($this->stopWatch->getEvent('majoraEvent.'.$this->clientId)->getDuration()); + $this->eventDispatcher->dispatch(HttpRequestEvent::EVENT_NAME, $this->event); + } +} \ No newline at end of file diff --git a/src/Majora/Framework/Http/Services/GuzzleWrapper.php b/src/Majora/Framework/Http/Services/GuzzleWrapper.php new file mode 100644 index 0000000..900d0d4 --- /dev/null +++ b/src/Majora/Framework/Http/Services/GuzzleWrapper.php @@ -0,0 +1,20 @@ +