REST z wykorzystaniem Zend Framework

04 mar 2009

REST to usługa sieciowa używana do dystrybuowania treści – głównie – pomiędzy aplikacjami internetowymi (tzw. web service). REST nie jest jedynym dostępnym web service; innymi popularnymi usługami są m.in. XML-RPC oraz SOAP.

Jako że REST jest prostym i lekkim protokołem, jest on – obok XML-RPC – najczęściej wykorzystywany we wszelkiego rodzaju API (Application Programming Interface).
Jest lekki, bo wszelkie requesty są standardowymi żądaniami HTTP (wykorzystywane są przy tym metody GET, POST, PUT oraz DELETE). Odpowiedzi są standardowymi odpowiedziami serwera (nagłówki + treść), przy czym status odpowiedzi informuje o błędzie (np. 404 Not Found dla nieznanej metody, 401 Unauthorized w przypadku braku lub błędnej autoryzacji, 200 OK informujący o powodzeniu operacji).

W Zend Framework mamy gotowy komponent do obsługi REST, dzięki niemu możemy łatwo stworzyć zarówno klienta (Zend_Rest_Client), jaki i serwer (Zend_Rest_Server).

Serwer REST zbudowany z wykorzystaniem Zend_Rest_Server:

$rest = new Zend_Rest_Server();
$rest->setClass('MyClass');
$rest->handle();

Komunikujemy się z serwerem REST używając Zend_Rest_Client:

$restClient = new Zend_Rest_Client('http://example.com/api/rest');
$restClientResponse = $restClient->getDate()->get();
if ($restClientResponse->isSuccess()) {
    echo $restClientResponse;
}

Wydawałoby się, że to kompletne rozwiązanie – możemy zarówno coś udostępnić, jak również odpytać. Niestety tak nie jest!
ZF umożliwia obsługę REST tylko z wykorzystaniem formatu XML. Co zatem mamy zrobić jeśli chcemy wykorzystać REST API obsługujące tylko format JSON (obok XML najczęściej stosowany format REST)?

Rozwiązanie jest proste – do odpytania REST API w formacie JSON wykorzystamy Zend_Http_Client, a wynik dekodujemy korzystając z Zend_Json.

Przykład odpytania REST API obsługującego format JSON:

$httpClient = new Zend_Http_Client('http://example.com/api/json');
$httpClient->setHeaders('Accept: application/json');
$httpClientResponse = $httpClient->request('get')->getBody();

OK, wiemy już zatem jak odpytać API obsługujące format JSON, wiemy też jak wykorzystać Zend_Rest do budowy/odpytania API wykorzystującego XML.
Co jeśli chcemy utworzyć serwer REST oferujący dane w formacie JSON (oraz XML)?

Musimy wykonać sprawdzenie – nagłówka Accept – i w zależności, czy znajdzie się tam application/json, czy nie, odpowiedzieć w odpowiednim formacie (domyślnie XML).

$rest = new Zend_Rest_Server();
$rest->setClass('MyClass');
$rest->returnResponse(true);
 // informujemy moduł, że chcemy przechwycić dpowiedź Zend_Rest_Server do zmiennej...
$response = $rest->handle();
 // ...i to też robimy, wywołują metodę handle()
// domyślny typ danych (xml)
$contentType = 'text/xml';
// sprawdzamy czy zadano danych JSON
if (preg_match('/(application\/json)/', $this->getRequest()->getServer('HTTP_ACCEPT'))) {
    // konwertujemy dane XML => JSON
    $response    = Zend_Json::fromXml($response, true);
    // nagłówek dla danych JSON
    $contentType= 'application/json';
}
// zwracamy dane ($response) z odpowiednim nagłówkiem Content-type
$responseObject = $this->getResponse()->setBody($response)->setHeader('Content-type', $contentType, true);
// pozostaje jeszcze wysłanie odpowiedniego statusu, zgodnie ze specyfikacją REST
$restHeaders = $rest->getHeaders();
// pobieramy nagłówki (drugi element tablicy - jeśli wystąpił błąd - zawiera status błędu)
if (isset($restHeaders[1])) {
    $responseObject->setRawHeader($restHeaders[1]);
}

Gotowe! Teraz możesz udostępnić własne API lub wykorzystać jedno z dostępnych :)

Komentarzy: 3

Rozumie, ze wspiera GET, POST, PUT i DELETE ? Jak zrobic, zeby nie owijal JSON’a w XML ??

dex @ 12 mar 2009 17:36. #

po pierwsze nauczyc sie polskiego.
a po drugie czytac ze zrozumieniem. ;-)

warden @ 24 kwi 2009 20:19. #

Piszę serwer RESTowy dla klienta androidowego i zapytano mnie, czy w JSONie nie mogę zwracać danych. Pomocne, dzięki!

Adrian Pawlik @ 04 maj 2009 14:22. #

Skomentuj wpis

Pole wymagane.

Pole wymagane. Adres nie będzie publikowany!

Jeśli posiadasz :)

 


Switch to our mobile site