Google Veri Gadget'ı Oluşturma

Eric Bidelman, Google Veri API'leri Ekibi
Ekim 2008

Giriş

Kitle

Bu makale Blogger gadget'ı oluşturma konusunda size yol gösterecektir. Google Veri API'leri ve JavaScript istemci kitaplığı hakkında bilgi sahibi olduğunuz varsayılır. Ayrıca, JavaScript'i akıcı bir şekilde geliştirmeniz ve gadget'ları* kullanarak OpenSocial gadget'ını uygulama konusunda deneyiminiz olması gerekir.* API bölümünde açıklanmıştır.

Bu örnek, gadget'larınızda harici kitaplıkların başarıyla nasıl kullanılacağını da gösterir. jQuery (esas olarak kullanıcı arayüzü efektleri için) ve mükemmel bir WYSIWYG zengin metin düzenleyici eklentisi olan TinyMCE kullandım.

Motivasyon

Google Veri API'lerinden biriyle JSON kullanan bir gadget oluşturmak için çok az JavaScript gerekir. Bu tür bir gadget'ın en büyük rahatsızlığı, verilerin herkese açık ve salt okunur olmasıdır. Daha ilgi çekici gadget'lar oluşturmak için kullanıcıların gizli verilerine (kimlik doğrulama gerektiren bir şey) erişmeniz gerekir. Şimdiye kadar, Google Hesabı API'lerinden faydalanmak için mükemmel bir yöntem sunulmamıştı. AuthSub, tarayıcı yönlendirmelerini zorunlu kılar ve ClientLogin, kullanıcının kimlik bilgilerini istemci tarafında kullanıma sunar. Bir type="url" gadget'ını korsan hale getirmek bile işe yaramadı.

OAuth Proxy'yi girin.

OAuth Proxy'si

OAuth hakkında bilginiz yoksa, kullanıcının özel verilerini başka bir web sitesi veya gadget'la paylaşmasına olanak tanıyan bir kimlik doğrulama standardıdır. OAuth spesifikasyonu, tüm veri isteklerinin dijital olarak imzalanmasını gerektirir. Bu, güvenlik için idealdir ancak JavaScript gadget'ı söz konusu olduğunda özel anahtarları yönetmek ve dijital imza oluşturmak güvenli değildir. Ayrıca, alan adları arası sorunların karmaşıklığı da ortadan kalkar.

Neyse ki bu sorunlar, gadget platformundan OAuth Proxy adı verilen bir özellikten yararlanılarak çözülür. OAuth Proxy, gadget geliştiricilerinin hayatını kolaylaştırmak için tasarlanmıştır. OAuth kimlik doğrulaması ayrıntılarının çoğunu gizler ve işin zor kısmını sizin yerinize yapar. Proxy, gadget'ınız adına veri isteklerini imzalar. Bu nedenle özel anahtarları yönetmeniz veya istekleri imzalamanız gerekmez. Bu komut çalışacaktır.

OAuth Proxy'si, gadget spesifikasyonunun bir uygulaması olan Shindig adlı açık kaynaklı bir projeyi temel alır.

Not: OAuth Proxy, yalnızca gadgets.* API'sini kullanan ve OpenSocial kapsayıcılarında çalışan gadget'lar için desteklenir. Eski gadget API'si için desteklenmez.

Başlayın

Bu eğitimin geri kalanında, kullanıcıların Blogger verilerine erişmek için bir gadget oluşturmaya odaklanılacaktır. Kimlik doğrulama (OAuth Proxy kullanarak), JavaScript istemci kitaplığını kullanma ve son olarak Blogger'a giriş gönderme işlemlerini gerçekleştiririz.

Kimlik doğrulama

Her şeyden önce, gadget'a OAuth kullanmasını söylememiz gerekir. Bunu yapmak için gadget'ın <ModulePrefs> bölümüne <OAuth> öğesini ekleyin:

<ModulePrefs>
...
<OAuth>
  <Service name="google">
    <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> 
    <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.blogger.com/feeds/" method="GET" /> 
    <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken?
                        oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> 
  </Service>
</OAuth>
...
</ModulePrefs>

<Service> öğesindeki üç URL uç noktası, Google'ın OAuth jeton uç noktalarına karşılık gelir. Sorgu parametreleriyle ilgili açıklama aşağıda verilmiştir:

  • scope

    Bu parametre, İstek URL'sinde gereklidir. Gadget'ınız, yalnızca bu parametrede kullanılan scope öğelerindeki verilere erişebilir. Bu örnekte, gadget Blogger'a erişecektir. Gadget'ınız birden fazla Google Data API'sine erişmek isterse ek scope'leri %20 ile birleştirin. Örneğin, hem Takvim'e hem de Blogger'a erişmek istiyorsanız kapsamı http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/ olarak ayarlayın.

  • oauth_callback

    Bu parametre, Yetkilendirme URL'sinde isteğe bağlıdır. Kullanıcı, verilerine erişimi onayladıktan sonra OAuth onay sayfası bu URL'ye yönlendirilir. Bu parametreyi değiştirmeyi, kendi "onaylanan sayfanız" olarak ayarlamayı veya tercihen http://oauth.gmodules.com/gadgets/oauthcallback kullanmayı seçebilirsiniz. Daha sonra, kullanıcılar gadget'ınızı ilk kez yüklediklerinde en iyi kullanıcı deneyimini sağlar. Bu sayfa, pop-up penceresini otomatik olarak kapatan bir JavaScript snippet'i sağlar.

Artık OAuth kullanan gadget'ımız olduğuna göre, kullanıcının verilerine erişimini onaylaması gerekiyor. Kimlik doğrulama akışı:

  1. Gadget ilk kez yüklenir ve kullanıcının Blogger verilerine erişmeyi dener.
  2. Kullanıcı, gadget'a erişim izni vermediğinden istek başarısız oldu. Neyse ki, yanıtta döndürülen nesne kullanıcıya giriş yapması için ulaşacağımız bir URL (response.oauthApprovalUrl) içeriyor. Bu gadget, "Blogger'da oturum aç"ı gösterir ve gadget'ını oauthApprovalUrl değerine ayarlar.
  3. Ardından, kullanıcı "Blogger'da oturum aç"ı tıklar ve OAuth onay sayfası ayrı bir pencerede açılır. Gadget, kullanıcının onay işlemini tamamlamasını bekler. Bağlantıda "Erişimi onayladım" yazar.
  4. Pop-up'ta, kullanıcı gadget'ımıza erişim izni vermeyi/erişimi reddetmeyi seçecektir. "Erişim izni ver" seçeneğini tıkladıklarında http://oauth.gmodules.com/gadgets/oauthcallback adresine yönlendirilirler ve pencere kapanır.
  5. Gadget, kapatılan pencereyi tanır ve kullanıcının verilerini yeniden isteyerek Blogger'a ikinci kez erişmeyi dener. Pencerenin kapandığını algılamak için bir pop-up işleyici kullandım. Bu tür bir kod kullanmazsanız kullanıcı manuel olarak "Erişimi onayladım" seçeneğini tıklayabilir.
  6. Gadget artık normal kullanıcı arayüzünü gösterir. Kimlik doğrulama jetonu IssuedAuthSubTokens altında iptal edilmediği sürece bu görünüm geçerli kalır.

Yukarıdaki adımları uygulayarak, gadget'lar için üç farklı durum kavramı var:

  1. Kimlik doğrulanmadı. Kullanıcının onay sürecini başlatması gerekir.
  2. Kullanıcının verilerine erişimini onaylaması bekleniyor.
  3. Kimlik doğrulandı. Gadget'lar normal şekilde çalışır durumda olur.

Gadget'ımda, her bir aşamayı ayırmak için <div> kapsayıcısı kullandım:

