CORS ( Cross-Origin Resource Sharing ) : connecting multiple site with multiple request method
CORS adalah draft teknologi yang dikembangkan oleh W3C sebagai alternatif yang lebih modern ketimbang JSONP. Ketika JSONP hanya men-support GET request method, CORS juga mensupport POST request method. Teknologi ini dikembangkan karena semakin kompleksnya kebutuhan mashup data di dunia internet. Ide dasar dari CORS ini adalah meng-custom HTTP Header agar client dan server dapat mengetahui satu sama lain apabila request dan response berhasil atau gagal dilakukan.
Kali ini, saya akan mencoba memaparkan tentang contoh implementasi CORS menggunakan jQuery javascript library, dan plugin CORS. Plugin asli dapat didownload di sini , yang akan saya sampaikan di sini sudah saya modifikasi dari aslinya untuk kebutuhan jQuery versi 1.5.
Pertama, kita siapkan dulu jQuery library kita, bisa didownload di sini. Setelah itu, kita buat plugin untuk handle CORS sebagai berikut :
(function($) { //activate cors support <-- for jQuery 1.5 jQuery.support.cors = true; $.corsGET = function(url,callback){ try{ jQuery.get(url, callback); }catch(e){ // jQuery get() failed, try IE8 CORS, or use the proxy if (jQuery.browser.msie && window.XDomainRequest) { // Use Microsoft XDR var xdr = new XDomainRequest(); xdr.open("get", url); xdr.onload = function() { callback(this.responseText, 'success'); }; xdr.send(); } else{ try { // Ancient browser, use our proxy var ancientcallback = function() { var textstatus = 'error'; var data = 'error'; if ((this.readyState == 4) && (this.status == '200')) { textstatus = 'success'; data = this.responseText; } callback(data, textstatus); }; // proxy_xmlhttp is a separate script you'll have to set up request = new proxy_xmlhttp(); request.open('GET', url, true); request.onreadystatechange = ancientcallback; request.send(); } catch(e) { // Could not fetch using the proxy alert('failed !!! '); } } } }; $.corsPOST = function(url,data,callback){ try{ jQuery.post(url, data, callback); }catch(e){ // jQuery post() failed, try IE8 CORS, or use the proxy if (jQuery.browser.msie && window.XDomainRequest) { // Use XDR var xdr = new XDomainRequest(); xdr.open("post", url); xdr.send(params); xdr.onload = function() { callback(xdr.responseText, 'success'); }; } else{ try { // Use the proxy to post the data. request = new proxy_xmlhttp(); request.open("POST", url, true); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); request.send(params); } catch(e2) { // could not post using the proxy alert('failed !!! '); } } } }; })(jQuery);
Kita bisa simpan plugin ini dan kita beri nama : jquery.cors.js . Ok, setelah itu kita buat contoh file sebagai requester cross domain kita, contoh sebagai berikut :
<!DOCTYPE html> <html> <head> <title> Test CORS ( Cross-Origin Resource Sharing ) </title> <script type="text/javascript" src="jquery-1.5.2.min.js"></script> <script type="text/javascript" src="jquery.cors.js"></script> <script type="text/javascript"> $(document).ready(function(){ $("#sendDataBtn").click(function(){ //clear label ... $("#resultcors").html(); if ($("#typeofparameter").val()=='get'){ $.corsGET('http://service.yourdomain.com?nama='+$("input[name=nama]").val()+'&'+(new Date()).getTime() , function(data){ $("#resultcors").html('The response is : '+data); }); }else{ $.corsPOST('http://service.yourdomain.com?'+(new Date()).getTime() , { nama: $("input[name=nama]").val() }, function(data){ $("#resultcors").html('The response is : '+data); }); } }); }); </script> </head> <body> <input type="text" name="nama" size="50" /> <br /> type : <select name="typeofparameter" id="typeofparameter"> <option value="get">GET</option> <option value="post">POST</option> </select> <input type="button" id="sendDataBtn" value="Send Data" /> <br /> <label id="resultcors"></label> </body> </html>
Kalau sudah, kita buat deh file responder-nya ( kita buat di server lain atau atas nama domain lain).
<?php // Specify domains from which requests are allowed header('Access-Control-Allow-Origin: *'); // Specify which request methods are allowed header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); // Additional headers which may be sent along with the CORS request // The X-Requested-With header allows jQuery requests to go through header('Access-Control-Allow-Headers: X-Requested-With'); // Set the age to 1 day ( 86400 ) to improve speed/caching. header('Access-Control-Max-Age: 86400'); // Exit early so the page isn't fully loaded for options requests if (strtolower($_SERVER['REQUEST_METHOD']) == 'options') { exit(); } // If raw post data, this could be from IE8 XDomainRequest // Only use this if you want to populate $_POST in all instances if (isset($HTTP_RAW_POST_DATA)) { $data = explode('&', $HTTP_RAW_POST_DATA); foreach ($data as $val) { if (!empty($val)) { list($key, $value) = explode('=', $val); $_POST[$key] = urldecode($value); } } } if ($_SERVER['REQUEST_METHOD'] == 'POST') { echo '<strong>posted</strong> : '.strtoupper( $_REQUEST['nama'] ); } if ($_SERVER['REQUEST_METHOD'] == 'GET') { echo '<strong>getted </strong> : '.strtoupper( $_GET['nama'] ); }
Taraaaa….Sehingga jika ditest, akan tampil sebagai berikut :
Gambar :
http://t2.gstatic.com/images?q=tbn:ANd9GcSbW9iPimNholkyrzJ2tvD-uqRQ8_5KkBC4hVLys9XEVh4KTN81
Referensi :
http://plugins.jquery.com/project/cors
http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing
http://en.wikipedia.org/wiki/JSONP
http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
http://enable-cors.org/
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
https://developer.mozilla.org/en/http_access_control
http://blueonionsoftware.com/blog.aspx?p=03aff202-4198-4606-b9d6-686fd13697ee
http://msdn.microsoft.com/en-us/library/cc288060%28v=vs.85%29.aspx
Zend Framework : Output Escaping – preventing XSS
Cross-site scripting (XSS) merupakan salah satu jenis serangan injeksi kode yang secara umum ditemukan di aplikasi berbasis web melalui client-side script. Salah satu cara menanganinya adalah dengan cara meng-escape output yang tampil pada halaman web. Pada Symfony Framework, output escaping otomatis dilakukan oleh framework itu sendiri, untuk Zend Framework , preventing XSS adalah tugas programmer :). XSS terjadi di bagian View, maka dari itu, Zend Framework menyediakan component Zend_View ( “view” portion of the ZF model-view-controller pattern) yang bisa digunakan untuk meng-escape output dari misalnya :
<script type="text/javascript">alert('hello');</script>
menjadi :
<script type="text/javascript">alert('hello');</script>
Sehingga kode javascript tidak tereksekusi. Nah, ada 2 cara penggunaan metode ini :
1. Encoding before echoing
Di layer View, tinggal kita panggil :
<?php echo $this->escape("<script type=\"text/javascript\">alert('hello');</script>"); ?>
2. Encoding when assigning template variables
Cara yang kedua ini, kita escape dulu di controller, contoh sebagai berikut :
$this->view->title = $this->view->escape("<script type=\"text/javascript\">alert('hello');</script>");
Baru di layer view :
echo $this->title;
Referensi :
http://www.scribd.com/doc/18171526/Secure-Programming-with-the-Zend-Framework
http://www.minte9.com/kb/zend-view-helper-programming-zend-framework-i329
http://devzone.zend.com/article/3412
http://en.wikipedia.org/wiki/Client-side_script
http://en.wikipedia.org/wiki/Cross-site_scripting
http://id.wikipedia.org/wiki/XSS
http://stackoverflow.com/questions/507593/what-is-the-best-way-to-escape-user-output-with-the-zend-framework
Zend Framework : Zend_Log – Working with Logs
Sebegitu pentingnya sebuah sejarah, sampai-sampai beberapa framework menambahkan fitur log, termasuk Zend Framework. Dengan adanya application log, kita bisa mengetahui apa saja yang telah terjadi yang bersinggungan dengan aplikasi kita. Log yang ada, salah satunya, bisa kita simpan di dalam file.
Kali ini, saya akan mencoba memaparkan penggunaan Zend_Log dengan media penyimpanan file dengan teknik Stream.
Pertama, yang kita butuhkan adalah file yang kita tunjuk sebagai media penyimpanan log, anggaplah kita simpan dalam PROJECTKITA\log\application.log, seperti berikut :
Kalau sudah, kita atur deh ErrorController kita sebagai berikut :
<?php class ErrorController extends Zend_Controller_Action { public function errorAction() { $errors = $this->_getParam('error_handler'); switch ($errors->type) { case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: // 404 error -- controller or action not found $this->getResponse()->setHttpResponseCode(404); $this->view->message = 'Page not found'; break; default: // application error $this->getResponse()->setHttpResponseCode(500); $this->view->message = 'Application error'; break; } // Log exception, if logger available if ($log = $this->getLog()) { $log->crit($this->view->message . " : ". $errors->exception); } // conditionally display exceptions if ($this->getInvokeArg('displayExceptions') == true) { $this->view->exception = $errors->exception; } $this->view->request = $errors->request; } public function getLog() { $bootstrap = $this->getInvokeArg('bootstrap'); if (!$bootstrap->hasPluginResource('Log')) { return false; } $log = $bootstrap->getResource('Log'); return $log; } }
Selanjutnya, kita setting di application.ini kita, tambahkan kode berikut :
;call Zend_Log_Writer_Stream resources.log.stream.writerName = "Stream" resources.log.stream.writerParams.stream = APPLICATION_PATH "/../log/application.log"
Dari kode yang telah kita buat di atas, semua critical error akan dicatat dalam file application.log seperti berikut :
2011-04-16T20:54:33+07:00 CRIT (2): Page not found : exception 'Zend_Controller_Action_Exception' with message 'Action "aa" does not exist and was not trapped in __call()' in D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Action.php:485 Stack trace: #0 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Action.php(515): Zend_Controller_Action->__call('aaAction', Array) #1 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Dispatcher\Standard.php(295): Zend_Controller_Action->dispatch('aaAction') #2 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Controller\Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #3 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Application\Bootstrap\Bootstrap.php(97): Zend_Controller_Front->dispatch() #4 D:\Zend\Apache2\htdocs\zftutwordpress\library\Zend\Application.php(366): Zend_Application_Bootstrap_Bootstrap->run() #5 D:\Zend\Apache2\htdocs\zftutwordpress\public\index.php(27): Zend_Application->run() #6 {main}
Nah, bagaimana ketika kita mempunyai hal aktivitas lain yang ingin kita simpan juga dalam history ? Yang kita perlukan adalah meng-inisialisasi resource dalam file Bootstrap.php kita dengan menambahkan function _init* sebagai berikut :
protected function _initLog() { if ($this->hasPluginResource('log')){ $r = $this->getPluginResource('log'); $log = $r->getLog(); Zend_Registry::set('log', $log); } }
Kalau sudah, kita coba test dengan memanggil di sembarang action ( misal di TestlogController dengan action indexAction ) sebagai berikut :
Zend_Registry::get('log')->info('something happened');
maka, di file log akan tampil semacam berikut :
2011-04-17T00:03:15+07:00 INFO (6): something happened
Hm…, asyik kan ? semoga bermanfaat 😀
Referensi :
http://www.zendcasts.com/transparent-logging-with-zend_log/2010/06/
http://framework.zend.com/manual/en/zend.log.writers.html
http://id.php.net/stream
http://en.wikipedia.org/wiki/Server_log
http://framework.zend.com/manual/en/learning.quickstart.create-model.html
http://en.wikipedia.org/wiki/Stream_%28computing%29
Zend Framework : View Partials – Dealing with Complex Templates
Bagi kamu-kamu yang ber-background Ruby on Rails, tentu sudah tidak asing lagi donkz dengan View Partials. Perbedaan rendering secara partial dengan normal view adalah bahwa partial mempunyai ruang lingkup variable sendiri, ia hanya akan melihat variable yang dilewatkan secara langsung. Sebagai contoh seperti berikut :
<?php echo $this->partial('foo.phtml', array('foo' => 'bar')); ?>
Dari contoh di atas, variable yang bisa dipakai di foo.phtml hanyalah single variable ‘foo’ dengan value ‘bar’. View Partials biasanya digunakan untuk menangani complex templates dengan mempunyai banyak view logic ( dalam konsep MVC, dibolehkan terdapat logic di view, asalkan logic tersebut digunakan untuk mengolah view , bukan mengolah data ). Misal kita ingin menampilkan data sehingga tampil seperti berikut :
Ok, kita bisa membuat Controller seperti di bawah :
<?php //Controller class TestpartialController extends Zend_Controller_Action { public function init() { $this->getHelper('layout')->disableLayout(); } //simple func to create fake data private function setItem($id,$name) { $item = new stdClass(); $item->id = $id; $item->name = $name; return $item; } //index action -> render to index.phtml public function indexAction() { $items = array(); $items[] = $this->setItem(1,'abdul'); $items[] = $this->setItem(2,'malik'); $items[] = $this->setItem(3,'ikhsan'); $items[] = $this->setItem(4,'emang'); $items[] = $this->setItem(5,'ganteng'); $items[] = $this->setItem(6,'banget'); $items[] = $this->setItem(7,'gitu lhoh'); $this->view->items = $items; } }
Nah, di sisi view, kita ingin menampilkan data dengan record bergantian warna-warni ( dibutuhkan logic untuk mengolah view ), maka kita bisa bagi menjadi 2, satu untuk “heading” ( index.phtml ) dan satu untuk dilooping dengan logic yg lebih kompleks ( rows.phtml ) .
<table width="70%"> <tr> <th>ID</th> <th>NAME</th> </tr> <?php $alt = false; foreach($this->items as $item){ $alt = !$alt; // 'render' another view echo $this->partial('testpartial/rows.phtml', array('alt'=>$alt, 'item'=>$item) ); } ?> </table>
Sekarang, kita buat file view lain yang akan dirender dengan variable yang dilewatkan
array('alt'=>$alt, 'item'=>$item)
Berikut contoh view logic ( rows.phtml ) :
<?php $style = "background-color:yellow;"; //view logic to manage view if ($this->alt) $style=""; ?> <tr style="<?php echo $style; ?>"> <td><?php echo $this->item->id; ?></td> <td><?php echo $this->item->name; ?></td> </tr>
Semoga bermanfaat 😀
Referensi :
http://www.zendcasts.com/zend-view-partials/2009/03/
http://devzone.zend.com/article/3412
http://framework.zend.com/manual/en/zend.view.helpers.html
http://stackoverflow.com/questions/746260/where-do-i-save-partial-views-in-zend-framework-to-be-accessible-for-all-views
http://stackoverflow.com/questions/931407/what-is-stdclass-in-php
http://www.webmaster-source.com/2009/08/20/php-stdclass-storing-data-object-instead-array/
http://us2.php.net/variables.scope
5 comments