by Enrico Zimuel
Senior Software Engineer
Rogue Wave Software (USA)
ZendCon & OpenEnterprise, Las Vegas (NV), Oct 15, 2018
|
HTTP Request:
GET /api/version
HTTP Response:
HTTP/1.1 200 OK
Connection: close
Content-Length: 17
Content-Type: application/json
{
"version": "1.0"
}
HAL-JSON (Hypertext Application Language JSON), Internet-Draft
GET /api/user/ezimuel
{
"_links": {
"self": {
"href": "http://domain/api/user/ezimuel"
},
"contacts": [
{ "href": "http://domain/api/user/mwop" },
{ "href": "http://domain/api/user/zeevs" }
]
},
"id": "ezimuel",
"name": "Enrico Zimuel"
}
Problem Details (RFC 7807)
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.net/validation-error",
"title": "Your request parameters didn't validate.",
"invalid-params": [
{
"name": "age",
"reason": "must be a positive integer"
},
]
}
Global variables:
Common interfaces for representing HTTP messages as described in RFC 7230 and RFC 7231, and URIs for use with HTTP messages as described in RFC 3986
// Returns an empty array if not found:
$header = $message->getHeader('Accept');
// Returns an empty string if not found:
$header = $message->getHeaderLine('Accept');
// Test for a header:
if (! $message->hasHeader('Accept')) {
}
// If the header has multiple values, fetch them
// as an array:
$values = $message->getHeader('X-Foo');
// Or as a comma-separated string:
$values = $message->getHeaderLine('X-Foo');
zendframework/zend-diactoros implements PSR-7
$response = $response->withStatus(418, "I'm a teapot");
$query = $request->getQueryParams();
$body = $request->getBodyParams();
$request = $request->withBodyParams(json_decode($body));
A function that gets a request and generates a response
function ($request)
{
// do something with $request
return $response;
}
function ($request, callable $delegate)
{
// delegating $request to another middleware
$response = $delegate($request);
return $response;
}
function ($request, callable $delegate) use ($cache)
{
if ($cache->has($request)) {
return $cache->get($request);
}
$response = $delegate($request);
$cache->set($request, $response);
return $response;
}
Common interfaces for HTTP server request handlers and HTTP server middleware components that use HTTP messages as described by PSR-7
namespace Psr\Http\Server;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
interface RequestHandlerInterface
{
public function handle(
ServerRequestInterface $request
): ResponseInterface;
}
An handler returns a response, without delegate
namespace Psr\Http\Server;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
interface MiddlewareInterface
{
public function process(
ServerRequestInterface $request,
RequestHandlerInterface $handler
): ResponseInterface;
}
A middleware participates in processing an HTTP message, it may deletegate.
The PHP framework for middleware applications
You can install Expressive using composer:
composer create-project zendframework/zend-expressive-skeleton api
$app->get('/api/ping', function ($request) {
return JsonResponse(['ack' => time()])
});
// or implement a RequestHandlerInterface
$app->get('/api/ping', App\Handler\PingHandler::class);
namespace App\Handler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Zend\Diactoros\Response\JsonResponse;
class PingHandler implements RequestHandlerInterface
{
public function handle(
ServerRequestInterface $request
) : ResponseInterface {
return new JsonResponse(['ack' => time()]);
}
}
$app->pipe(ErrorHandler::class);
$app->pipe(ServerUrlMiddleware::class);
$app->pipe(RouteMiddleware::class);
$app->pipe(ImplicitHeadMiddleware::class);
$app->pipe(ImplicitOptionsMiddleware::class);
$app->pipe(MethodNotAllowedMiddleware::class);
$app->pipe(UrlHelperMiddleware::class);
$app->pipe(ProblemDetailsMiddleware::class);
$app->pipe(DispatchMiddleware::class);
$app->pipe(NotFoundHandler::class);
/config/pipeline.php
$app->route('/api/users[/{id}]', [
Authentication\AuthenticationMiddleware::class,
Authorization\AuthorizationMiddleware::class,
Api\Action\UserAction::class
], ['GET', 'POST', 'PATCH', 'DELETE'], 'api.users');
// or route each HTTP method
$app->get('/api/users[/{id}]', ..., 'api.users.get');
$app->post('/api/users', ..., 'api.users.post');
$app->patch('/api/users/{id}', ..., 'api.users.patch');
$app->delete('/api/users/{id}', ..., 'api.users.delete');
More info: http://getexpressive.org
Contact me: enrico.zimuel [at] roguewave.com
Follow me: @ezimuel
This work is licensed under a
Creative Commons Attribution-ShareAlike 3.0 Unported License.
I used reveal.js to make this presentation.