Oktober 2008
Pengantar
Audiens
Artikel ini akan memandu Anda membuat gadget Blogger. Panduan ini mengasumsikan bahwa Anda sudah memahami Google Data API dan library klien JavaScript. Anda juga harus fasih dalam JavaScript dan memiliki pengalaman dalam menerapkan gadget OpenSocial menggunakan gadgets.* API.
Contoh ini juga menunjukkan cara berhasil menggunakan library eksternal di gadget Anda. Saya telah menggunakan jQuery (terutama untuk efek UI-nya) dan TinyMCE, plugin editor teks kaya WYSIWYG yang hebat.
Motivasi
Hanya diperlukan sedikit JavaScript untuk membuat gadget yang menggunakan JSON dengan salah satu Google Data API. Masalah utama gadget semacam itu adalah data
bersifat publik dan hanya baca. Untuk membuat gadget yang lebih menarik, Anda memerlukan akses ke data pribadi pengguna (sesuatu yang memerlukan autentikasi). Hingga saat ini, belum ada cara yang efektif untuk memanfaatkan Google Account API. AuthSub memerlukan pengalihan browser dan ClientLogin mengekspos kredensial pengguna di sisi klien. Bahkan meretas gadget type="url"
pun tidak nyaman.
Masukkan OAuth Proxy.
Proxy OAuth
Jika Anda belum memahami OAuth, OAuth adalah standar autentikasi yang memungkinkan pengguna membagikan data pribadi mereka ke situs atau gadget lain. Spesifikasi OAuth mewajibkan semua permintaan data ditandatangani secara digital. Hal ini sangat bagus untuk keamanan, tetapi dalam kasus gadget JavaScript, mengelola kunci pribadi dan membuat tanda tangan digital tidak aman. Ada juga komplikasi tambahan terkait masalah lintas-domain.
Untungnya, masalah ini dapat diatasi dengan memanfaatkan fitur dari platform gadget yang disebut OAuth Proxy. OAuth Proxy dirancang untuk mempermudah pekerjaan developer gadget. Library ini menyembunyikan sebagian besar detail otentikasi OAuth dan melakukan tugas berat untuk Anda. Proxy menandatangani permintaan data atas nama gadget Anda, sehingga Anda tidak perlu mengelola kunci pribadi atau khawatir tentang penandatanganan permintaan. Berfungsi dengan baik.
OAuth Proxy didasarkan pada project open source bernama Shindig, yang merupakan implementasi spesifikasi gadget.
Catatan: OAuth Proxy hanya didukung untuk gadget yang menggunakan gadgets.*
API dan berjalan di penampung OpenSocial.
Layanan ini tidak didukung untuk API gadget lama.
Memulai
Bagian selanjutnya dari tutorial ini akan berfokus pada pembuatan gadget untuk mengakses data Blogger pengguna. Kita akan membahas autentikasi (menggunakan OAuth Proxy), penggunaan library klien JavaScript, dan terakhir, memposting entri ke Blogger.
Autentikasi
Pertama-tama, kita perlu memberi tahu gadget untuk menggunakan OAuth. Untuk melakukannya, tambahkan elemen <OAuth>
di bagian <ModulePrefs>
gadget:
<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>
Tiga endpoint URL dalam elemen <Service>
sesuai dengan endpoint token OAuth Google. Berikut penjelasan parameter kueri:
scope
Parameter ini wajib ada di URL Permintaan. Gadget Anda hanya dapat mengakses data dari
scope
yang digunakan dalam parameter ini. Dalam contoh ini, gadget akan mengakses Blogger. Jika gadget Anda ingin mengakses lebih dari satu Google Data API, gabungkanscope
tambahan dengan%20
. Sebagai contoh, jika Anda ingin mengakses Kalender dan Blogger, tetapkan cakupan kehttp://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/
.oauth_callback
Parameter ini bersifat opsional di URL Otorisasi. Halaman persetujuan OAuth akan dialihkan ke URL ini setelah pengguna menyetujui akses ke datanya. Anda dapat memilih untuk tidak menggunakan parameter ini, menyetelnya ke "halaman yang disetujui" milik Anda, atau lebih baik lagi, menggunakan
http://oauth.gmodules.com/gadgets/oauthcallback
. Yang terakhir memberikan pengalaman pengguna terbaik saat pengguna pertama kali menginstal gadget Anda. Halaman tersebut menyediakan cuplikan JavaScript yang otomatis menutup jendela pop-up.
Setelah gadget kita menggunakan OAuth, pengguna harus menyetujui akses ke datanya. Berikut alur autentikasinya:
- Gadget dimuat untuk pertama kalinya dan mencoba mengakses data Blogger pengguna.
- Permintaan gagal karena pengguna belum memberikan akses ke gadget. Untungnya, objek yang ditampilkan dalam respons
berisi URL (
response.oauthApprovalUrl
) tempat kita akan mengarahkan pengguna untuk login. Gadget menampilkan "Login ke Blogger" dan menetapkan href-nya ke nilaioauthApprovalUrl
. - Selanjutnya, pengguna mengklik "Login ke Blogger" dan halaman persetujuan OAuth akan terbuka di jendela terpisah. Gadget menunggu pengguna menyelesaikan proses persetujuan dengan menampilkan link: "Saya telah menyetujui akses".
- Di jendela pop-up, pengguna akan memilih untuk memberikan/menolak akses ke gadget kita. Setelah mengklik "Beri akses", pengguna akan diarahkan ke
http://oauth.gmodules.com/gadgets/oauthcallback
dan jendela akan ditutup. - Gadget mengenali jendela yang ditutup dan mencoba mengakses Blogger untuk kedua kalinya dengan meminta ulang data pengguna. Untuk mendeteksi penutupan jendela, saya telah menggunakan handler pop-up. Jika Anda tidak menggunakan kode tersebut, pengguna dapat mengklik "Saya telah menyetujui akses" secara manual.
- Gadget kini menampilkan UI normalnya. Tampilan ini akan tetap ada kecuali jika token autentikasi dicabut di IssuedAuthSubTokens.
Jadi, dari langkah-langkah di atas, gadget memiliki tiga status yang berbeda:
- Tidak diautentikasi. Pengguna harus memulai proses persetujuan.
- Menunggu pengguna menyetujui akses ke datanya.
- Diautentikasi. Gadget menampilkan status fungsional normalnya.
Di gadget saya, saya telah menggunakan <div>
penampung untuk memisahkan setiap tahap:
<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>
Setiap <div>
ditampilkan sendiri menggunakan showOnly()
. Lihat gadget contoh lengkap untuk mengetahui detail fungsi tersebut.
Menggunakan library klien JavaScript
Untuk mengambil konten jarak jauh di OpenSocial, Anda melakukan panggilan ke metode gadgets.io.makeRequest
menggunakan gadgets.*
API.
Namun, karena kita membuat gadget Google Data, tidak perlu menyentuh API gadgets.io.*
. Sebagai gantinya, manfaatkan library klien JavaScript yang memiliki metode khusus untuk membuat permintaan ke setiap layanan Data Google.
Catatan: Pada saat penulisan artikel ini, pustaka JavaScript hanya mendukung Blogger, Kalender,
Kontak,
Finance, dan Google Base. Untuk menggunakan salah satu API
lainnya, gunakan gadgets.io.makeRequest
tanpa library.
Memuat library
Untuk memuat library JavaScript, sertakan loader umum di bagian <Content>
dan impor library
setelah gadget diinisialisasi. Memberikan callback ke gadgets.util.registerOnLoadHandler()
akan
membantu menentukan kapan gadget siap:
<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>
Panggilan ke blogger.useOAuth('google')
memberi tahu library untuk menggunakan Proxy OAuth (bukan AuthSubJS - metode autentikasi normalnya).
Terakhir, gadget mencoba mengambil data Blogger pengguna dengan memanggil fetchData()
. Metode tersebut dijelaskan di bawah.
Mengambil data
Setelah semuanya disiapkan, bagaimana cara kita benar-benar GET
atau POST
data ke Blogger?
Paradigma umum di OpenSocial adalah menentukan fungsi yang disebut fetchData()
di gadget Anda. Metode ini biasanya menangani berbagai tahap autentikasi dan mengambil data menggunakan gadgets.io.makeRequest
. Karena kita menggunakan library klien JavaScript, gadgets.io.makeRequest
digantikan oleh panggilan ke blogger.getBlogFeed()
:
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); }
Saat fungsi ini dipanggil untuk kedua kalinya, response.feed
berisi data.
Catatan: getBlogFeed()
menggunakan fungsi yang sama untuk callback dan pengendali errornya.
Memposting entri ke Blogger
Langkah terakhir adalah memposting entri baru ke Blog. Kode di bawah menunjukkan apa yang terjadi saat pengguna mengklik tombol "Simpan".
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); }
Kesimpulan
Sekarang Anda memiliki elemen dasar untuk mulai membuat kode gadget di atas Google Data API.
Semoga artikel ini membuat Anda mengapresiasi betapa sederhananya autentikasi gadget dengan OAuth Proxy. Dengan menggabungkan alat canggih ini dengan library klien JavaScript Data Google, Anda dapat dengan mudah membuat gadget yang menarik, interaktif, dan canggih.
Jika ada pertanyaan atau komentar tentang artikel ini, kunjungi kami di forum diskusi Google Account API.
Resource
- Menulis Gadget OAuth (dokumentasi gadget lengkap)
- Menggunakan OAuth dengan Google Data API (artikel tentang penggunaan OAuth dengan Google Data API)
- Autentikasi OAuth untuk Aplikasi Web (dokumentasi OAuth lengkap)
- Library klien JavaScript
- Forum diskusi Google Accounts API