tuupola / slim-api-skeleton

Compare 2cde552 ... +6 ... 68645e4

Showing 7 of 48 files from the diff.
Other files ignored by Codecov
Makefile has changed.
app.php has changed.
.gitignore has changed.
README.md has changed.
routes/todos.php has changed.
Vagrantfile has changed.
routes/token.php has changed.
composer.json has changed.
.travis.yml was deleted.

@@ -17,25 +17,32 @@
Loading
17 17
namespace Skeleton\Application\Response;
18 18
19 19
use Crell\ApiProblem\ApiProblem;
20 -
use Slim\Http\Headers;
21 -
use Slim\Http\Response;
22 -
use Slim\Http\Stream;
20 +
use Psr\Http\Message\ResponseFactoryInterface;
21 +
use Psr\Http\Message\ResponseInterface;
22 +
use Tuupola\Http\Factory\ResponseFactory;
23 23
24 -
class NotFoundResponse extends Response
24 +
class NotFoundResponseFactory
25 25
{
26 -
    public function __construct($message, $status = 404)
26 +
    private $factory;
27 +
28 +
    public function __construct(ResponseFactoryInterface $factory = null)
29 +
    {
30 +
        $this->factory = $factory ?: new ResponseFactory;
31 +
    }
32 +
33 +
    public function create($message, $status = 404)
27 34
    {
28 35
        $problem = new ApiProblem(
29 36
            $message,
30 37
            "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
31 38
        );
32 39
        $problem->setStatus($status);
33 40
34 -
        $handle = fopen("php://temp", "wb+");
35 -
        $body = new Stream($handle);
41 +
        $response = $this->factory->createResponse($status);
42 +
        $body = $response->getBody();
36 43
        $body->write($problem->asJson(true));
37 -
        $headers = new Headers;
38 -
        $headers->set("Content-type", "application/problem+json");
39 -
        parent::__construct($status, $headers, $body);
44 +
        return $response
45 +
            ->withHeader("Content-type", "application/problem+json")
46 +
            ->withBody($body);
40 47
    }
41 48
}

@@ -1,12 +1,8 @@
Loading
1 1
<?php
2 +
declare(strict_types=1);
2 3
3 4
/*
4 -
 * This file is part of the Slim API skeleton package.
5 -
 *
6 -
 * This handler is called in case of otherwise uncaught exceptions.
7 -
 * However due to way Slim works CORS headers are lost. It would be better
8 -
 * to handle exceptions gracefully by returning one of the predefined
9 -
 * error responses instead.
5 +
 * This file is part of the Slim API skeleton package
10 6
 *
11 7
 * Copyright (c) 2016-2017 Mika Tuupola
12 8
 *
@@ -21,34 +17,54 @@
Loading
21 17
namespace Skeleton\Infrastructure\Slim\Handler;
22 18
23 19
use Crell\ApiProblem\ApiProblem;
24 -
use Psr\Http\Message\ServerRequestInterface as Request;
25 -
use Psr\Http\Message\ResponseInterface as Response;
26 -
use Psr\Log\LoggerInterface;
27 -
use Slim\Handlers\AbstractError;
20 +
use Psr\Http\Message\ResponseInterface;
21 +
use Slim\Exception\HttpBadRequestException;
22 +
use Slim\Exception\HttpException;
23 +
use Slim\Exception\HttpForbiddenException;
24 +
use Slim\Exception\HttpMethodNotAllowedException;
25 +
use Slim\Exception\HttpNotFoundException;
26 +
use Slim\Exception\HttpNotImplementedException;
27 +
use Slim\Exception\HttpUnauthorizedException;
28 +
use Slim\Handlers\ErrorHandler;
29 +
use Exception;
28 30
use Throwable;
29 31
30 -
final class ApiErrorHandler extends AbstractError
32 +
class ApiErrorHandler extends ErrorHandler
31 33
{
32 -
    protected $logger;
33 -
34 -
    public function __construct(LoggerInterface $logger)
35 -
    {
36 -
        $this->logger = $logger;
37 -
    }
38 -
39 -
    public function __invoke(Request $request, Response $response, Throwable $throwable)
34 +
    protected function respond(): ResponseInterface
40 35
    {
41 -
        $this->logger->critical($throwable->getMessage());
36 +
        //$this->logger->critical($throwable->getMessage());
42 37
43 -
        $status = $throwable->getCode() ?: 500;
38 +
        $response = $this->responseFactory->createResponse();
44 39
45 -
        $problem = new ApiProblem($throwable->getMessage(), "about:blank");
40 +
        $status = $this->exception->getCode() ?: 500;
41 +
        $problem = new ApiProblem($this->exception->getMessage(), "about:blank");
46 42
        $problem->setStatus($status);
47 -
        $body = $problem->asJson(true);
43 +
44 +
        if ($this->exception instanceof HttpMethodNotAllowedException) {
45 +
            $allowed = $this->exception->getAllowedMethods();
46 +
47 +
            /* 405 response must include Allow header. */
