Postar dados no JsonP

É possível postar dados no JsonP? Ou todos os dados precisam ser passados ​​na querystring como uma solicitação GET?

Eu tenho muitos dados que preciso enviar para o serviço, entre domínios e é muito grande para enviar através da querystring

Quais são as opções para contornar isso?

Não é possível fazer um POST asynchronous para um serviço em outro domínio, devido à limitação (bastante sensata) da mesma política de origem . O JSON-P só funciona porque você pode inserir tags no DOM, e elas podem apontar para qualquer lugar.

É claro que você pode tornar uma página em outro domínio a ação de um formulário regular POST.

Edit : Há alguns hacks interessantes lá fora, se você estiver disposto a se esforçar para inserir oculto e se preocupar com suas propriedades.

Se você precisar enviar muitos dados entre domínios. Eu costumo criar um serviço que você pode chamar em duas etapas:

  1. Primeiro o cliente faz um FORMULÁRIO de envio (pós domínio permitido). O serviço armazena a input na session no servidor (usando o GUID como chave). (o cliente cria um GUID e o envia como parte da input)

  2. Em seguida, o cliente faz uma injeção de script normal (JSONP) como um parâmetro que você usa o mesmo GUID usado na postagem do FORM. O serviço processa a input da session e retorna os dados no formato JSONP normal. Depois disso, a session é destruída.

Isso, claro, depende de que você escreva o backend do servidor.

Eu sei que isso é uma séria necromancia, mas eu pensei em postar minha implementação do JSONP POST usando jQuery, que estou usando com sucesso para o meu widget JS (isso é usado para registro de clientes e login):

Basicamente, estou usando uma abordagem de IFrame, como sugerido na resposta aceita. O que estou fazendo de diferente é depois de enviar o pedido, estou assistindo, se o formulário puder ser acessado no iframe, usando um timer. Quando o formulário não pode ser alcançado, significa que o pedido foi devolvido. Então, estou usando uma solicitação JSONP normal para consultar o status da operação.

Espero que alguém ache útil. Testado em> = IE8, Chrome, FireFox e Safari.

 function JSONPPostForm(form, postUrl, queryStatusUrl, queryStatusSuccessFunc, queryStatusData) { var tmpDiv = $('
'); form.parent().append(tmpDiv); var clonedForm = cloneForm(form); var iframe = createIFrameWithContent(tmpDiv, clonedForm); if (postUrl) clonedForm.attr('action', postUrl); var postToken = 'JSONPPOST_' + (new Date).getTime(); clonedForm.attr('id', postToken); clonedForm.append(''); clonedForm.attr('id', postToken ); clonedForm.submit(); var timerId; var watchIFrameRedirectHelper = function() { if (watchIFrameRedirect(iframe, postToken )) { clearInterval(timerId); tmpDiv.remove(); $.ajax({ url: queryStatusUrl, data: queryStatusData, dataType: "jsonp", type: "GET", success: queryStatusSuccessFunc }); } } if (queryStatusUrl && queryStatusSuccessFunc) timerId = setInterval(watchIFrameRedirectHelper, 200); } function createIFrameWithContent(parent, content) { var iframe = $(''); parent.append(iframe); if (!iframe.contents().find('body').length) { //For certain IE versions that do not create document content... var doc = iframe.contents().get()[0]; doc.open(); doc.close(); } iframe.contents().find('body').append(content); return iframe; } function watchIFrameRedirect(iframe, formId) { try { if (iframe.contents().find('form[id="' + formId + '"]').length) return false; else return true; } catch (err) { return true; } return false; } //This one clones only form, without other HTML markup function cloneForm(form) { var clonedForm = $('
'); //Copy form attributes $.each(form.get()[0].attributes, function(i, attr) { clonedForm.attr(attr.name, attr.value); }); form.find('input, select, textarea').each(function() { clonedForm.append($(this).clone()); }); return clonedForm; }

Bem, geralmente o JSONP é implementado adicionando uma tag ao documento de chamada, de modo que a URL do serviço JSONP seja o "src". O navegador busca fonte de script com uma transação HTTP GET.

Agora, se o seu serviço JSONP estiver no mesmo domínio que sua página de chamada, provavelmente você poderia remendar algo junto com uma simples $.ajax() . Se não estiver no mesmo domínio, não sei como isso seria possível.

Você poderia usar um proxy CORS usando este projeto . Ele direcionaria todo o tráfego para um endpoint em seu domínio e redirectia essa informação para um domínio externo. Como o navegador está registrando todas as solicitações para estar no mesmo domínio, podemos postar o JSON. NOTA: Isso também funciona com certificados SSL mantidos no servidor.

Há uma solução (hack) que fiz muitas vezes, você poderá postar com o JsonP. (Você será capaz de postar formulário, maior que 2000 caracteres do que você pode usar por GET)

Javascript do aplicativo cliente

 $.ajax({ type: "POST", // you request will be a post request data: postData, // javascript object with all my params url: COMAPIURL, // my backoffice comunication api url dataType: "jsonp", // datatype can be json or jsonp success: function(result){ console.dir(result); } }); 

JAVA:

 response.addHeader( "Access-Control-Allow-Origin", "*" ); // open your api to any client response.addHeader( "Access-Control-Allow-Methods", "POST" ); // a allow post response.addHeader( "Access-Control-Max-Age", "1000" ); // time from request to response before timeout 

PHP:

 header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST'); header('Access-Control-Max-Age: 1000'); 

Fazendo assim, você está abrindo seu servidor para qualquer solicitação de postagem, você deve ressegurar isso fornecendo ident ou outra coisa.

Com esse método, você também pode alterar o tipo de solicitação de jsonp para json, ambos funcionam, basta definir o tipo de conteúdo de resposta correto

jsonp

 response.setContentType( "text/javascript; charset=utf-8" ); 

json

 response.setContentType( "application/json; charset=utf-8" ); 

Por favor, não que seu servidor não respeite mais o SOP (mesma política de origem), mas quem se importa?

É possível, aqui está a minha solução:

Em seu javascript:

 jQuery.post("url.php",data).complete(function(data) { eval(data.responseText.trim()); }); function handleRequest(data){ .... } 

Em seu url.php:

 echo "handleRequest(".$responseData.")";