link.png Cross-domain jQuery AJAX ← Powrót

Technologia AJAX pozwoliła twórcom witryn na łączenie się z serwerem i pobieranie z niego potrzebnych informacji bez przeładowywania całej strony. Nowe możliwości stały się jednocześnie furtką dla nowego rodzaju ataków na strony, poprzez wysyłanie lub pobieranie danych z innych, niż aktualnie odwiedzana witryn. Mogło się to dziać w tle bez wiedzy użytkownika. Taka opcja została więc szybko zablokowana przez twórców przeglądarek. Co jednak, gdy mimo wszystko zajdzie potrzeba połączenia się z serwerem o innym adresie?

Cross-domain

W przypadku innego typu danych jak np. obrazków, czy całych skryptów ten problem nie występuje. Wystarczy wpisać dowolny adres w atrybucie src, a przeglądarka posłusznie zaciągnie wskazany obiekt. Dlaczego, więc nie wykorzystać tej metody do asynchronicznego kontaktu z serwerem? 

<script type="text/javascript" src="http://www.matw.pl/samples/codeigniter/static/js/jquery-1.8.3.min.js"></script>

Tworząc za pomocą języka JavaScript odpowiedni adres możemy umieścić w nim praktycznie dowolne parametry. Następnie wystarczy dodać odpowiednio przygotowany fragment kodu do dokumentu, wtedy przeglądarka pobierze dane z wskazanej lokalizacji, a my będziemy mogli je dalej przetworzyć. Tak, w dużym skrócie, działa skrypt pozwalający na takie połączenie. To podejście ma jednak pewne wady m.in. brak możliwości ustawienia nagłówków czy konieczność przekazywania danych metodą GET, co jednak w większości przypadków nie będzie stanowiło znaczących trudności.

Przykład

Powyższe rozwiązanie zostało również zaimplementowane w bibliotece jQuery. Przejdźmy zatem do krótkiego przykładu obrazującego jego działanie. Nasz skrypt ma za zadanie wysłać do serwera dwa wyrazy uzupełnione w formularzu, dla których serwer zwróci odległość pomiędzy nimi. Odległość wyrazów jest równa liczbie operacji (dodanie znaku, usunięcie znaku lub zmiana wskazanego znaku na inny), które należy wykonać, aby z jednego wyrazu otrzymać drugi  np. odległość wyrazów hotel i hottel wynosi 1, ponieważ, aby z pierwszego z nich uzyskać drugi należy w odpowiednim miejscu dodać literkę t (lub analogicznie z drugiego ją usunąć). Do wyznaczenia odległości skorzystamy z natywnej funkcji PHP levenshtein. Funkcja napisana w JavaScript z pomocą biblioteki jQuery wygląda następująco:

<script type="text/javascript">
        function ajax_check_word_distance() {
                var url = 'http://www.matw88.nazwa.pl/_samples/crossdomainajax/index.php';
                var word1 = $('#word1').val();
                var word2 = $('#word2').val();
                
                $.ajax({
                        url: url,
                        dataType: 'jsonp',
                        type: 'GET',
                        data: {
                                word1: word1,
                                word2: word2
                                },
                        success: function(response) {
                                console.log(response);
                                $('#info').html('Odległość wyrazów "'+word1+'" i "'+word2+'" wynosi '+response);
                        }
                });
	}
</script>

Parametrem odpowiadającym za możliwość połączenia z inną domeną jest ustawienie dataType na JSONP – który w obsłudze jest analogiczny do tradycyjnego JSON’a . Różnica w zapytaniu polega na przesłaniu specjalnego identyfikatora, który automatycznie jest doklejany przez bibliotekę a później dodaniu go do zwracanej z serwera odpowiedzi. W przypadku cross-domain’owego połączenia na próżno możemy szukać  w konsoli zapytania przesyłanego AJAX’em – inny sposób jego wykonania sprawia, że jest ono tam niewidoczne, a podglądnięcie go wymaga zastosowania programów takich jak np. Fiddler.  Skrypt na serwerze przedstawia się następująco:

<?php 

	//odbieramy przesłane słowa
        $word1 = $_GET['word1'];
        $word2 = $_GET['word2'];

	//wyznaczamy ich odległość
        $distance = levenshtein($word1,$word2);

	//wysyłamy odpowiedź jako JSON
        die($_GET['callback'].'('.json_encode($distance).')');

?>

A teraz zapraszam do przetestowania opisanego przykładu:

Wyraz 1:

Wyraz 2:

Zobacz także: