формировать POST в iframe, не затрагивая историю

Можно ли отправить форму внутри iframe, не затрагивая историю браузера?

Я реализовал отправку междоменного POST-запроса. Он использует Javascript для создания и отправки формы внутри iframe. Это работает, но каждый запрос добавляет элемент в историю браузера.

Кто-нибудь знает способ обойти это? Я пытался создать iframe с помощью innerHTML и createElement. Я пока не увидел разницы.

PS. Я бы хотел использовать XMLHttpRequest ("Ajax"), но он не поддерживает отправку данных между доменами. И я хотел бы использовать GET вместо публикации, но мне нужно отправить более 2 КБ данных.

Вот одна из версий моего кода. Я пробовал много вариантов и искал повсюду, но я не могу найти решение, которое не влияет на историю браузера. Я считаю, что это невозможно - кто-нибудь может это подтвердить?

<html>

<head>
  <script type="text/javascript">
    function submit(params) {

      var div = document.createElement('div');
      div.innerHTML = '<iframe height="50" width="50"></iframe>';
      document.body.appendChild(div);

      var iframe = div.firstChild;
      var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
      iframeDocument.open();
      iframeDocument.close();

      var form = iframeDocument.createElement('form');
      iframeDocument.body.appendChild(form);
      form.setAttribute('action', 'http://some-other-domain.com/submit-here');
      form.setAttribute('method', 'POST');

      for (param in params) {
        var field = iframeDocument.createElement('input');
        field.setAttribute('type', 'hidden');
        field.setAttribute('name', param);
        field.setAttribute('value', params[param]);
        form.appendChild(field);
      }
      form.submit();
    }

    window.onload = function() {
      document.getElementById('button').onclick = function() {
        submit({
          'x' : 'Some Value',
          'y' : 'Another Value',
          'z' : new Date().getTime()
        });
      }
    }
  </script>
</head>

<body>
  <h1>Example of using Javascript to POST across domains...</h1>
  <input id="button" type="button" value="click to send">
</body>

</html>

person Brian    schedule 20.10.2009    source источник
comment
Почему вы не можете просто использовать ajax для отправки формы? Это помешает вам перезагружать какие-либо страницы, что должно освободить вашу историю. Я что-то пропустил?   -  person Alex Sexton    schedule 21.10.2009
comment
Мне нужно опубликовать кросс-домены. Ajax (XMLHttpRequest) POST не поддерживает отправку данных в домен, который отличается от главной страницы.   -  person Brian    schedule 21.10.2009
comment
Я думаю, что вы действительно можете отправить запрос POST в ajax. Смотрите мой обновленный ответ. Я надеюсь, что это помогает.   -  person Robert Massaioli    schedule 21.10.2009
comment
Я думаю, что это невозможно .. (даже если бы это было как-то, это, вероятно, было бы специфично для браузера).   -  person hasen    schedule 21.10.2009
comment
Брайан, у вас есть окончательный пример кода, который вы использовали для решения этой проблемы, которым вы могли бы поделиться? Спасибо   -  person    schedule 15.01.2011
comment
Окончательное решение заключалось в следующем: 1) вставить iframe, размещенный в моем домене, 2) использовать хак window.name для отправки данных со страницы хоста (в другом домене) на iframe и 3) отправить запрос Ajax POST на сервер на мой домен.   -  person Brian    schedule 18.11.2011


Ответы (5)


Работает ли использование JS для добавления IFRAME, чей src размещен на вашем сайте (домен, на который сторонний скрипт должен отправлять данные?) Этот IFRAME может включать в себя необходимый Javascript для создания XMLHttpRequest к вашему/его домен. А что касается получения фактических данных в этот IFRAME со стороннего сайта - попробуйте: http://softwareas.com/cross-domain-communication-with-iframes . Это довольно умное решение, включающее изменение идентификаторов фрагментов (#something) в конце URL-адреса IFRAME, который затем можно прочитать через JS внутри IFRAME.

Тоже предположение, но если вы примените это прошлое решение SO к аналогичной проблеме с историей (используя location.replace) для вышеизложенного, мы надеемся, что это позволит вам выполнить часть изменения привязки, не нарушая стек истории.

person Ben Regenspan    schedule 21.10.2009
comment
Очень интересно! Мне потребуется некоторое время на расследование, но это может быть то, что я искал. Спасибо! - person Brian; 21.10.2009
comment
Это полностью сработало, и теперь я могу использовать Ajax в iframe. - person Brian; 22.10.2009
comment
Рад слышать это! Спасибо, что сообщили здесь, я вижу, что, скорее всего, мне придется использовать этот подход в ближайшем будущем. - person Ben Regenspan; 22.10.2009
comment
Возможно, я сказал слишком рано. Safari не записывает историю iframe, в отличие от других браузеров. Все еще работаю над этим. tagneto.org/blogcode/xframe/ui.html - person Brian; 23.10.2009
comment
Окончательное решение заключалось в следующем: 1) вставить iframe, размещенный в моем домене, 2) использовать хак window.name для отправки данных со страницы хоста (в другом домене) на iframe и 3) отправить запрос Ajax POST на сервер на мой домен. - person Brian; 23.03.2010

