За последние 24 часа нас посетили 19057 программистов и 1623 робота. Сейчас ищут 772 программиста ...

Post запрос

Тема в разделе "Прочие вопросы по PHP", создана пользователем Serjuk, 7 апр 2012.

  1. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Здравствуйте, мне нужно реализовать кросс доменный post запрос. У меня есть сайт, на нем находится гиперссылка. По нажатию на гиперссылку должен идти post запрос на другой сервер на защищенную страницу (https). Прочитал в интернете, что можно реализовать через proxy.
    Что мне нужно: Послать на другой сервер на защищенную страницу (https) данные в формате json и c заголовком (content type) application/json.
    Ответ от сервера будет тоже в json с заголовком application/json.

    Вот что у меня есть:
    файл sample.html:
    Код (Text):
    1.  
    2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    3. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
    4. <head>
    5.     <meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
    6.     <script type="text/javascript" src="http://site.ru/jquery.js"></script>
    7.  
    8. <script type="text/javascript">
    9.     var proxy_url = 'http://site.ru/proxy.php';
    10.     var ajax_url = 'https://site2.ru/example'; //другой сервер, на который должен идти post запрос!
    11. var people ={"FirstName":"Oleg","LastName":"Ivanov","amount":2.0};
    12.  
    13. $(document).ready(function(){
    14.         $('#link').click(function(){
    15.            
    16.             $.ajax({
    17.               type: 'POST',dataType:'json',contentType:'application/json', url: proxy_url,data:people,
    18.            
    19.                          success: function(res) {
    20.               flag = res.substring(0, 2);
    21.                 if (flag == '0|') alert('Ошибка: ' + res.substring(2, res.length));
    22.                else alert('Удачно: ' + res);
    23.               },
    24.               error: function(xhr, er_type) { alert('Ошибка: ' + er_type); }
    25.             });
    26.         });
    27.     });
    28.     </script>
    29. </head>
    30. <body>
    31. <a href="#" id="link">Запрос</a>
    32. </body>
    33. </html>
    Файл proxy.php
    Код (Text):
    1.  
    2. <?php
    3. error_reporting(0);
    4. if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])
    5.     || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest'
    6.     || !count($_POST) || !isset($_POST['ajax_url']))
    7.         die("0|Неверный запрос");
    8. $url_info = parse_url($_POST['ajax_url']);
    9. unset($_POST['ajax_url']);
    10.  
    11. $data = array();
    12. foreach ($_POST as $k => $v) $data[] = $k.'='.$v;
    13. $data = implode('&', $data);
    14.  
    15. $fp = @fsockopen(@$url_info['host'], 80, $errno, $errstr, 6);
    16. if (!$fp) die("0|Не могу соединиться с ".@$url_info['host']);
    17. $out  = "POST ".@$url_info['path']." HTTP/1.1\r\n";
    18. $out .= "Host: ".@$url_info['host']."\r\n";
    19. $out .= "Referer: /misc/proxy.php\r\n";
    20. $out .= "User-Agent: Opera\r\n";
    21. $out .= "Content-Type: application/x-www-form-urlencoded\r\n";
    22. $out .= "Content-Length: ".strlen($data)."\r\n\n";
    23. $out .= "Connection: close\r\n\r\n";
    24. $out .= $data;
    25. fputs($fp, $out);
    26.  
    27. $in = '';
    28. while (($line = fgets($fp, 8192))!==false) $in .= $line;
    29. fclose($fp);
    30.  
    31. fputs($fh, $in);
    32. fclose($fh);
    33.  
    34. $out = substr($in, strpos($in, "\r\n\r\n") + 4);
    35.  
    36. header("Content-type:text/plain; charset=utf-8");
    37. header("Cache-Control: no-store, no-cache, must-revalidate");
    38. header("Cache-Control: post-check=0, pre-check=0", false);
    39. print $out;
    40. ?>
    Запрос идет, но приходит ответ, что parseerror. Мне кажется, что неправильно в proxy.php. Что данные идут не в json формате..
    Прошу помощи. Пожалуйста.
     
  2. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    ВАХ!!!
     
  3. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
  4. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Вот элементарно возьмите урежте этот скрипт до минимума и оставьте только отправку пост
    и success, далее в php тоже нужно json.

    И вообще прочтитека, что это и для, чего json.

    Зачем вы берете сразу тучу кода и пытаетесь понять?

    Что нельзя блин начать с малого и расширить!?

    Как будто у вас за спиной на вас направили B.5.1. =)
     
  5. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    знаешь как помочь ?
     
  6. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    И научитесь вы читабельно писать код...

    Это просто как пример:

    Код (PHP):
    1. function posts(name,callback)
    2. {
    3.     $.ajax(
    4.     {
    5.         url:'./post.php',
    6.         cache:false,
    7.         dataType:'json',
    8.         success:function(data)
    9.         {
    10.             callback(data);
    11.         },
    12.         type:'post',
    13.         data:{name:name}
    14.     });
    15. }
    16. var name=$('input[name=name]').val();
    17. posts(name,function(data)
    18. {
    19.     ...........data.json[0].name............
    20.     bla bla bla.............................
    21. });
    22.  
    Чтобы не путаться и видеть все действия, а не в строку пока просмотришь застрелят =)


    еще есть такое чудо $.post();
     
  7. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    ну ведь ajax работает, только внутри одного домена. А мне нужно, передать post запрос со своего сервера на другой сервер на защищенную страницу, причем json и с заголовком application/json.
    Поэтому приходится так вертеться.
     
  8. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Читайте, что такое json
     
  9. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    я понимаю, что такое json, но я никак не могу понять, почему у меня идет ошибка parseerror от другого сервера..
     
  10. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Пройдись по всем этапам работы программы и посмотри, где в какой момент какие данные. Посмотри, какой запрос приходит в PHP от JS - распечатай его полностью (или сохрани в файл) и посмотри. Убедись, что ты правильно его обрабатываешь.
    Таким же образом (вывод на экран или в файл) проверь, какой именно запрос ты отправляешь на удалённый сервер - т.е. выведи на экран или в файл ту самую строку, которую отправляешь на сервер.
    Точно также же проверь данные, которые приходят в ответ от удалённого сервера.
    Распечатай в своём JS-коде ответ от своего сервера.
     
  11. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Смотрите, ставлю в первом файле :
    Код (Text):
    1. var people ={"FirstName":"Oleg","LastName":"Ivanov","amount":2.0};
    2. alert(people);
    Alert выдает Object object.
    Код (Text):
    1.   error: function(xhr, er_type) { alert('Ошибка: ' + er_type); }
    Выдаст Ошибка:parseerror
    Ответ от сервера : 0|Неверный запрос

    Мне немного непонятно вот тут:
    Код (Text):
    1. if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])
    2.    || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest'
    3.    || !count($_POST) || !isset($_POST['ajax_url']))
    4.       die("0|Неверный запрос");
    5. $url_info = parse_url($_POST['ajax_url']);
    6. unset($_POST['ajax_url']);
    7.  
    8. $data = array();
    9. foreach ($_POST as $k => $v) $data[] = $k.'='.$v;
    10. $data = implode('&', $data);
    Сообственно получается, что она преобразует в строку и отправляет? а мне нужно в json.
     
  12. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Для начала - json - это и есть строка текста. Просто строка текста в определённом формате и не более того.
    Это:
    Код (PHP):
    1. if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])
    2.    || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest'
    3.    || !count($_POST) || !isset($_POST['ajax_url']))
    4.       die("0|Неверный запрос"); 
    Проверяет, чтобы в массиве $_SERVER был элемент HTTP_X_REQUESTED_WITH и его значение должно быть равно XMLHttpRequest, а также, чтобы массив $_POST был не пустой и в нём присутствовал элемент ajax_url.
    Собственно, чего-то у тебя нет, раз скрипт постоянно вылетает на этой ошибке :)
    Распечатай, что у тебя в массиве $_SERVER и в массиве $_POST.
     
  13. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Так? а не подскажешь аналог alert на php?
    Код (Text):
    1.  
    2. if (!isset($_SERVER['HTTP_X_REQUESTED_WITH'])
    3.    || $_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest'
    4.    || !count($_POST) || !isset($_POST['ajax_url']))
    5.       die("0|Неверный запрос");
    6. echo ($_SERVER['HTTP_X_REQUESTED_WITH']);
    7. echo ($_POST['ajax_url']);
    Добавлено спустя 30 минут 37 секунд:
    Я понял в чем дело
    переделал первый скрипт:
    Код (Text):
    1.  
    2.  data.FirstName= "Oleg";
    3.   data.LastName = "Ivanov";
    4.   data.amount="100.0";
    5. data.ajax_url = "https://site2.ru/example";
    6. ....
    7. //post теперь выглядит так:
    8. $.ajax({
    9.         type: 'POST', url: proxy_url,data:data,
    10.  ...
    Теперь запрос доходит до сервера и выдает:
    Код (Text):
    1.  
    2.  
    3. <html>
    4. <head><title>302 Found</title></head>
    5. <body bgcolor="white">
    6. <center><h1>302 Found</h1></center>
    7. <hr><center>nginx</center>
    8. </body>
    9. </html>
    Но в параметрах, которые передаются post запросом учавствует ajax_url... как мне ее убрать из параметров?
     
  14. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Прописать в PHP-скрипте, я думаю. Если нужно дёргать разные сайты в зависимости от параметров - можешь передавать из JS в PHP номер, по которому PHP-скрипт будет определять, к какому сайту делать запрос.

    Я думаю, можно переделать скрипт. Я убрал бы эти проверки:
    Код (PHP):
    1. isset($_SERVER['HTTP_X_REQUESTED_WITH']) 
    Код (PHP):
    1. $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' 
    Во-первых, не все сервера (ну, или не при любых настройках) эти значения предоставляют, во-вторых - не вижу от них толка в данном скрипте.
    Из JS адрес сервера, к которому ты будешь делать запрос - можно убрать. Тогда нужно убрать также эту проверку:
    Код (PHP):
    1. !isset($_POST['ajax_url']) 
    Ну и вот эти строки:
    Код (PHP):
    1. $url_info = parse_url($_POST['ajax_url']);
    2. unset($_POST['ajax_url']); 
    Вместо этого можешь написать
    Код (PHP):
    1. $url_info = array('host' => 'site2.ru', 'path' => '/example'); 
    Вместо сокетов я бы использовал file_get_contents() - мне кажется, что работать с ним несколько проще, но это уже дело привычек.

    Теперь по поводу parseerror. Когда ты указываешь в JS скрипте
    Код (Text):
    1. dataType:'json'
    Ты указываешь ожидаемый формат данных, которые придут тебе в ответе от сервера. Но у тебя скрипт завершал работу вот этой строкой:
    Код (PHP):
    1. die("0|Неверный запрос"); 
    А она не является строкой в формате JSON. По этому твой JavaScript и ругается, что не может распарсить ответ от сервера.
    Если ты будешь возвращать корректную JSON-строку, то, по идее, эта ошибка исчезнет. Я не знаю, что там вернёт тот сервер, к которому ты делаешь запрос, но если он действительно вернёт строку в формате JSON - то должно заработать. Ну, правда есть ещё одна мелочь. Твой JS-скрипт ожидает получить в ответе строку в формате JSON, а ты ему отправляешь зачем-то загаловок, что в ответе будет text/plain...

    В общем, касаемо серверной части, у меня получилось бы что-то наподобии такого:
    Код (PHP):
    1. <?php
    2. if(!count($_POST))
    3.     die('[0,"Неверный запрос"]');
    4.  
    5. $data = array();
    6. foreach($_POST as $k => $v)
    7.     $data[] = $k . '=' . $v;
    8. $data = implode('&', $data);
    9.  
    10. // Тут прописываем адрес, по которому будем обращаться к удалённому серверу
    11. $url = 'http://site.com/path';
    12.  
    13. $options = array(
    14.     'http' => array(
    15.         'method' => 'POST',
    16.         'user_agent' => 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.10.229 Version/11.61',
    17.         'content' => $data
    18.     )
    19. );
    20. $context = stream_context_create($options);
    21. $out = file_get_contents($url, false, $options);
    22.  
    23. header('Content-type: application/json');
    24. header('Cache-Control: no-store, no-cache, must-revalidate');
    25. header('Cache-Control: post-check=0, pre-check=0', false);
    26. echo $out;
    27. ?>
     
  15. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Заменил мой серверный скрипт на Ваш теперь появился Warning : file_get_contents() expects parameter 3 to be resource, array given in адрес on line 21. Выводится alert'ом
     
  16. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    $context = stream_context_create($options);
    $out = file_get_contents($url, false, $options);
    во втором случае контекст должен быть а не опции
     
  17. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Если заменить опции на контекст будет сообщение :
    Код (Text):
    1. <br />
    2. <b>Notice</b>:  file_get_contents() [<a href='function.file-get-contents'>function.file-get-contents</a>]: Content-type not specified assuming
    3. application/x-www-form-urlencoded in <b>/home/proxy.php</b> on line <b>21</b><br />
    4. <br />
    5. <b>Warning</b>:  file_get_contents(адрес сервера (защищенная страница) на который посылаем запрос)
    6. [<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
    7.  in <b>/home/proxy.php</b> on line <b>21</b><br />
     
  18. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
    Можете попробовать через curl.
    А так хз, может быть у Вас либа тупит php_openssl.dll или закомментирована?
     
  19. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    А можно поподробней, я ее нигде не подключал.. У меня сайт на платном хостинге

    Добавлено спустя 16 минут 26 секунд:
    failed to open stream: HTTP request failed! HTTP/1.1 415 Unsupported Media Type

    Может это из-за того, что не совпадают заголовки сообщения ? мне нужно в запросе использовать application/json и в ответе приходит application/json.
     
  20. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Ребят, ошибка 'failed to open stream: HTTP request failed! HTTP/1.1 415 Unsupported Media Type' из-за того, что в запросе Content-Type:application/x-www-form-urlencoded, а надо application/json, как его можно поменять ?
     
  21. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Добавить соответствующий заголовок в $options:

    Код (PHP):
    1. $options = array(
    2.     'http' => array(
    3.         'method' => 'POST',
    4.         'header' => 'Content-type: application/json',
    5.         'user_agent' => 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.10.229 Version/11.61',
    6.         'content' => $data
    7.     )
    8. ); 
     
  22. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Спасибо! ) Осталась последняя ошибка. Почему то ругается на строчку
    Код (Text):
    1. $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 />

    Помогите пожалуйста
     
  23. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Ну, если тот удалённый сервер хочет получить от тебя строку в формате JSON - то, видимо, в таком формате и надо ему её передавать :)

    Вместо этого:
    Код (PHP):
    1. $data = array();
    2. foreach($_POST as $k => $v)
    3.     $data[] = $k . '=' . $v;
    4. $data = implode('&', $data); 
    Написать:
    Код (PHP):
    1. $data = json_encode($_POST); 
    Только неизвестным остаётся, в какую POST-переменную эту строку засунуть. Вообще, недостаточно информации. Нужно точно знать, что и в каком виде хочет получить от тебя тот сервер, к которому ты делаешь запрос, чтобы вернуть тебе правильный ответ. Мы же тут понятия об этом не имеем и "гадаем на кофейной гуще". Если бы была чёткая информация по этому поводу - всё решилось бы ещё несколько постов назад.
     
  24. Serjuk

    Serjuk Активный пользователь

    С нами с:
    31 окт 2011
    Сообщения:
    44
    Симпатии:
    0
    Если написать :
    Код (Text):
    1. $data = json_encode($_POST); 
    то будет ошибка:
    И заголовок сообщения почему то поменялся, теперь он html/text
    Надо :
    Json объект вида
    {
    "FirstName":"Oleg",
    "LastName":"Ivanov",
    ...
    }
    Заголовок запроса и ответа: application/json.
     
  25. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Что-то ты там где-то напутал, наверно, пока менял. Должно было получиться такое:

    Код (PHP):
    1. <?php
    2. if(!count($_POST))
    3.     die('[0,"Неверный запрос"]');
    4.  
    5. $data = json_encode($_POST);
    6.  
    7. // Тут прописываем адрес, по которому будем обращаться к удалённому серверу
    8. $url = 'http://site.com/path';
    9.  
    10. $options = array(
    11.     'http' => array(
    12.         'method' => 'POST',
    13.         'header' => 'Content-type: application/json',
    14.         'user_agent' => 'Opera/9.80 (Windows NT 5.1; U; ru) Presto/2.10.229 Version/11.61',
    15.         'content' => $data
    16.     )
    17. );
    18. $context = stream_context_create($options);
    19. $out = file_get_contents($url, false, $context);
    20.  
    21. header('Content-type: application/json');
    22. header('Cache-Control: no-store, no-cache, must-revalidate');
    23. header('Cache-Control: post-check=0, pre-check=0', false);
    24. echo($out);
    25. ?>
    Никаких parse error тут не должно быть. Но и заработает это врядли - и я написал выше почему. Никто не знает, какой запрос ожидает получить от тебя удалённый сервер.