REST API
Request & Response

HyperText Transfer Protocol (HTTP)
The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems.
(Hypertext Transfer Protocol – HTTP/1.1)
HTTP Request
- Method
- Request URI
- Request Headers
- Request Body
HTTP Request Methods
- Definují, co budeme chtít dělat z resourcem na dané URI
- GET
- POST
- PUT, PATCH, DELETE
- OPTIONS
HTTP Request Headers
- Umožňují posílání dalších informací ohledně requestu a klienta
- Jsou ve formátu klíč: hodnota
- Příklad
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)
Accept: */*
HTTP Request Body
- Obsahuje data, která odesíláme na server
- Formát dat je specifikován v hlavičce
- Může být prázdné (např. pro GET requesty)
HTTP Request Example
curl -v http://example.com
GET / HTTP/1.1
Host: example.com
User-Agent: curl/7.54.0
Accept: */*
HTTP Response
- Status Code
- Response Headers
- Response Body
HTTP Response Status Code
- Trojciferný kód označující výsledek requestu
- 5 kategorií
- 1xx - Informační
- 2xx - Akce proběhla úspěšně
- 3xx - Přesměrování
- 4xx - Chyba na straně klienta
- 5xx - Chyba na straně serveru
HTTP Response Status Code 2xx
- 200 OK
- 201 Created
- 204 No Content
HTTP Response Status Code 4xx
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 405 Method Not Allowed
- 415 Unsupported Media Type
HTTP Response Headers
- Stejný formát jako Request Headers
- Obsahují metadata o odpovědi
- Formát odpovědi
- Velikost obsahu
- Informace pro cachování
- apod.
HTTP Response Body
- Data odpovědi
- Může být prázdné (např. pro 204 No Content odpovědi)
HTTP Response Example
HTTP/1.1 200 OK
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Mon, 26 Nov 2018 10:01:14 GMT
Etag: "1541025663+gzip+ident"
Expires: Mon, 03 Dec 2018 10:01:14 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (dca/53DB)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1270
<!doctype html>
...
Hypertext Transfer Protocol Secure (HTTPS)
- Rozšíření HTTP protokolu pro bezpečnou komunikaci po síti
- Používá Transport Layer Security (TLS) protokol pro šifrování
- HTTP protokol nepoužívá šifrování a je tak zranitelný vůči man-in-the-middle útokům
REpresentational State Transfer (REST)
- Architektura používaná k vývoji webových služeb
- RESTful API využívá HTTP protokol ke komunikaci
- Typicky používá JSON formát (ale ne nutně)
REST API - GET
- Výpis všech existujících entit –
GET /resource
> GET /products
< 200 OK
[
{ "id": 1, "name": "Fridge" },
{ "id": 2, "name": "Oven" }
]
REST API - GET
- Získání dat konkrétní entity –
GET /resource/:id
> GET /products/1
< 200 OK
{ "id": 1, "name": "Fridge" }
REST API - POST
- Vytvoření nové entity –
POST /resource
> POST /products
{"name": "Television"}
< 201 Created
Location: http://example.com/products/1
REST API - PUT
- Úprava existující entity (její kompletní přepsání), nebo vytvoření nové, známe-li požadovanou URI
> PUT /products/1
{"name": "Freezer"}
< 204 No Content
nebo
< 201 Created
REST API - PATCH
- Úprava existující entity (změna pouze zaslaných dat), nelze tvořit nová
> PATCH /products/1
{"name": "Microware"}
< 204 No Content
REST API - DELETE
- Smazání existující entity –
DELETE /resource/:id
> DELETE /product/1
< 204 No Content
Authentication & Authorization
- Authentication - ověření, kdo uživatel je
- Authorization - ověření, že daný uživatel může provádět požadovanou akci
- RESTful API je stateless, informace o uživateli musí být součástí každého requestu
- Authorization header
- Hlavička, která obsahuje credentials
HTTP Basic Auth
- Authorization header obsahuje slovo Basic a token vytvořený z uživatelského jména a hesla pomocí base64
- https://en.wikipedia.org/wiki/Base64
- Basic base64(username:password)
GET /
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Další možnosti
- OAuth2
- Json Web Tokens (JWT)
Nástroje pro vývoj - volání API
- curl - CLI
- Postman - https://www.getpostman.com - GUI
- GuzzleHttp - https://github.com/guzzle/guzzle] - PHP library
Slim Framework
- PHP microframework pro psaní webových aplikací a API
- https://www.slimframework.com
Slim Framework instalace
$ composer require slim/slim:^4.0
$ composer require slim/psr7
Example
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
// Create Slim app
$app = AppFactory::create();
// Define app routes
$app->get('/', function (Request $request, Response $response, $args) {
$response->getBody()->write("Hello world!");
return $response;
});
// Run app
$app->run();
Spuštění
- Pomocí PHP built-in webserveru
$ php -S localhost:8080
Response
- Nastavení status kódu (výchozí 201)
$response->withStatus(201);
$data = ['name' => 'Bob', 'age' => 40];
$payload = json_encode($data);
$response->getBody()->write($payload);
return $response->withHeader('Content-Type', 'application/json');
Request Headers
- https://www.slimframework.com/docs/v4/objects/request.html#the-request-headers
- Získání hlavičky/hlaviček v podobě pole
$headers = $request->getHeader('Content-Type');
Request Body
- https://www.slimframework.com/docs/v4/objects/request.html#the-request-body
- Získání JSON dat v podobě PHP asociativního pole (nutné použít middleware)
$parsedBody = $request->getParsedBody();
Middleware
<?php
$app = AppFactory::create();
$beforeMiddleware = function ($request, $handler) {
$response = $handler->handle($request);
$existingContent = (string) $response->getBody();
$response = new Response();
$response->getBody()->write('BEFORE' . $existingContent);
return $response;
};
$afterMiddleware = function ($request, $handler) {
$response = $handler->handle($request);
$response->getBody()->write('AFTER');
return $response;
};
$app->add($beforeMiddleware);
$app->add($afterMiddleware);
// ...
$app->run();
Seskupení cest
$app->group('', function (RouteCollectorProxy $group) {
$group->get('/billing', function ($request, $response, $args) {
// Route for /billing
});
$group->get('/invoice/{id:[0-9]+}', function ($request, $response, $args) {
// Route for /invoice/{id:[0-9]+}
});
})->add(new GroupMiddleware());