Вы должны использовать AJAX POST.

Обычно при создании приложений Ajax используется только метод GET. Но есть несколько случаев, когда POST необходим при создании ajax-запроса. Это может быть по нескольким причинам. Например, запрос POST считается более безопасным, чем запрос GET, поскольку создать запрос POST относительно сложнее, чем запрос GET.

Вызовы AJAX не сохраняются в истории просмотров.

person Esteban Küber    schedule 20.10.2009
comment
Полезные ссылки, вы должны перейти по ним, но не так много описания. - person Robert Massaioli; 21.10.2009
comment
@Shhnap: это была немного тяжелая любовь. Во всяком случае, добавил соответствующую информацию, которая нужна Брайану. - person Esteban Küber; 21.10.2009
comment
Ajax POST не работает между доменами. Страница будет размещена на одном домене и будет отправлять данные на другой. Кроме того, размер данных превышает 2 КБ, поэтому GET не сработает. - person Brian; 21.10.2009

Если ваш сервер может запускать код, вы, вероятно, могли бы выполнить ajax-запрос к «прокси-странице» на вашем сервере, который затем сам запустит запрос на удаленном сервере и вернет результаты на вашу страницу.

person David Thibault    schedule 21.10.2009
comment
Я не запускаю хост-домен. Я запускаю домен, на который мне нужно отправить данные. Хост-страница будет включать мой код в качестве стороннего скрипта. Однако, спасибо. - person Brian; 21.10.2009
comment
Понимаю. Быстрый поиск показывает, что это можно сделать с помощью flash-прокси (см. blog.monstuff.com/ архивы/000280.html). Если вы не хотите идти по этому пути, я не уверен, что это возможно. - person David Thibault; 21.10.2009
comment
Flash немного тяжеловат, но это хорошая идея. Я обязательно это учту. - person Brian; 21.10.2009
comment
На самом деле, вес вспышки не имеет значения. Причина, по которой я не могу его использовать, в том, что он не работает на iPhone. - person Brian; 23.10.2009

(?) Я не вижу веских причин, по которым вы используете элемент iframe. (Поскольку это был более старый вопрос, возможно, вы тестировали HTML 4 1997 года выпуска. Кстати, игнорируйте «XML» в имени объекта — это перенос с 2000 года и более поздние версии [X] HTML — без XML требуется.)

Если вы отправите HTTP-запрос из JavaScript, а не из элементов документа, в историю ничего не будет добавлено.

function httpPost(body) {
  req = new XMLHttpRequest();
  req.open("POST", "/submit-here", true/*async*/);
     // or "http://some-other-domain.com/submit-here"
  req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  req.send(body);
}
window.onload = function() {
   document.getElementById('button').onclick = function() {
      httpPost('x=Some+Value&y=Another+Value&z=' + new Date().getTime());
      // or use a buildQuery function, JQuery formSerialize, etc. to create the body
   }
}

Я использую символические ссылки ("ln -s..."), чтобы формы можно было отправлять в тот же домен, что и документ, поэтому в моем случае "/submit-here" является относительным URI.

person Rob at TVSeries.com    schedule 17.02.2012

Как указано в комментариях, решение этой проблемы заключается в том, чтобы сделать запрос AJAX с вашего сервера вместо того, чтобы пытаться отправить страницу в обычном режиме. У W3schools действительно хорошее введение в AJAX, которое вы можете найти здесь: http://www.w3schools.com/Ajax/Default.Asp

По сути, AJAX использует javascript для отправки запроса на сервер и отображает ответ, а поскольку это происходит с использованием Pure javascript, страница не перезагружается, и история вообще не затрагивается. Что звучит как именно то, что вы хотите.

Изменить: AJAX не может отправлять данные.

Я действительно думаю, что может; или, по крайней мере, есть некоторые обходные пути, позволяющие публиковать данные. Посмотреть здесь:

http://www.captain.at/howto-ajax-form-post-request.php

Кажется, это делается довольно просто. Смотрите код внизу страницы. Конкретно:

http_request.onreadystatechange = alertContents;
http_request.open('POST', url, true);
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
person Robert Massaioli    schedule 20.10.2009
comment
XMLHttpRequest поддерживает POST, но не поддерживает отправку данных между доменами. - person Brian; 21.10.2009