Простой способ реализовать кроссдоменный AJAX-запрос методом POST

Как известно, объект XMLHttpRequest не разрешает делать запросы на другой домен. В будущей версии XMLHttpRequest этого ограничения нет, однако, к сожалению, пройдет еще немало времени прежде чем его можно будет использовать без оглядки на старые браузеры. Давайте посмотрим как можно быстро реализовать кроссдоменный post-запрос.

Суть способа достаточно тривиальна:

  1. Делаем AJAX-запрос PHP-скрипту на этом же домене;
  2. Этот скрипт пересылает запрос PHP-скрипту на другой домен;
  3. После получения ответа с другого домена, первый PHP-скрипт отвечает AJAX-запросу.

Единственное требование — возможность размещения и выполнения на исходном домене php-скрипта (+ возможность работы с сокетами).

Напишем пример JavaScript кода, отправляющего AJAX-запрос методом POST. Для простоты примера используем библиотеку JQuery.

<script type="text/javascript">
var proxy_url = '/proxy.php';
var ajax_url = 'http://www.otherdomain.com/ajax.php';

$(document).ready(function() {
  var data = new Object();
  data.field = 'value';
  data.field1 = 'value1';
  data.ajax_url = ajax_url;
  $.ajax({
    type: 'POST', url: proxy_url, dataType: 'html', data: data,
    success: function(res) {
      flag = res.substring(0, 2);
      if (flag == '0|') alert('Ошибка: ' + res.substring(2, res.length));
      else alert('Удачно: ' + res);
    },
    error: function(xhr, er_type) { alert('Ошибка: ' + er_type); }
  });
});
</script>

Теперь напишем код скрипта proxy.php. Для запроса к PHP-скрипту на другом домене, будем использовать фукнцию fsockopen().

<?php
error_reporting(0);
if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])
	|| $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest'
	|| !count($_POST) || !isset($_POST['ajax_url']))
		die("0|Неверный запрос");
$url_info = parse_url($_POST['ajax_url']);
unset($_POST['ajax_url']);

$data = array();
foreach ($_POST as $k => $v) $data[] = $k.'='.$v;
$data = implode('&', $data);

$fp = fsockopen(@$url_info['host'], 80, $errno, $errstr, 6);
if (!$fp) die("0|Не могу соединиться с ".@$url_info['host']);
$out  = "POST ".@$url_info['path']." HTTP/1.1\r\n";
$out .= "Host: ".@$url_info['host']."\r\n";
$out .= "Content-Type: application/x-www-form-urlencoded\r\n";
$out .= "Content-Length: ".strlen($data)."\r\n";
$out .= "Connection: close\r\n\r\n";
$out .= $data;
fputs($fp, $out);

$in = '';
while (($line = fgets($fp, 8192))!==false) $in .= $line;
fclose($fp);
header("Content-type: text/plain; charset=windows-1251");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
print substr($in, strpos($in, "\r\n\r\n") + 4);
?>

А теперь напишем конечный скрипт ajax.php, который будет находиться на другом домене и отвечать proxy.php.

<?php
error_reporting(0);
header("Content-type: text/plain; charset=windows-1251");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Connection: close");

if (!count($_POST)) die('0|Неверный запрос');
$data = array();
foreach ($_POST as $k => $v) $data[] = $k.'='.$v;
echo implode('&', $data);
exit;
?>

Кликнув ниже на ссылку "Протестировать", вы фактически отправите кроссдоменный запрос с alt-f4.ru на домен portal.e-gloryon.com. Результатом будет простой alert вернувшихся данных.

Протестировать

В прикрепленных файлах можно скачать архив с исходниками, в который входят файлы (инструкции в файле Readme.txt):

  1. Readme.txt
  2. sample.html
  3. jquery.js
  4. proxy.php
  5. ajax.php

Добавить комментарий

Filtered HTML

  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешённые HTML-теги: <a> <em> <i> <strong> <b> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <br>
  • Строки и параграфы переносятся автоматически.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
CAPTCHA на основе изображений
Введите код с картинки