APIs e Microsserviços

23 nov, 2012

Primeiros passos com Spring Social: um “behind the scenes” do Facebook e do Twitter

Publicidade

Em meu último artigo, criei um aplicativo do Twitter simples que usa o módulo Spring Social Twitter para acessar dados da timelime de um usuário público. Como eu disse naquele artigo, o exemplo não é particularmente complicado e irei acrescentar recursos extras depois. Antes de fazer isso, eu queria explicar um pouco mais sobre um provedor de software como serviço (SaaS), como Facebook e Twitter, e mostrar algo do que a API Spring Social está fazendo para você.

E a boa notícia é que não há nada de mágico sobre serviços de SaaS, eles são apenas um grupo de servidores web que responde a determinadas solicitações HTTP/HTTPS tanto com JSON como com XML em vez de HTML, com o formato das solicitações publicado pelos fornecedores de SaaS em seus web sites.

Por exemplo, o Twitter publica o que chama de REST API RESOURCES, que você pode encontrar no seguinte endereço: https://dev.twitter.com/docs/api.

O código de exemplo para recuperar uma timeline do usuário que eu forneci no meu último artigo continha as seguintes linhas:

private List<Tweet> queryForTweets(String screenName) {

TimelineOperations timelineOps = twitter.timelineOperations();
List<Tweet> results = timelineOps.getUserTimeline(screenName);
logger.info("Fond Twitter timeline for :" + screenName + " adding " + results.size()
+ " tweets to model");
return results;
}

… o que, eu suspeito, sem olhar para o código, está enviando a solicitação:

https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=roghughe

… e, depois de ler a resposta, será algo como isto:

[{"created_at":"Fri Jun 15 19:58:49 +0000 2012","id":213722250153697280,"id_str":"213722250153697280","text":"RT @joshbloch: Incredibly depressing (to me) article on the state and future of Apple hardware http:\/\/t.co\/Mwv7MZFz . If I can't hack it ...","source":"\u003ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003eEchofon\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":117413536,"id_str":"117413536","name":"Roger Hughes","screen_name":"roghughe","location":"UK","description":"","url":"http:\/\/www.captaindebug.com","protected":false,"followers_count":11,"friends_count":18,"listed_count":0,"created_at":"Thu Feb 25 13:51:47 +0000 2010","favourites_count":87,"utc_offset":0,"time_zone":"London","geo_enabled":false,"verified":false,"statuses_count":19,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"B2DFDA","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme13\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme13\/bg.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/729683837\/Head1_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/729683837\/Head1_normal.jpg","profile_link_color":"93A644","profile_sidebar_border_color":"EEEEEE","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Jun 15 19:19:51 +0000 2012","id":213712443388600320,"id_str":"213712443388600320","text":"Incredibly depressing (to me) article on the state and future of Apple hardware http:\/\/t.co\/Mwv7MZFz . If I can't hack it, I don't want it.","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":61135090,"id_str":"61135090","name":"Joshua Bloch","screen_name":"joshbloch","location":"Silicon Valley","description":"Effective Java author, API Designer, Swell guy","url":null,"protected":false,"followers_count":15836,"friends_count":94,"listed_count":942,"created_at":"Wed Jul 29 06:50:55 +0000 2009","favourites_count":3,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":1017,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"BADFCD","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme12\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme12\/bg.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1778383824\/joshbloch.original-1326394501_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1778383824\/joshbloch.original-1326394501_normal.jpg","profile_link_color":"FF0000","profile_sidebar_border_color":"F2E195","profile_sidebar_fill_color":"FFF7CC","profile_text_color":"0C3E53","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":66,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/Mwv7MZFz","expanded_url":"http:\/\/goo.gl\/jmkfM","display_url":"goo.gl\/jmkfM","indices":[80,100]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},"retweet_count":66,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/Mwv7MZFz","expanded_url":"http:\/\/goo.gl\/jmkfM","display_url":"goo.gl\/jmkfM","indices":[95,115]}],"user_mentions":[{"screen_name":"joshbloch","name":"Joshua Bloch","id":61135090,"id_str":"61135090","indices":[3,13]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Jun 15 17:54:37 +0000 2012","id":213690991708880897,"id_str":"213690991708880897","text":"RT @bobbyllew: RT @jeffjarvis: In solidarity, every schoolkid everywhere should start tweeting pix of their meals:  http:\/\/t.co\/NWeROWBo","source":"\u003ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003eEchofon\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":117413536,"id_str":"117413536","name":"Roger Hughes","screen_name":"roghughe","location":"UK","description":"","url":"http:\/\/www.captaindebug.com","protected":false,"followers_count":11,"friends_count":18,"listed_count":0,"created_at":"Thu Feb 25 13:51:47 +0000 2010","favourites_count":87,"utc_offset":0,"time_zone":"London","geo_enabled":false,"verified":false,"statuses_count":19,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"B2DFDA","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme13\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme13\/bg.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/729683837\/Head1_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/729683837\/Head1_normal.jpg","profile_link_color":"93A644","profile_sidebar_border_color":"EEEEEE","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Jun 15 12:37:47 +0000 2012","id":213611259055181826,"id_str":"213611259055181826","text":"RT @jeffjarvis: In solidarity, every schoolkid everywhere should start tweeting pix of their meals:  http:\/\/t.co\/NWeROWBo","source":"\u003ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003eTweetDeck\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1077971,"id_str":"1077971","name":"Robert Llewellyn","screen_name":"bobbyllew","location":"London","description":"Conflicted wet liberal, amateur nerd, every few years Kryten in Red Dwarf. Electric vehicle fan and Stone Cold Fox (apparently)","url":"http:\/\/www.llewtube.com","protected":false,"followers_count":85654,"friends_count":668,"listed_count":3418,"created_at":"Tue Mar 13 09:20:36 +0000 2007","favourites_count":20,"utc_offset":0,"time_zone":"London","geo_enabled":false,"verified":true,"statuses_count":37079,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"253132","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/366726010\/NFGsmall.jpg","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/366726010\/NFGsmall.jpg","profile_background_tile":true,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1183945291\/twitterpic2_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1183945291\/twitterpic2_normal.jpg","profile_link_color":"4242DA","profile_sidebar_border_color":"87BC44","profile_sidebar_fill_color":"A3DF0D","profile_text_color":"000000","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":27,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/NWeROWBo","expanded_url":"http:\/\/bit.ly\/LrgTtP","display_url":"bit.ly\/LrgTtP","indices":[101,121]}],"user_mentions":[{"screen_name":"jeffjarvis","name":"Jeff Jarvis","id":11435642,"id_str":"11435642","indices":[3,14]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},"retweet_count":27,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/NWeROWBo","expanded_url":"http:\/\/bit.ly\/LrgTtP","display_url":"bit.ly\/LrgTtP","indices":[116,136]}],"user_mentions":[{"screen_name":"bobbyllew","name":"Robert Llewellyn","id":1077971,"id_str":"1077971","indices":[3,13]},{"screen_name":"jeffjarvis","name":"Jeff Jarvis","id":11435642,"id_str":"11435642","indices":[18,29]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false}]

