diff --git a/Classes/Controller/GraphQLController.php b/Classes/Controller/GraphQLController.php index e78cb11..1402849 100644 --- a/Classes/Controller/GraphQLController.php +++ b/Classes/Controller/GraphQLController.php @@ -9,6 +9,7 @@ use Neos\Flow\Mvc\Controller\ActionController; use t3n\GraphQL\Context; use t3n\GraphQL\Exception\InvalidContextException; +use t3n\GraphQL\Log\RequestLoggerInterface; use t3n\GraphQL\Service\DefaultFieldResolver; use t3n\GraphQL\Service\SchemaService; use t3n\GraphQL\Service\ValidationRuleService; @@ -43,6 +44,13 @@ class GraphQLController extends ActionController */ protected $endpointConfigurations; + /** + * @Flow\Inject + * + * @var RequestLoggerInterface + */ + protected $requestLogger; + /** * phpcs:disable SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableParameterTypeHintSpecification * @@ -62,8 +70,10 @@ public function queryAction(string $endpoint, string $query, ?array $variables = $schema = $this->schemaService->getSchemaForEndpoint($endpoint); $validationRules = $this->validationRuleService->getValidationRulesForEndpoint($endpoint); - if (isset($this->endpointConfigurations[$endpoint]['context'])) { - $contextClassname = $this->endpointConfigurations[$endpoint]['context']; + $endpointConfiguration = $this->endpointConfigurations[$endpoint] ?? []; + + if (isset($endpointConfiguration['context'])) { + $contextClassname = $endpointConfiguration['context']; } else { $contextClassname = $this->contextClassName; } @@ -73,6 +83,10 @@ public function queryAction(string $endpoint, string $query, ?array $variables = throw new InvalidContextException('The configured Context must extend \t3n\GraphQL\Context', 1545945332); } + if (isset($endpointConfiguration['logRequests']) && $endpointConfiguration['logRequests'] === true) { + $this->requestLogger->info('Incoming graphql request', ['endpoint' => $endpoint, 'query' => json_encode($query), 'variables' => empty($variables) ? 'none' : $variables]); + } + GraphQL::setDefaultFieldResolver([DefaultFieldResolver::class, 'resolve']); $result = GraphQL::executeQuery( diff --git a/Classes/Log/RequestLoggerInterface.php b/Classes/Log/RequestLoggerInterface.php new file mode 100644 index 0000000..e333aa5 --- /dev/null +++ b/Classes/Log/RequestLoggerInterface.php @@ -0,0 +1,11 @@ +endpoints[$endpoint] ?? null; + } + protected function getSchemaFromEnvelope(string $envelopeClassName): Schema { $envelope = $this->objectManager->get($envelopeClassName); diff --git a/Configuration/Objects.yaml b/Configuration/Objects.yaml index db8e187..c5f1f24 100644 --- a/Configuration/Objects.yaml +++ b/Configuration/Objects.yaml @@ -14,3 +14,11 @@ t3n\GraphQL\Service\SchemaService: arguments: 1: value: t3n_GraphQL_Schema + +t3n\GraphQL\Log\RequestLoggerInterface: + scope: singleton + factoryObjectName: Neos\Flow\Log\PsrLoggerFactoryInterface + factoryMethodName: get + arguments: + 1: + value: graphQLRequestLogger diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index dc221b6..6cf196f 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -7,6 +7,17 @@ Neos: 'graphQLOptions': position: 'before routing' component: 't3n\GraphQL\Http\HttpOptionsComponent' + log: + graphQLRequestLogger: + logger: Neos\Flow\Log\Logger + backend: Neos\Flow\Log\Backend\FileBackend + backendOptions: + logFileURL: '%FLOW_PATH_DATA%Logs/GraphQLRequests.log' + createParentDirectories: true + severityThreshold: '%LOG_INFO%' + maximumLogFileSize: 10485760 + logFilesToKeep: 1 + logMessageOrigin: false t3n: GraphQL: @@ -14,5 +25,6 @@ t3n: includeExceptionMessageInOutput: true endpoints: [] # 'some-endpoint': +# 'logRequests': true # if enabled all requests are logged # 'context:' 'Foo\Vendor\GraphQL\Context # optional context that overrides the global context # 'schemaEnvelope': 'Some\Fully\Qualified\Namespace' diff --git a/Readme.md b/Readme.md index f74eb7a..d826089 100644 --- a/Readme.md +++ b/Readme.md @@ -362,6 +362,21 @@ class MutationResolver implements ResolverInterface } ``` +### Log incoming requests + +You can enable logging of incoming requests per endpoint: + +```yaml +t3n: + GraphQL: + endpoints: + 'your-endpoint': + logRequests: true +``` + +Once activated all incoming requests will be logged to `Data/Logs/GraphQLRequests.log`. Each log entry +will contain the endpoint, query and variables. + ### Secure your endpoint To secure your api endpoints you have several options. The easiest way is to just configure