Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Rest sdk

447 views

Published on

Italian language
C++ REST SDK (codename Casablanca) in action

Published in: Software
  • Be the first to comment

  • Be the first to like this

Rest sdk

  1. 1. www.italiancpp.org Italian C++ Conference 2016 14 Maggio, Milano REST e Websocket in C++ diventano semplici e produttivi con il REST SDK Raffaele Rialdi Twitter: @raffaeler Email: raffaeler@vevy.com Website: http://iamraf.net
  2. 2. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community Chi sono … • Lavoro nella programmazione software dal 1987 •Senior Software Architect in Vevy Europe •Consulente in diversi ambiti (finanziario, automotive, racing, manufacturing, healthcare) • Specializzato sul mondo Microsoft •Ho iniziato con il DOS 1.0 … e ho seguito tutto ciò che è venuto dopo •Linguaggi preferiti: C++ e C# •Prediligo le tecnologie di "basso" livello e la «application security» •Microsoft MVP dall'anno 2003 • Trainer e speaker •Ho insegnato informatica per anni (e salutariamente continuo) •Partecipo a varie conferenze italiane e internazionali
  3. 3. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community Cos'è Casablanca REST SDK? • Una libreria che semplifica l'accesso a servizi REST e comunicazioni Websocket •Provvede anche servizi base (in beta) per creare semplici HTTP Server • Si basa su alcuni «pillars» fondamentali: 1. Gestione asincrona basata sui Task 2. Utilizzo di C++ "moderno" (è nata al momento dello standard C++11) 3. Cross-platform (Windows Desktop/Store/Phone, Linux, Android, Mac, iOS) 4. Cerca di offrire tutti i «building blocks» indispensabili (Json, Uri, conversioni Unicode, OAuth, etc.)
  4. 4. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community I problemi del cross-platform • In Windows, le stringhe sono wide (16 bit) •wchar_t, wstring, … • In Posix (Linux, Unix) le stringhe sono narrow (8 bit) •char, string, … •Il REST SDK definisce un tipo neutrale •Conversioni disponibili • to_string_t, to_utf8string, to_utf16string utility::string_t #ifdef _UTF16_STRINGS typedef wchar_t char_t ; typedef std::wstring string_t; #define _XPLATSTR(x) L ## x typedef std::wostringstream ostringstream_t; typedef std::wofstream ofstream_t; typedef std::wostream ostream_t; typedef std::wistream istream_t; typedef std::wifstream ifstream_t; typedef std::wistringstream istringstream_t; typedef std::wstringstream stringstream_t; #define ucout std::wcout #define ucin std::wcin #define ucerr std::wcerr #else ... basic_types.h U("Hello, world") std::string ansiRaf("raffaele"); string_t raf_t(to_string_t(ansiRaf)); std::string(begin(raf_t), end(raf_t));
  5. 5. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community PPL in una slide • Dimenticate i thread, pensate a task • Motivazioni: cross-platform, scalabilità, migliore schedulazione, codice più pulito, richiesto nelle applicazioni mobile • Ok, da domani li uso … ma che problemi ci sono? • Le STL sono sincrone, co-routines non fanno parte dello standard, i «futures» hanno diverse lacune • Arrivano le «Parallel Pattern Library» in soccorso • creare un task • scrivere una continuation • continuation con co_await • usare i task_completion • Un task setta il risultato • L'altro task è un attesa del risultato #include <ppl.h> using namespace concurrency; return create_task([] () {}); SumAsync(10, 20).then([=](int sum) { Process(sum); }; int result = co_await SumAsync(10, 20); Process(result); task_completion_event<bool> quit; quit->set(true); bool result = co_await pplx::task<bool>(quit);
  6. 6. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community concurrency::stream cheat sheet basic_istream<> stdio_istream<> async_iostream<> basic_iostream<> std concurrency::streams namespaces concurrency::streams::details streambuf<> basic_streambuf<> container_buffer<> producer_consumer_ buffer<> rawptr_buffer<> basic_ostream<> stdio_ostream<> async_ostream<> basic_ostream<> async_istream<> basic_istream<> astreambuf.h interopstream.h streams.h containerstream.h bytestream (factory) containerstream.h container_stream<> (factory) containerstream.h producerconsumerstream.h rawptrstream.h rawptr_stream (factory) rawptrstream.h interopstream.h interopstream.h astreambuf.h streams.h interopstream.h interopstream.h
  7. 7. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community typedefs definiti dal REST SDK typedef container_stream<std::basic_string<char>> stringstream; typedef stringstream::buffer_type stringstreambuf; typedef container_stream<utility::string_t> wstringstream; typedef wstringstream::buffer_type wstringstreambuf; typedef file_stream<uint8_t> fstream; typedef basic_ostream<uint8_t> ostream; typedef basic_istream<uint8_t> istream; typedef basic_ostream<utf16char> wostream; typedef basic_istream<utf16char> wistream;
  8. 8. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community File streams – leggere un file di testo file_buffer<> file_stream<> (factory) filestream.h std concurrency::streams namespaces concurrency::streams::details std::string Test1(const string_t& filename) { auto istr = slx::fstream::open_istream(filename, std::ios::in).get(); slx::stringstreambuf strbuf; auto size = istr.read_to_end(strbuf).get(); istr.close(); string content = strbuf.collection(); cout << content.c_str(); return content; } task<std::string> Test1Async2(const string_t& filename) { auto istr = co_await slx::fstream::open_istream(filename, std::ios::in); slx::stringstreambuf strbuf; auto size = co_await istr.read_to_end(strbuf); istr.close(); string content = strbuf.collection(); cout << content.c_str(); return content; } Nota: Al momento co_await funziona solo se viene aggiunto /await alla riga di comando del compilatore
  9. 9. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community File streams – copiare un file file_buffer<> file_stream<> (factory) filestream.h std concurrency::streams namespaces concurrency::streams::details void Test3(const string_t& source, const string_t& target) { auto istr = slx::fstream::open_istream(source, std::ios::in).get(); auto ostr = slx::fstream::open_ostream(target, std::ios::out).get(); slx::producer_consumer_buffer<char> buffer; int size = 110; // dimensione del blocco da copiare while (auto ilen = istr.read(buffer, size).get()) { auto olen = ostr.write(buffer, ilen).get(); } istr.close(); ostr.close(); } co_await co_await co_await co_await Nota: Al momento co_await funziona solo se viene aggiunto /await alla riga di comando del compilatore
  10. 10. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community I building block di rete • Le tre classi principali sono: •http_client: astrazione su tre librerie • boost::asio per il mondo *nix • WinHttp per Windows Desktop • WinRT per il Windows Store •http_listener (beta): astrazione su: • boost::asio per il mondo *nix • Http.sys per il mondo Windows Desktop • WinRT vieta l'uso di listener nelle App (security!) •websocket_client: astrazione su: • Websocket++ per tutti gli OS tranne … • WinRT offre il suo supporto nativo Boost::Asio WinHttp WinRT http_client Boost::Asio Http.Sys http_listener WebsocketPP WinRT websocket_client
  11. 11. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community Features vs Sistema Operativo Windows Desktop Windows Store WP 8 WP 8.1 WP 8.1 Silverlight Windows XP Linux (Ubuntu) Mac OS X iOS Android Programming with Tasks JSON Asynchronous Streams URIs HTTP Client HTTP Listener (Beta) (Beta) (Beta) (Beta) (Beta) WebSocket Client OAuth Client (Beta) (Beta) (Beta, OAuth2 only) (Beta, OAuth2 only) (Beta, OAuth2 only) (Beta, OAuth2 only) (Beta) (Beta) (Beta) (Beta)
  12. 12. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community Leggere/scrivere JSON #include "cpprestjson.h" json::value root2(100); auto root6 = json::value::string(U("hello, world")); vector<pair<string_t, json::value>> props ... auto root2 = json::value::object(props); Creare un intero: Creare una stringa: Creare un oggetto: using namespace web; using namespace utility; using namespace utility::conversions; auto jsonText = U("[ "Book", "Pencil" ]"); auto json = json::value::parse(jsonText); Deserializzazione: void print(const json::value& val) { string_t text = val.serialize(); std::string utf8 = to_utf8string(text); cout << utf8.c_str() << endl; } Serializzazione:
  13. 13. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community tip: deserializzare in un boost::variant 1. 2. definire un tipo "metamorfico" 3. ciclare le proprietà del json::object e deserializzare ogni valore in un "universal" 4. boost::variant è "iostream" friendly typedef boost::variant<bool, double, int, std::string> universal; #include "boostvariantvariant.hpp" if (val.is_string()) { auto stringt = val.as_string(); return universal(string(begin(stringt), end(stringt))); } if (val.is_boolean()) return universal(val.as_bool()); if (val.is_double()) return universal(val.as_double()); ...
  14. 14. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community http_client in action 1. Costruire del client 2. Costruire una request 3. Aggiungere gli header 4. Aggiungere il body (POST) 5. Eseguire la chiamata 6. Controllare http status 7. Leggere il contenuto http_client client(_address); http_request request(methods::POST); request.headers().add( header_names::user_agent, U("IAmRaf agent")); request.set_body(body); auto resp = co_await client.request(request); http_response if (response.status_code() == status_codes::OK) auto json = co_await resp.extract_json();
  15. 15. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community http_listener (beta) 1. Dichiarare uno smart ptr 2. Creare il listener 3. Binding per ogni verb 4. Iniziare la Listen sulla rete unique_ptr<http_listener> _listener; _listener = make_unique<http_listener>(address); _listener->support(methods::GET, std::bind(&Listener::handle_get, this, std::placeholders::_1)); co_await _listener->open(); #include "cppresthttp_listener.h"
  16. 16. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community websocket_client 1. Creare il client 2. Aprire la connessione 3. Creare un messaggio (out) 4. Impostare il contenuto 5. Spedire il messaggio 6. Ricevere la risposta 7. Leggere il body 8. Leggere il body type 9. Leggere il contenuto co_await client->connect(U("ws://server/..."); client = std::make_unique<websocket_client>(); websocket_outgoing_message message; message.set_utf8_message("hello, world"); websocket_incoming_message message = co_await client->receive(); client->send(message); istream body = message.body(); websocket_message_type messageType = message.message_type(); auto text = co_await message.extract_string(); RFC 6455
  17. 17. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community tip: subprotocollo e headers Websockets • Il protocollo Websocket inizia con un handshake HTTP • Segue una notifica « 101 – Upgrade » • E una negoziazione di un "subprotocol" definito a livello applicativo Ecco i passi per poter aggiungere headers e subprotocollo • Create the options • Add the sub-protocol • Add headers websocket_client_config config; config.add_subprotocol(U("subprotocol-raf")); config.headers().add(U("X-Raf"), to_string_t("C++ Native Client")); RFC 6455
  18. 18. Italian C++ Conference 2016 – Un evento dell’Italian C++ Community Domande? Raffaele Rialdi Twitter: @raffaeler Email: raffaeler@vevy.com

×