… que eu trunquei para economizar espaço. Uma vez que o módulo Twitter possui os dados acima, ele vai analisá-lo em uma lista de Tweet beans usando o processador Java Jackson JSON e algumas outras classes. Essa lista de Tweet beans é o que seu aplicativo recebe como valor de retorno à sua chamada.

Da mesma forma, o Facebook possui uma API que eles chamam de Graph API, um bom nome, pois permite que o caller acesse o social graph do usuário. Detalhes da Graph API estão disponíveis aqui – embora seja necessário se logar para poder vê-la: https://developers.facebook.com/docs/reference/api/.

Se você já viu a amostra do Spring Social QuickStart, você vai saber que ele demonstra como se apossar de uma lista dos seus amigos do Facebook usando o seguinte código:

@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
List<Reference> friends = facebook.friendOperations().getFriends();
model.addAttribute("friends", friends);
return "home";
}

E, como o código do Twitter acima, eu aposto que o código do Keith Donald mapeia para uma solicitação da API do Facebook que é algo mais ou menos assim:

https://graph.facebook.com/me/friends?access_token=AAAAAAITEghMWiBBlEC5OGXjotoIjzn7r3KinZAWIbbleoHX1rYFlMMr9cvUmAEYEtQ1ZCHPFSbop2gXQ1ibbleeIWAbrZChwfrcywlYGTWIBBLeAVbjNnWjIlE

… o resultado que é igualmente analisado e retornado para o seu aplicativo como uma lista de POJOs.

No entanto, repare o símbolo de acesso, dê o seu nome completo, o token de acesso OAuth. Isso é conhecido apenas por seu aplicativo e pelo Facebook, e é usado para conceder o seu acesso do seu aplicativo aos dados privados de seus usuários. É este o X da questão doOAuth: o seu aplicativo obtendo de um token de acesso para que ele possa acessar o Facebook do seu usuário, o LinkedIn, o Sina Weibo ou outros dados privados de SaaS.

Então, como é que o seu app se apossa de um token de acesso? Acontece que existem alguns obstáculos que temos que ultrapassar, mas falaremos mais sobre isso na próxima vez…

***

Texto original disponível em http://www.captaindebug.com/2012/06/facebook-and-twitter-behind-scenes.html