48 +
            $response = $response->withHeader("Allow", implode(", ", $allowed));
49 +
50 +
            /* Show allowed methods also in API problem body. */
51 +
            if (1 === count($allowed)) {
52 +
                $detail = "Request method must be {$allowed[0]}";
53 +
            } else {
54 +
                $last = array_pop($allowed);
55 +
                $first = implode(", ", $allowed);
56 +
                $detail = "Request method must be either {$first} or {$last}.";
57 +
            }
58 +
            $problem->setDetail($detail);
59 +
        }
60 +
        $json = $problem->asJson(true);
61 +
62 +
        $body = $response->getBody();
63 +
        $body->write($json);
48 64
49 65
        return $response
50 -
                ->withStatus($status)
51 -
                ->withHeader("Content-type", "application/problem+json")
52 -
                ->write($body);
66 +
            ->withStatus($status)
67 +
            ->withHeader("Content-type", "application/problem+json")
68 +
            ->withBody($body);
53 69
    }
54 70
}

@@ -0,0 +1,45 @@
Loading
1 +
<?php
2 +
declare(strict_types=1);
3 +
4 +
/*
5 +
 * This file is part of the Slim API skeleton package
6 +
 *
7 +
 * Copyright (c) 2016-2017 Mika Tuupola
8 +
 *
9 +
 * Licensed under the MIT license:
10 +
 *   http://www.opensource.org/licenses/mit-license.php
11 +
 *
12 +
 * Project home:
13 +
 *   https://github.com/tuupola/slim-api-skeleton
14 +
 *
15 +
 */
16 +
17 +
namespace Skeleton\Application\Response;
18 +
19 +
use Crell\ApiProblem\ApiProblem;
20 +
use Psr\Http\Message\ResponseFactoryInterface;
21 +
use Psr\Http\Message\ResponseInterface;
22 +
use Tuupola\Http\Factory\ResponseFactory;
23 +
24 +
class UnauthorizedResponseFactory
25 +
{
26 +
    private $factory;
27 +
28 +
    public function __construct(ResponseFactoryInterface $factory = null)
29 +
    {
30 +
        $this->factory = $factory ?: new ResponseFactory;
31 +
    }
32 +
33 +
    public function create($message, $status = 401)
34 +
    {
35 +
        $problem = new ApiProblem($message, "about:blank");
36 +
        $problem->setStatus($status);
37 +
38 +
        $response = $this->factory->createResponse($status);
39 +
        $body = $response->getBody();
40 +
        $body->write($problem->asJson(true));
41 +
        return $response
42 +
            ->withHeader("Content-type", "application/problem+json")
43 +
            ->withBody($body);
44 +
    }
45 +
}

