Здравствуйте, мне нужно реализовать кросс доменный post запрос. У меня есть сайт, на нем находится гиперссылка. По нажатию на гиперссылку должен идти post запрос на другой сервер на защищенную страницу (https). Прочитал в интернете, что можно реализовать через proxy. Что мне нужно: Послать на другой сервер на защищенную страницу (https) данные в формате json и c заголовком (content type) application/json. Ответ от сервера будет тоже в json с заголовком application/json. Вот что у меня есть: файл sample.html: Код (Text): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru"> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <script type="text/javascript" src="http://site.ru/jquery.js"></script> <script type="text/javascript"> var proxy_url = 'http://site.ru/proxy.php'; var ajax_url = 'https://site2.ru/example'; //другой сервер, на который должен идти post запрос! var people ={"FirstName":"Oleg","LastName":"Ivanov","amount":2.0}; $(document).ready(function(){ $('#link').click(function(){ $.ajax({ type: 'POST',dataType:'json',contentType:'application/json', url: proxy_url,data:people, 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> </head> <body> <a href="#" id="link">Запрос</a> </body> </html> Файл proxy.php Код (Text): <?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 .= "Referer: /misc/proxy.php\r\n"; $out .= "User-Agent: Opera\r\n"; $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; $out .= "Content-Length: ".strlen($data)."\r\n\n"; $out .= "Connection: close\r\n\r\n"; $out .= $data; fputs($fp, $out); $in = ''; while (($line = fgets($fp, 8192))!==false) $in .= $line; fclose($fp); fputs($fh, $in); fclose($fh); $out = substr($in, strpos($in, "\r\n\r\n") + 4); header("Content-type:text/plain; charset=utf-8"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); print $out; ?> Запрос идет, но приходит ответ, что parseerror. Мне кажется, что неправильно в proxy.php. Что данные идут не в json формате.. Прошу помощи. Пожалуйста.
Вот элементарно возьмите урежте этот скрипт до минимума и оставьте только отправку пост и success, далее в php тоже нужно json. И вообще прочтитека, что это и для, чего json. Зачем вы берете сразу тучу кода и пытаетесь понять? Что нельзя блин начать с малого и расширить!? Как будто у вас за спиной на вас направили B.5.1. =)
И научитесь вы читабельно писать код... Это просто как пример: Код (PHP): function posts(name,callback) { $.ajax( { url:'./post.php', cache:false, dataType:'json', success:function(data) { callback(data); }, type:'post', data:{name:name} }); } var name=$('input[name=name]').val(); posts(name,function(data) { ...........data.json[0].name............ bla bla bla............................. }); Чтобы не путаться и видеть все действия, а не в строку пока просмотришь застрелят =) еще есть такое чудо $.post();
ну ведь ajax работает, только внутри одного домена. А мне нужно, передать post запрос со своего сервера на другой сервер на защищенную страницу, причем json и с заголовком application/json. Поэтому приходится так вертеться.
я понимаю, что такое json, но я никак не могу понять, почему у меня идет ошибка parseerror от другого сервера..
Пройдись по всем этапам работы программы и посмотри, где в какой момент какие данные. Посмотри, какой запрос приходит в PHP от JS - распечатай его полностью (или сохрани в файл) и посмотри. Убедись, что ты правильно его обрабатываешь. Таким же образом (вывод на экран или в файл) проверь, какой именно запрос ты отправляешь на удалённый сервер - т.е. выведи на экран или в файл ту самую строку, которую отправляешь на сервер. Точно также же проверь данные, которые приходят в ответ от удалённого сервера. Распечатай в своём JS-коде ответ от своего сервера.
Смотрите, ставлю в первом файле : Код (Text): var people ={"FirstName":"Oleg","LastName":"Ivanov","amount":2.0}; alert(people); Alert выдает Object object. Код (Text): error: function(xhr, er_type) { alert('Ошибка: ' + er_type); } Выдаст Ошибкаarseerror Ответ от сервера : 0|Неверный запрос Мне немного непонятно вот тут: Код (Text): 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); Сообственно получается, что она преобразует в строку и отправляет? а мне нужно в json.
Для начала - json - это и есть строка текста. Просто строка текста в определённом формате и не более того. Это: Код (PHP): if (!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' || !count($_POST) || !isset($_POST['ajax_url'])) die("0|Неверный запрос"); Проверяет, чтобы в массиве $_SERVER был элемент HTTP_X_REQUESTED_WITH и его значение должно быть равно XMLHttpRequest, а также, чтобы массив $_POST был не пустой и в нём присутствовал элемент ajax_url. Собственно, чего-то у тебя нет, раз скрипт постоянно вылетает на этой ошибке Распечатай, что у тебя в массиве $_SERVER и в массиве $_POST.
Так? а не подскажешь аналог alert на php? Код (Text): if (!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' || !count($_POST) || !isset($_POST['ajax_url'])) die("0|Неверный запрос"); echo ($_SERVER['HTTP_X_REQUESTED_WITH']); echo ($_POST['ajax_url']); Добавлено спустя 30 минут 37 секунд: Я понял в чем дело переделал первый скрипт: Код (Text): data.FirstName= "Oleg"; data.LastName = "Ivanov"; data.amount="100.0"; data.ajax_url = "https://site2.ru/example"; .... //post теперь выглядит так: $.ajax({ type: 'POST', url: proxy_url,data:data, ... Теперь запрос доходит до сервера и выдает: Код (Text): <html> <head><title>302 Found</title></head> <body bgcolor="white"> <center><h1>302 Found</h1></center> <hr><center>nginx</center> </body> </html> Но в параметрах, которые передаются post запросом учавствует ajax_url... как мне ее убрать из параметров?
Прописать в PHP-скрипте, я думаю. Если нужно дёргать разные сайты в зависимости от параметров - можешь передавать из JS в PHP номер, по которому PHP-скрипт будет определять, к какому сайту делать запрос. Я думаю, можно переделать скрипт. Я убрал бы эти проверки: Код (PHP): isset($_SERVER['HTTP_X_REQUESTED_WITH']) Код (PHP): $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' Во-первых, не все сервера (ну, или не при любых настройках) эти значения предоставляют, во-вторых - не вижу от них толка в данном скрипте. Из JS адрес сервера, к которому ты будешь делать запрос - можно убрать. Тогда нужно убрать также эту проверку: Код (PHP): !isset($_POST['ajax_url']) Ну и вот эти строки: Код (PHP): $url_info = parse_url($_POST['ajax_url']); unset($_POST['ajax_url']); Вместо этого можешь написать Код (PHP): $url_info = array('host' => 'site2.ru', 'path' => '/example'); Вместо сокетов я бы использовал file_get_contents() - мне кажется, что работать с ним несколько проще, но это уже дело привычек. Теперь по поводу parseerror. Когда ты указываешь в JS скрипте Код (Text): dataType:'json' Ты указываешь ожидаемый формат данных, которые придут тебе в ответе от сервера. Но у тебя скрипт завершал работу вот этой строкой: Код (PHP): die("0|Неверный запрос"); А она не является строкой в формате JSON. По этому твой JavaScript и ругается, что не может распарсить ответ от сервера. Если ты будешь возвращать корректную JSON-строку, то, по идее, эта ошибка исчезнет. Я не знаю, что там вернёт тот сервер, к которому ты делаешь запрос, но если он действительно вернёт строку в формате JSON - то должно заработать. Ну, правда есть ещё одна мелочь. Твой JS-скрипт ожидает получить в ответе строку в формате JSON, а ты ему отправляешь зачем-то загаловок, что в ответе будет text/plain... В общем, касаемо серверной части, у меня получилось бы что-то наподобии такого: Код (PHP): <?php if(!count($_POST)) die('[0,"Неверный запрос"]'); $data = array(); foreach($_POST as $k => $v) $data[] = $k . '=' . $v; $data = implode('&', $data); // Тут прописываем адрес, по которому будем обращаться к удалённому серверу $url = 'http://site.com/path'; $options = array( 'http' => array( 'method' => 'POST', 'user_agent' => 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.10.229 Version/11.61', 'content' => $data ) ); $context = stream_context_create($options); $out = file_get_contents($url, false, $options); header('Content-type: application/json'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: post-check=0, pre-check=0', false); echo $out; ?>
Заменил мой серверный скрипт на Ваш теперь появился Warning : file_get_contents() expects parameter 3 to be resource, array given in адрес on line 21. Выводится alert'ом
$context = stream_context_create($options); $out = file_get_contents($url, false, $options); во втором случае контекст должен быть а не опции
Если заменить опции на контекст будет сообщение : Код (Text): <br /> <b>Notice</b>: file_get_contents() [<a href='function.file-get-contents'>function.file-get-contents</a>]: Content-type not specified assuming application/x-www-form-urlencoded in <b>/home/proxy.php</b> on line <b>21</b><br /> <br /> <b>Warning</b>: file_get_contents(адрес сервера (защищенная страница) на который посылаем запрос) [<a href='function.file-get-contents'>function.file-get-contents</a>]: failed to open stream: HTTP request failed! HTTP/1.1 415 Unsupported Media Type in <b>/home/proxy.php</b> on line <b>21</b><br />
Можете попробовать через curl. А так хз, может быть у Вас либа тупит php_openssl.dll или закомментирована?
А можно поподробней, я ее нигде не подключал.. У меня сайт на платном хостинге Добавлено спустя 16 минут 26 секунд: failed to open stream: HTTP request failed! HTTP/1.1 415 Unsupported Media Type Может это из-за того, что не совпадают заголовки сообщения ? мне нужно в запросе использовать application/json и в ответе приходит application/json.
Ребят, ошибка 'failed to open stream: HTTP request failed! HTTP/1.1 415 Unsupported Media Type' из-за того, что в запросе Content-Type:application/x-www-form-urlencoded, а надо application/json, как его можно поменять ?
Добавить соответствующий заголовок в $options: Код (PHP): $options = array( 'http' => array( 'method' => 'POST', 'header' => 'Content-type: application/json', 'user_agent' => 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.10.229 Version/11.61', 'content' => $data ) );
Спасибо! ) Осталась последняя ошибка. Почему то ругается на строчку Код (Text): $out = file_get_contents($url, false, $context); Выдает: file_get_contents(https://адрес сервера запроса) [<a href='function.file-get-contents'>function.file-get-contents</a>]: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request in <b>/home/proxy.php</b> on line <b>23</b><br /> Помогите пожалуйста
Ну, если тот удалённый сервер хочет получить от тебя строку в формате JSON - то, видимо, в таком формате и надо ему её передавать Вместо этого: Код (PHP): $data = array(); foreach($_POST as $k => $v) $data[] = $k . '=' . $v; $data = implode('&', $data); Написать: Код (PHP): $data = json_encode($_POST); Только неизвестным остаётся, в какую POST-переменную эту строку засунуть. Вообще, недостаточно информации. Нужно точно знать, что и в каком виде хочет получить от тебя тот сервер, к которому ты делаешь запрос, чтобы вернуть тебе правильный ответ. Мы же тут понятия об этом не имеем и "гадаем на кофейной гуще". Если бы была чёткая информация по этому поводу - всё решилось бы ещё несколько постов назад.
Если написать : Код (Text): $data = json_encode($_POST); то будет ошибка: И заголовок сообщения почему то поменялся, теперь он html/text Надо : Json объект вида { "FirstName":"Oleg", "LastName":"Ivanov", ... } Заголовок запроса и ответа: application/json.
Что-то ты там где-то напутал, наверно, пока менял. Должно было получиться такое: Код (PHP): <?php if(!count($_POST)) die('[0,"Неверный запрос"]'); $data = json_encode($_POST); // Тут прописываем адрес, по которому будем обращаться к удалённому серверу $url = 'http://site.com/path'; $options = array( 'http' => array( 'method' => 'POST', 'header' => 'Content-type: application/json', 'user_agent' => 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.10.229 Version/11.61', 'content' => $data ) ); $context = stream_context_create($options); $out = file_get_contents($url, false, $context); header('Content-type: application/json'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: post-check=0, pre-check=0', false); echo($out); ?> Никаких parse error тут не должно быть. Но и заработает это врядли - и я написал выше почему. Никто не знает, какой запрос ожидает получить от тебя удалённый сервер.