Restify

 Restify

Prezentacja i omówienie możliwości frameworku Restify do tworzenia RESTful webservices w oparciu o Node.js.

572884b36b9538ad273ef7dd7e23b228?s=128

Adam Jodłowski

July 29, 2012
Tweet

Transcript

  1. 3.

    3 Node.js • środowisko uruchomieniowe JavaScript na serwerze • przeznaczone

    dla nowoczesnych aplikacji nastawionych na bogatą interakcję z klientem • zorientowane na zdarzenia (event loop) • jednowątkowość wymusza nieblokujące operacje I/O • podstawą projektu jest silnik JavaScript Google V8, kilka wbudowanych bibliotek i moduły użytkowników • implementuje ECMAScript 5, część standardu CommonJS i dostarcza konsolę REPL
  2. 5.

    5 REpresentational State Transfer • paradygmat tworzenia usług klient-serwer zainspirowany

    sposobem działania protokołu HTTP • opiera się na pojęciu reprezentacji zasobu i możliwych do wykonania na nim metod zmieniających jego stan • główne cechy • architektura klient-serwer • zorientowanie na zasoby • jednolity interfejs • bezstanowość
  3. 7.

    7 Restify v1.3 • moduł Node.js ułatwiający tworzenie poprawnych usług

    sieciowych zgodnych z paradygmatem REST • opracowany z myślą o lepszej kontroli nad HTTP niż dają to frameworki webowe (np. Express) • zawiera szereg udogodnień (wersjonowanie, sumy kontrolne, filtry) dla tworzenia tzw. strict APIs
  4. 8.

    8 Instalacja i uruchomienie $ npm install restify var restify

    = require('restify'); var server = restify.createServer(); server.listen(8080, function() { console.log('%s listening at %s', server.name, server.url); }); function respond(req, res, next) { res.send('hello ' + req.params.name); } server.get('/hello/:name', respond); $ node server.js restify listening at http://0.0.0.0:8080
  5. 9.

    9 Sprawdzenie, czy działa $ curl -is http://localhost:8080/hello/adamus -H 'Accept:

    text/plain' HTTP/1.1 200 OK Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Accept, Accept-Version, Content-Length, Content- MD5, Content-Type, Date, X-Api-Version Access-Control-Expose-Headers: X-Api-Version, X-Request-Id, X-Response-Time Server: restify X-Request-Id: 06ace5a0-87ab-4faf-b76c-9a9a35682937 Access-Control-Allow-Methods: GET Connection: close Content-Length: 12 Content-MD5: TNyTQnhx7KlWEKi+aTn9zA== Content-Type: text/plain; charset=UTF-8 Date: Thu, 15 Mar 2012 12:24:49 GMT X-Response-Time: 3 hello adamus // domyślny Content-Type to application/json
  6. 11.

    11 Konfiguracja i wspólne handlery żądań Obiekt konfiguracyjny używany przy

    tworzeniu serwera var fs = require('fs'); var options = { certificate: fs.readFileSync('certificate.crt'), key: fs.readFileSync('private.key'), name: 'Restify Server 1.0', version: '1.0.0', // X-Api-Version: 1.0.0 formatters: { 'format': function() { ... } } }; var server = restify.createServer(options); Obsługa żądań przed lub po wywołaniu metod rutingu server.pre(function (req, res, next) { // server.pre([f1, f2, ...]); // przetwarzanie ... return next(); }); // kolejność wywołania zależna od kolejności rejestracji względem rutingu server.use(function (req, res, next) { ... });
  7. 12.

    12 Ruting Ruting oparty jest o metody dostępu i ścieżki

    zasobów, parametry w formie URL-encoded lub JSON są automatycznie parsowane server.get('/posts/:id', function (req, res, next) { console.log('post id = ' + req.params.id); res.send(200, {author: 'adamus', content: 'this is a post'}); return next(); }); $ curl http://localhost:8080/posts/8 {"author":"adamus","content":"this is a post"} // komunikat konsoli serwera: post id = 8 Pozostałe metody obsługujemy analogicznie server.post(...); server.put(...); server.del(...); server.head(...); W miejsce ścieżki możemy przekazać obiekt RegExp a dopasowania kolejnych grup otrzymamy w req.params[0], req.params[1] itd.
  8. 13.

    13 Wersjonowanie rutingu Protokół HTTP nie definiuje sposobu wersjonowania RESTfulowych

    API, przyjęto zatem rozwiązanie Semantic Versioning (SemVer) server.get({path: '/posts/:id', version: '2.0.1'}, function (req, res, next) { ... }); server.get({path: '/posts/:id', version: '1.2.3'}, function (req, res, next) { ... }); $ curl localhost:8080/posts/8 -H 'Accept-Version: 1' // otrzymamy wersję 1.2.3 $ curl localhost:8080/posts/8 // otrzymamy pierwszą zarejestrowaną wersję, czyli 2.0.1 $ curl localhost:8080/posts/8 -H 'Accept-Version: 3' HTTP/1.1 400 Bad Request {"code":"InvalidVersion","message":"GET /posts/8 supports versions: 2.0.1, 1.2.3"} W powyższych ścieżkach możemy podać tablice kolejnych wersji W taki sam sposób działa parametr version całego serwera, ale dotyczy wszystkich ścieżek, którym nie nadano wersji (pełni rolę domyślną)
  9. 14.

    14 Negocjacja reprezentacji treści Wysyłając odpowiedź metodą send() wartość nagłówka

    Content-Type może być ustalona automatycznie na podstawie dostępnych formaterów, wbudowano obsługę application/octet-stream*, application/json i text/plain Własne formatery treści podajemy w konfiguracji serwera formatters: { 'application/my-format': function (req, res, body) { // logika konwersji formatu return reprezentacja_body; } // kolejne formatery ... } Wysyłając żądanie z określonym formatem w nagłówku Accept, zostanie odesłana postać zwrócona w funkcji obsługi tego formatu Obsługiwane przez serwer formaty znajdują się w tablicy server.acceptable
  10. 15.

    15 Obsługa błędów Nieobsłużone błędy powodują zwrócenie kodu 500 Możemy

    zwracać błędy pierwszym argumentem liczbowym metody send() oraz korzystać z obiektu Error('wiadomość') res.send(401, new Error('Nie masz uprawnień')); Restify posiada zestaw symbolicznych błędów HttpError i RestError (niestandardowe błędy z dodatkowym opisem w postaci JSON) return next(new restify.ConflictError("Żądanie jest konfliktowe")); // HttpError return next(new restify.InvalidArgumentError("Niepoprawny argument")); // RestError // obie instrukcje zwrócą kod 409
  11. 16.

    16 Zdarzenia rozgłaszane (EventEmitter) Restify rozgłasza standardowe zdarzenia z modułu

    http.Server Node.js oraz własne, takie jak: • 'NotFound' • 'MethodNotAllowed' • 'VersionNotAllowed' • 'after' • 'uncaughtException' Nasłuchujemy na zdarzenia przez server.on('zdarzenie', funkcja_obsługi(...) { ... });
  12. 17.

    17 Wbudowane pluginy Restify dostarcza kilka pluginów do przetwarzania żądań

    • AcceptParser • QueryParser • BodyParser • Throttle (token bucket) • ConditionalRequest • ETag / If-None-Match • LastModified / If-Modified-Since • AuditLogger
  13. 18.

    18 Obiekt żądania Do standardowych właściwości z http.ServerRequest (method, url,

    headers) Restify dodaje własne .header('Authorization') – pobranie wartości nagłówka .accepts('text/plain') – czy żądanie akceptuje format .is('application/json') – czy żądanie jest danego typu .contentLength, .contentType .id – UUID żądania .time – czas dotarcia do serwera .secure – czy żądanie przyszło w sesji SSL
  14. 19.

    19 Obiekt odpowiedzi Do standardowych właściwości z http.ServerResponse (statusCode, get/set/removeHeader)

    Restify dodaje własne .header('X-My-Header', '...') – ustawienie wartości nagłówka .cache(typ, opcje) – ustawienie nagłówka Cache-Control .status(200)/.code – ustawienie kodu odpowiedzi .contentLength, .contentType .charSet – kodowanie dopisywane do Content-Type .id – UUID żądania Możemy nadpisać domyślnie odsyłane nagłówki i ich treść restify.defaultResponseHeaders = function(data) { this.header('Server', 'Mój serwer'); }; // this to obiekt odpowiedzi a data to gotowe do wysłania ciało (response body)
  15. 21.

    21 Restify Client Moduł kliencki pozwala konsumować usługi sieciowe •

    JsonClient • wysyła i odbiera wiadomości w formacie JSON • StringClient • wysyła Url-Encoded i odbiera czysty tekst, na przykład XML • HttpClient • umożliwia pracę ze strumieniami danych na poziomie oferowanym przez moduły http/https Node.js Konfiguracja żądań obejmuje metodę dostępu, nagłówki, czas timeoutu, liczbę powtórzeń wywołania itp.
  16. 23.

    23 Problemy z Restify • Nieaktualna i niedokładna dokumentacja •

    Brak obsługi niestandardowych metod HTTP • Brak negocjacji Accept-Charset, -Encoding*, -Language • Brak obsługi nietrywialnych metod autoryzacji • Niespójne API Rozwiązanie? Fork me on GitHub
  17. 25.

    25 Warto poczytać • Just what is Node.js? http://www.ibm.com/developerworks/opensource/library/os-nodejs/ •

    What is Node.js? http://radar.oreilly.com/2011/07/what-is-node.html • Nobody Understands REST or HTTP http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http • Some People Understand REST and HTTP http://blog.steveklabnik.com/posts/2011-08-07-some-people-understand-rest-and-http • How I Explained REST to My Wife http://tomayko.com/writings/rest-to-my-wife • Restify documentation http://mcavage.github.com/node-restify/ • RESTful Web Services Cookbook Subbu Allamaraju, O’Reilly 2010, Yahoo! Press