@@ -0,0 +1,45 @@
Loading
1 +
<?php
2 +
declare(strict_types=1);
3 +
4 +
/*
5 +
 * This file is part of the Slim API skeleton package
6 +
 *
7 +
 * Copyright (c) 2016-2017 Mika Tuupola
8 +
 *
9 +
 * Licensed under the MIT license:
10 +
 *   http://www.opensource.org/licenses/mit-license.php
11 +
 *
12 +
 * Project home:
13 +
 *   https://github.com/tuupola/slim-api-skeleton
14 +
 *
15 +
 */
16 +
17 +
namespace Skeleton\Application\Response;
18 +
19 +
use Crell\ApiProblem\ApiProblem;
20 +
use Psr\Http\Message\ResponseFactoryInterface;
21 +
use Psr\Http\Message\ResponseInterface;
22 +
use Tuupola\Http\Factory\ResponseFactory;
23 +
24 +
class ForbiddenResponseFactory
25 +
{
26 +
    private $factory;
27 +
28 +
    public function __construct(ResponseFactoryInterface $factory = null)
29 +
    {
30 +
        $this->factory = $factory ?: new ResponseFactory;
31 +
    }
32 +
33 +
    public function create($message, $status = 403): ResponseInterface
34 +
    {
35 +
        $problem = new ApiProblem($message, "about:blank");
36 +
        $problem->setStatus($status);
37 +
38 +
        $response = $this->factory->createResponse($status);
39 +
        $body = $response->getBody();
40 +
        $body->write($problem->asJson(true));
41 +
        return $response
42 +
            ->withHeader("Content-type", "application/problem+json")
43 +
            ->withBody($body);
44 +
    }
45 +
}

@@ -0,0 +1,45 @@
Loading
1 +
<?php
2 +
declare(strict_types=1);
3 +
4 +
/*
5 +
 * This file is part of the Slim API skeleton package
6 +
 *
7 +
 * Copyright (c) 2016-2017 Mika Tuupola
8 +
 *
9 +
 * Licensed under the MIT license:
10 +
 *   http://www.opensource.org/licenses/mit-license.php
11 +
 *
12 +
 * Project home:
13 +
 *   https://github.com/tuupola/slim-api-skeleton
14 +
 *
15 +
 */
16 +
17 +
namespace Skeleton\Application\Response;
18 +
19 +
use Crell\ApiProblem\ApiProblem;
20 +
use Psr\Http\Message\ResponseFactoryInterface;
21 +
use Psr\Http\Message\ResponseInterface;
22 +
use Tuupola\Http\Factory\ResponseFactory;
23 +
24 +
class PreconditionFailedResponseFactory
25 +
{
26 +
    private $factory;
27 +
28 +
    public function __construct(ResponseFactoryInterface $factory = null)
29 +
    {
30 +
        $this->factory = $factory ?: new ResponseFactory;
31 +
    }
32 +
33 +
    public function create($message, $status = 412)
34 +
    {
35 +
        $problem = new ApiProblem($message, "about:blank");
36 +
        $problem->setStatus($status);
37 +
38 +
        $response = $this->factory->createResponse($status);
39 +
        $body = $response->getBody();
40 +
        $body->write($problem->asJson(true));
41 +
        return $response
42 +
            ->withHeader("Content-type", "application/problem+json")
43 +
            ->withBody($body);
44 +
    }
45 +
}

Click to load this diff.
Loading diff...

Click to load this diff.
Loading diff...

Learn more Showing 7 files with coverage changes found.

Changes in src/Infrastructure/ZendTodoRepository.php
+3
Loading file...
Changes in src/Application/Todo/TodoHydratorFactory.php
+2
Loading file...
New file src/Application/Response/UnauthorizedResponseFactory.php
New
Loading file...
New file src/Application/Response/PreconditionFailedResponseFactory.php
New
Loading file...
New file src/Domain/TodoRepository.php
New
Loading file...
New file src/Application/Response/PreconditionRequiredResponseFactory.php
New
Loading file...
New file src/Application/Response/ForbiddenResponseFactory.php
New
Loading file...
Files Complexity Coverage
src ø -1.11% 98.61%
Project Totals (28 files) 108 98.61%
Loading