<Content type="html">
<![CDATA[

<!-- Normal state of the gadget. The user is authenticated -->       
<div id="main" style="display:none">
  <form id="postForm" name="postForm" onsubmit="savePost(this); return false;">
     <div id="messages" style="display: none"></div>
     <div class="selectFeed">Publish to:
       <select id="postFeedUri" name="postFeedUri" disabled="disabled"><option>loading blog list...</option></select>
     </div>
     <h4 style="clear:both">Title</h4>
     <input type="text" id="title" name="title"/>
     <h4>Content</h4>
     <textarea id="content" name="content" style="width:100%;height:200px;"></textarea>
     <h4 style="float:left;">Labels (comma separated)</h4><img src="blogger.png" style="float:right"/>
     <input type="text" id="categories" name="categories"/>
     <p><input type="submit" id="submitButton" value="Save"/> 
     <input type="checkbox" id="draft" name="draft" checked="checked"/> <label for="draft">Draft?</label></p>
  </form>
</div>

<div id="approval" style="display: none">
  <a href="#" id="personalize">Sign in to Blogger</a>
</div>

<div id="waiting" style="display: none">
  <a href="#" id="approvalLink">I've approved access</a>
</di

<!-- An errors section is not necessary but great to have -->
<div id="errors" style="display: none"></div>
 
<!-- Also not necessary, but great for informing users -->     
<div id="loading">
  <h3>Loading...</h3>
  <p><img src="ajax-loader.gif"></p>
</div>

]]> 
</Content>

Her <div>, showOnly() kullanılarak tek başına görüntülenir. Söz konusu işlevle ilgili ayrıntılar için tam örnek gadget'ına bakın.

JavaScript istemci kitaplığını kullanma

OpenSocial'da uzak içerik getirmek için gadgets.* API'sini kullanarak gadgets.io.makeRequest yöntemini çağırırsınız. Bununla birlikte, bir Google Veri gadget'ı geliştirdiğimizden gadgets.io.* API'lerine dokunmamıza gerek yoktur. Bunun yerine, her bir Google Veri hizmetine istek göndermek için özel yöntemler içeren JavaScript istemci kitaplığından yararlanın.

Not: Bu makale hazırlanırken JavaScript kitaplığı yalnızca Blogger, Takvim, Kişiler, Finans ve Google Base'i desteklemektedir. Diğer API'lerden birini kullanmak için kitaplık olmadan gadgets.io.makeRequest kullanın.

Kitaplık yükleniyor

JavaScript kitaplığını yüklemek için <Content> bölümüne ortak yükleyiciyi ekleyin ve gadget başlatıldıktan sonra kitaplığı içe aktarın. gadgets.util.registerOnLoadHandler() işlevini geri çağırmayı beslemek, gadget'ın ne zaman hazır olduğunu belirlemeye yardımcı olur:

<Content type="html">
<![CDATA[
  ...
  <script src="https://www.google.com/jsapi"></script>
  <script type="text/javascript">
  var blogger = null;  // make our service object global for later
  
  // Load the JS library and try to fetch data once it's ready
  function initGadget() {  
    google.load('gdata', '1.x', {packages: ['blogger']});  // Save overhead, only load the Blogger service
    google.setOnLoadCallback(function () {
      blogger = new google.gdata.blogger.BloggerService('google-BloggerGadget-v1.0');
      blogger.useOAuth('google');
      fetchData();
    });
  }
  gadgets.util.registerOnLoadHandler(initGadget);
  </script>
  ...
]]> 
</Content>

blogger.useOAuth('google') çağrısı, kitaplığa (normal kimlik doğrulama yöntemi olan AuthSubJS yerine) OAuth Proxy'yi kullanmasını söyler. Son olarak gadget, fetchData() numarasını arayarak kullanıcının Blogger verilerini almayı dener. Bu yöntem aşağıda tanımlanmıştır.

Veriler alınıyor

Tüm ayarları yaptığımıza göre verileri Blogger'a nasıl gönderebiliriz? GET veya POST

OpenSocial'da yaygın olarak kullanılan bir paradigma, gadget'ınızda fetchData() adında bir işlev tanımlamaktır. Bu yöntem genellikle kimlik doğrulamanın farklı aşamalarını yönetir ve verileri gadgets.io.makeRequest kullanarak getirir. JavaScript istemci kitaplığını kullandığımız için gadgets.io.makeRequest, blogger.getBlogFeed() yerine bir çağrıyla değiştirilecek:

