Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema validation and error detail settings by get params #150

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip
* Support for semantic versioning api.
* [BC] DefaultHandler response code 404 instead 400
* [BC] Added Container to API Decider
* [BC] Output Configurator, Allows different methods for output configuration. Needs to be added to config services.

#### Added
* CorsPreflightHandlerInterface - resolve multiple service registered handler error
* Lazy API handlers

#### Added
* Button to copy `Body` content in api console
* Ability to disable schema validation and provide additional error info with get parameters.

#### Changed
* Handler tag wrapper has changed class from `btn` to `label`
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ application:
Api: Tomaj\NetteApi\Presenters\*Presenter
```

Then register your preffered output configurator in *config.neon* services:

```neon
services:
apiOutputConfigurator: Tomaj\NetteApi\Output\Configurator\QueryConfigurator
Martin-Beranek marked this conversation as resolved.
Show resolved Hide resolved
```

And add route to you RouterFactory:

```php
Expand Down
14 changes: 14 additions & 0 deletions src/Output/Configurator/ConfiguratorInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Tomaj\NetteApi\Output\Configurator;

use Nette\Application\Request;

interface ConfiguratorInterface
{
public function validateSchema(?Request $request = null): bool;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ten request je v interface-y len kvoli tomu QueryConfiguratoru? nebolo by lepsie dat Http\Request do konstruktoru QueryConfiguratoru a ostatne implementacie nechat bez parametrov?


public function showErrorDetail(?Request $request = null): bool;
}
21 changes: 21 additions & 0 deletions src/Output/Configurator/DebuggerConfigurator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Tomaj\NetteApi\Output\Configurator;

use Nette\Application\Request;
use Tracy\Debugger;

class DebuggerConfigurator implements ConfiguratorInterface
{
public function validateSchema(?Request $request = null): bool
{
return !Debugger::$productionMode;
}

public function showErrorDetail(?Request $request = null): bool
{
return !Debugger::$productionMode;
}
}
28 changes: 28 additions & 0 deletions src/Output/Configurator/EnvConfigurator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Tomaj\NetteApi\Output\Configurator;

use Nette\Application\Request;

class EnvConfigurator implements ConfiguratorInterface
{
public function validateSchema(?Request $request = null): bool
{
$appEnv = getenv("APP_ENV");
Martin-Beranek marked this conversation as resolved.
Show resolved Hide resolved
if ($appEnv === "production") {
return false;
}
return true;
}

public function showErrorDetail(?Request $request = null): bool
{
$appEnv = getenv("APP_ENV");
if ($appEnv === "production") {
return false;
}
return true;
}
}
36 changes: 36 additions & 0 deletions src/Output/Configurator/QueryConfigurator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Tomaj\NetteApi\Output\Configurator;

use Nette\Application\Request;

class QueryConfigurator implements ConfiguratorInterface
{
/*
### Disable schema validation in not production environment
Include get parameter no_schema_validate in your request to disable schema validation. This is useful for testing purposes.
* schema validation is disabled by default in production environment for performance reasons

### Add additional info to error response
Include get parameter error_detail in your request to show additional info in error response. This is useful for debugging purposes.
*/
public function validateSchema(?Request $request = null): bool
{
if ($request === null) {
return false;
}
$getParams = $request->getParameters();
return !isset($getParams['no_schema_validate']);
Martin-Beranek marked this conversation as resolved.
Show resolved Hide resolved
}

public function showErrorDetail(?Request $request = null): bool
{
if ($request === null) {
return false;
}
$getParams = $request->getParameters();
return isset($getParams['error_detail']);
Martin-Beranek marked this conversation as resolved.
Show resolved Hide resolved
}
}
11 changes: 8 additions & 3 deletions src/Presenters/ApiPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Tomaj\NetteApi\RateLimit\RateLimitInterface;
use Tomaj\NetteApi\Response\JsonApiResponse;
use Tracy\Debugger;
use Tomaj\NetteApi\Output\Configurator\ConfiguratorInterface;

final class ApiPresenter implements IPresenter
{
Expand All @@ -33,6 +34,9 @@ final class ApiPresenter implements IPresenter
/** @var Container @inject */
public $context;

/** @var ConfiguratorInterface @inject */
public $outputConfigurator;

/**
* CORS header settings
*
Expand Down Expand Up @@ -83,7 +87,7 @@ public function run(Request $request): IResponse
$paramsProcessor = new ParamsProcessor($handler->params());
if ($paramsProcessor->isError()) {
$this->response->setCode(Response::S400_BAD_REQUEST);
if (!Debugger::$productionMode) {
if ($this->outputConfigurator->showErrorDetail($request)) {
$response = new JsonResponse(['status' => 'error', 'message' => 'wrong input', 'detail' => $paramsProcessor->getErrors()]);
} else {
$response = new JsonResponse(['status' => 'error', 'message' => 'wrong input']);
Expand All @@ -94,7 +98,8 @@ public function run(Request $request): IResponse
try {
$response = $handler->handle($params);
$code = $response->getCode();
if (!Debugger::$productionMode) { /// If not production mode, validate output

if ($this->outputConfigurator->validateSchema($request)) { /// If not production mode or no no_schema_validate parameter present, validate output
Martin-Beranek marked this conversation as resolved.
Show resolved Hide resolved
$outputValid = count($handler->outputs()) === 0; // back compatibility for handlers with no outputs defined
$outputValidatorErrors = [];
foreach ($handler->outputs() as $output) {
Expand All @@ -115,7 +120,7 @@ public function run(Request $request): IResponse
}
}
} catch (Throwable $exception) {
if (!Debugger::$productionMode) {
if ($this->outputConfigurator->showErrorDetail($request)) {
$response = new JsonApiResponse(Response::S500_INTERNAL_SERVER_ERROR, ['status' => 'error', 'message' => 'Internal server error', 'detail' => $exception->getMessage()]);
} else {
$response = new JsonApiResponse(Response::S500_INTERNAL_SERVER_ERROR, ['status' => 'error', 'message' => 'Internal server error']);
Expand Down
Loading