Tengo una aplicación cliente de navegador basada en JavaScript que se ocupa de una gran cantidad de datos estatales. Ocasionalmente, esos datos deben reunirse en un objeto bien formado y volcarse a una nueva ventana que acepta esos datos para su procesamiento.

Una solución que tengo que ya funciona es la siguiente: cuando los datos deben enviarse, la URL de destino y los datos se pasan a lo que efectivamente es esta función, que aprovecha un elemento form virtual que envía los datos:

function sendJson(targetUrl, jsonData) {
    let form = document.createElement("form");
    form.method = "POST";
    form.action = targetUrl;
    form.target = '_blank';

    let element = document.createElement("input");
    element.value = JSON.stringify(jsonData);
    element.name = 'json';
    form.appendChild(element);

    document.body.appendChild(form);
    form.submit();
    form.parentNode.removeChild(form);
}

Esto agrupa efectivamente los datos bien formados en un solo campo de formulario y lo vuelve a codificar como application/x-www-form-urlencoded. Un script PHP aguarda en el otro extremo que extrae los datos más o menos así:

$json_data = json_decode($_POST['json'], true);

Este método tiene algunas ventajas que me gustan, a saber:

  • La nueva ventana tiene una URL distinta de la principal.
  • La solicitud de red pertenece a la nueva ventana, no a la ventana principal que la abrió.

Esto significa que puedo volver a POSTAR la misma solicitud una y otra vez simplemente actualizando la ventana y reenviando las variables POST, lo cual es útil.

Lo que no me gusta es que los datos a través del cable ahora están codificados en URL. Las herramientas de depuración de mi red que muestran nítidamente los datos jerárquicos JSON no pueden analizarlos y, en su lugar, simplemente eliminan lo que es ahora: una sola cadena excesivamente larga llena de símbolos codificados. Si alguna vez necesito inspeccionar esto, tengo que ejecutarlo a través de un decodificador de URL y un embellecedor JSON, lo que encuentro increíblemente inconveniente. Sería muy beneficioso si pudiera enviar la solicitud como application/json en lugar de application/x-www-form-urlencoded.

Entonces, en su lugar, probé una solución como esta, utilizando window.open():

function sendJson(targetUrl, jsonData) {
    fetch(targetUrl, {
        method: 'POST',
        headers: {
            'Content-type': 'application/json',
            'Accept': 'text/html'
        },
        body: JSON.stringify(jsonData)
    })
        .then(response => response.text())
        .then(text => {
            let newWin = window.open(targetUrl, '_blank');
            newWin.document.open();
            newWin.document.write(text);
            newWin.document.close();
        });
}

Y PHP en el otro lado lo recoge como:

$json_data = json_decode(file_get_contents('php://input'), true);

Ahora el JSON está revisando el cable en su formato nativo, resolviendo el problema de codificación. Pero ahora la llamada a window.document.open() restablece la URL de la nueva ventana a la URL del padre. Si se actualiza la nueva ventana, se redirige a la ventana principal. E incluso si ese no fuera el caso, no hay datos POST para actualizar, ya que la solicitud "pertenece" a la ventana principal. Los datos simplemente se transmitieron al padre y se escribieron en la nueva ventana manualmente.

Lo que me queda son dos soluciones funcionales, pero menos que ideales. Mi pregunta es: ¿existe una solución que me brinde todas las funciones que deseo?

  • Implementación pura de JavaScript (sin bibliotecas, preferiblemente sin trucos DOM)
  • POST datos enviados como application/json por cable
  • La solicitud se abre en una nueva ventana / pestaña
  • La nueva ventana apunta a una URL distinta de la ventana principal
  • La nueva ventana se puede volver a publicar actualizando esa ventana
0
Fawfulcopter 25 ago. 2020 a las 20:32

1 respuesta

La mejor respuesta

No.

Solo fetch y XMLHttpRequest se pueden usar para realizar una solicitud con un cuerpo application/json, y la respuesta a esas solo se puede manejar con JS.

1
Quentin 25 ago. 2020 a las 17:34