Menelusuri Permasalahan jQuery AJAX CORS (Cross-Origin Resource Sharing)

First of all, mengenai tentang CORS bisa membaca referensinya disini, bagi yang belum mengenalnya bisa membacanya terlebih dahulu.

Cross-origin resource sharing (CORS) is a mechanism that allows many resources (e.g. fonts, JavaScript, etc.) on a web page to be requested from another domain outside the domain the resource originated from. In particular, JavaScript’s AJAX calls can use the XMLHttpRequest mechanism. Such “cross-domain” requests would otherwise be forbidden by web browsers, per the same origin security policy. CORS defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request. It is more useful than only allowing same-origin requests, but it is more secure than simply allowing all such cross-origin requests.

Saat ini saya menghadapi suatu kasus dimana saya melakukan request POST melalui AJAX terhadap domain yang berbeda. Prosesnya seperti ini:

  1. domainsatu.com melakukan request POST menggunakan AJAX terhadap domaindua.com
  2. domaindua.com memproses request POST tersebut, lalu memberikan output atau return value terhadap domainsatu.com
  3. domainsatu.com mendapatkan output atau return value dari domaindua.com.

Berikut contoh code jQuery AJAX melakukan request, yang pada kasus ini jenis request-nya POST:

[php]
// request terhadap domaindua.com
var req = $.ajax({
type: ‘POST’,
url: ‘http://domaindua.com/post/’,
data: { post_id: 999, post_type: ‘article’ },
dataType: "html",
timeout: 30000, // 30 sec
});

// jika request berhasil
req.done(function(val){
// do something with ‘val’ value
});

// jika request gagal
req.fail(function(jqXHR, msg){
// reporting ‘msg’ message
});
[/php]

Permasalahannya adalah ketika saya melakukan AJAX request menggunakan jQuery terhadap domain yang berbeda, request yang diberikan domainsatu.com dapat diterima dan diproses oleh domaindua.com, namun domainsatu.com tidak bisa mendapatkan output atau return value dari domaindua.com.

[Missing Image]

Terlihat pada gambar diatas bahwa Cross-Origin Request diblok 🙁

Saya mencoba mencari penyelesaiannya, dan menemukan caranya dengan menambahkan code PHP, Header Control Allow Origin.

[php]
header( "Access-Control-Allow-Origin: *" );
header( "Access-Control-Allow-Credentials: true" );
header( "Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS" );
header( "Access-Control-Max-Age: 604800" );
header( "Access-Control-Request-Headers: x-requested-with" );
header( "Access-Control-Allow-Headers: x-requested-with, x-requested-by" );
[/php]

Bagi pengguna framework CodeIgniter penulisan code menjadi seperti ini:

[php]
$this->output->set_header( "Access-Control-Allow-Origin: *" );
$this->output->set_header( "Access-Control-Allow-Credentials: true" );
$this->output->set_header( "Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS" );
$this->output->set_header( "Access-Control-Max-Age: 604800" );
$this->output->set_header( "Access-Control-Request-Headers: x-requested-with" );
$this->output->set_header( "Access-Control-Allow-Headers: x-requested-with, x-requested-by" );
[/php]

Jika menggunakan Web Server Apache, perlu dipastikan mod_headers aktif, secara default memang sudah aktif. Sehingga permasalahan untuk kondisi seperti ini bisa dikatakan selesai.

Namun, saya memiliki kondisi yang lain lagi, saya menggunakan Web Server Apache yang saya sendiri tidak memiliki hak akses penuh, dan mod_headers di non-aktifkan. Kabar buruk? Ya, tentu saja, tapi saya mencoba berpikir lagi dan mendapatkan cara lain lagi untuk menyelesaikan masalah ini, yaitu dengan membuat file php khusus atau jika menggunakan framework CodeIgniter, buatlah controller khusus untuk melakukan request, dengan menggunakan native function php file_get_contents.

Sehingga AJAX request dilakukan dari domainsatu.com terhadap file php/controller khusus yang dimiliki oleh domainsatu.com, yang didalam file php/controller khusus domainsatu.com tersebut terdapat function file_get_contents yang melakukan request ke domaindua.com.

Lebih jelasnya, tahapannya menjadi sebagai berikut:

  1. domainsatu.com melakukan request POST menggunakan AJAX terhadap file php/controller khusus domainsatu.com, misalkan terhadap domainsatu.com/post.
  2. domainsatu.com/post melakukan request menggunakan function file_get_contents terhadap domaindua.com
  3. domaindua.com memproses request tersebut, lalu memberikan output atau return value terhadap domainsatu.com/post
  4. domainsatu.com mendapatkan output atau return value dari domaindua.com/post.

Kesimpulannya ada satu tahapan tambahan, yang secara garis besar dapat dikatakan request AJAX dilakukan dari domainsatu.com diarahkan ke domainsatu.com itu sendiri (domainsatu.com/post), sehingga return value dapat diperoleh sesuai request, dan dianggap tidak terjadi CORS, padahal terjadi CORS terhadap domaindua.com, hanya saja request tersebut “diselundupkan” melalui perantara file php/controller khusus (domainsatu.com/post).

Jika keadaan mendesak dan terbatas, cara tricky ini bisa dijadikan alternatif. Semoga bermanfaat. 😀

By the way, judulnya terlihat membingungkan yaa.. “Menelusuri Permasalahan jQuery AJAX CORS (Cross-Origin Resource Sharing)“, saya tidak tahu judul yang lebih tepat untuk pemasalahan ini seperti apa, menjelaskannya pun sedikit kebingungan, intinya seperti inilah. 🙂

Bagi yang memiliki pengalaman tentang CORS bisa sharing disini melalui komentar 😉

Referensi:

  1. http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
  2. http://www.w3.org/TR/cors/
  3. http://enable-cors.org
  4. http://stackoverflow.com/questions/5750696/how-to-get-a-cross-origin-resource-sharing-cors-post-request-working
  5. http://stackoverflow.com/questions/5584923/a-cors-post-request-works-from-plain-javascript-but-why-not-with-jquery
  6. http://ellislab.com/codeigniter/user-guide/libraries/output.html
  7. http://code.tutsplus.com/tutorials/building-a-codeigniter-web-application-from-scratch-part-1–net-34338

Published by

Riza

Web Developer & Designer

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.