kleijnweb/php-api-middleware

Middleware for kleijnweb/php-api-descriptions.

v1.0.0-alpha1 2017-05-15 19:15 UTC

README

Build Status Coverage Status Scrutinizer Code Quality Latest Stable Version

Middleware for kleijnweb/php-api-descriptions.

Components

DefaultPipe

A complete chain of middleware that can process OpenAPI requests from begin to end, once you add some command handlers. The middleware in this section is executed in order listed.

You can append and prepend 3rd party middleware, ResultSerializer is appended just before dispatching.

OperationMatcher

Determines which Operation object a request maps to (routing), or returning 404/405 responses respectively. Returns an request object some API description objects as well as the path parameters added as attributes.

BodyParsing

Parses the request body. In DefaultPipe uses JsonBodyParser but the parser is injectable.

ParameterAssembler

Coerces all the request data that qualify as OpenAPI parameters (bar the body) and sets them as request attributes.

MessageValidator

Validates the incoming request using the OpenAPI document and returns a 400 response with failure messages when invalid.

ParameterHydrator

Uses kleijnweb/php-api-hydrator to hydrate custom typed objects and \DateTime.

CommandDispatcher

Dead simple command dispatcher that invokes callables with the arguments in order as found in the request.

ResponseBodyDehydrator

Picks up the result of CommandDispatcher and produces a response object.

Example

require __DIR__.'/../vendor/autoload.php';

use Doctrine\Common\Cache\ApcuCache;
use KleijnWeb\PhpApi\Descriptions\Description\Repository;
use KleijnWeb\PhpApi\Middleware\DefaultPipe;
use KleijnWeb\PhpApi\Middleware\Tests\Functional\Pet;
use Middlewares\Utils\Factory;
use Zend\Diactoros\Response\SapiEmitter;
use Zend\Diactoros\ServerRequestFactory;

$cache = new ApcuCache();

$commands = [
    '/pets/{id}:get' => function (int $id) use ($cache): Pet {
        return unserialize($cache->fetch($id));
    },
    '/pets:post'     => function (Pet $pet) use ($cache) {
        $count = $cache->fetch('count');
        $pet->setId($id = $count + 1);
        $cache->save($id, serialize($pet));
        $cache->save('count', $id);

        return $pet;
    },
];

$repository = new Repository(null, $cache);
$repository->register(__DIR__.'/../tests/Functional/petstore.yml');

$pipe = new DefaultPipe(
    $repository,
    $commands,
    ['KleijnWeb\PhpApi\Middleware\Tests\Functional']
);

$request = ServerRequestFactory::fromGlobals($_SERVER, $_GET, $_POST, $_COOKIE, $_FILES);

$response = $pipe->dispatch($request, function () {
    return Factory::createResponse(500);
});

(new SapiEmitter())->emit($response);

Verify that it works properly by starting a dev server and issuing some cURL requests:

php -S localhost:1234 test.php
curl -vH "Content-Type: application/json" -d '{"name":"doggie"}' http://localhost:1234/pets
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 1234 (#0)
> POST /pets HTTP/1.1
> Host: localhost:1234
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 17
> 
* upload completely sent off: 17 out of 17 bytes
< HTTP/1.1 200 OK
< Host: localhost:1234
< Connection: close
< X-Powered-By: PHP/7.0.15-0ubuntu0.16.04.4
< Content-Type: application/json
< Content-Length: 24
< 
* Closing connection 0
{"id":1,"name":"doggie"}

$ curl -vH "Content-Type: application/json" -d '{}' http://localhost:1234/pets
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 1234 (#0)
> POST /pets HTTP/1.1
> Host: localhost:1234
> User-Agent: curl/7.47.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 2
> 
* upload completely sent off: 2 out of 2 bytes
< HTTP/1.1 400 Bad Request
< Host: localhost:1234
< Connection: close
< X-Powered-By: PHP/7.0.15-0ubuntu0.16.04.4
< Content-Type: application/json
< Content-Length: 55
< 
* Closing connection 0
{"errors":{"pet.name":"The property name is required"}}

 curl -v  http://localhost:1234/pets/1
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 1234 (#0)
> GET /pets/1 HTTP/1.1
> Host: localhost:1234
> User-Agent: curl/7.47.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Host: localhost:1234
< Connection: close
< X-Powered-By: PHP/7.0.15-0ubuntu0.16.04.4
< Content-Type: application/json
< Content-Length: 24
< 
* Closing connection 0
{"id":1,"name":"doggie"}

Contributing

Pull requests are very welcome, but the code has to be PSR2 compliant, follow used conventions concerning parameter and return type declarations, and the coverage can not go down.

License

KleijnWeb\PhpApi\Middleware is made available under the terms of the LGPL, version 3.0.