function fetchData() {
  jQuery('#errors').hide();
  
  var callback = function(response) {
    if (response.oauthApprovalUrl) {
      // You can set the sign in link directly:
      // jQuery('#personalize').get(0).href = response.oauthApprovalUrl
      
      // OR use the popup.js handler
      var popup = shindig.oauth.popup({
        destination: response.oauthApprovalUrl,
        windowOptions: 'height=600,width=800',
        onOpen: function() {
          showOnly('waiting');
        },
        onClose: function() {
          showOnly('loading');
          fetchData();
        }
      });
      jQuery('#personalize').get(0).onclick = popup.createOpenerOnClick();
      jQuery('#approvalLink').get(0).onclick = popup.createApprovedOnClick();
      
      showOnly('approval');
    } else if (response.feed) {
      showResults(response);
      showOnly('main');
    } else {
      jQuery('#errors').html('Something went wrong').fadeIn();
      showOnly('errors');
    }
  };
  
  blogger.getBlogFeed('http://www.blogger.com/feeds/default/blogs', callback, callback);
}

Bu işlev ikinci kez çağrıldığında, response.feed veri içerir.

Not: getBlogFeed(), geri çağırma ve hata işleyici için aynı işlevi kullanır.

Blogger'da bir giriş yayınlayın

Son adım, bir Blog'da yeni bir giriş yayınlamaktır. Aşağıdaki kod, kullanıcı "Kaydet" düğmesini tıkladığında ne olacağını göstermektedir.

function savePost(form) { 
  jQuery('#messages').fadeOut();
  jQuery('#submitButton').val('Publishing...').attr('disabled', 'disabled');
  
  // trim whitespace from the input tags
  var input = form.categories.value;
  var categories = jQuery.trim(input) != '' ? input.split(',') : [];   
  jQuery.each(categories, function(i, value) {
    var label = jQuery.trim(value);
    categories[i] = {
      scheme: 'http://www.blogger.com/atom/ns#',
      term: label
    };
  });

  // construct the blog post entry
  var newEntry = new google.gdata.blogger.BlogPostEntry({
    title: {
      type: 'text', 
      text: form.title.value
    },
    content: {
      type: 'text', 
      text: form.content.value
    },
    categories: categories
  });
  
  // publish as draft?
  var isDraft = form.draft.checked;
  if (isDraft) {
    newEntry.setControl({draft: {value: google.gdata.Draft.VALUE_YES}});
  }
  
  // callback for insertEntry()
  var handleInsert = function(entryRoot) {
    var entry = entryRoot.entry;
    var str = isDraft ? '(as draft)' : '<a href="' + entry.getHtmlLink().getHref() + '" target="_blankt">View it</a>';

    jQuery('#messages').html('Post published! ' + str).fadeIn();
    jQuery('#submitButton').val('Save').removeAttr('disabled');
  };
  
  // error handler for insertEntry()
  var handleError = function(e) {
    var msg = e.cause ? e.cause.statusText + ': ' : '';
    msg += e.message;
    alert('Error: ' + msg);
  };
  
  blogger.insertEntry(form.postFeedUri.value, newEntry, handleInsert, handleError);
}

Sonuç

Artık bir gadget'ı Google Veri API'larına ek olarak kodlamaya başlamak için gerekli yapı taşlarına sahipsiniz.

Bu makalenin OAuth Proxy'nin gadget kimlik doğrulamasını ne kadar basit hale getirdiğini takdir ettiğini umuyoruz. Bu güç aracını Google Veri JavaScript istemci kitaplığıyla birleştirmek, ilginç, etkileşimli ve gelişmiş gadget'lar oluşturmanızı kolaylaştırır.

Bu makale hakkında sorularınız veya yorumlarınız varsa lütfen Google Hesapları API'sı tartışma forumunda bizi ziyaret edin.

Kaynaklar