Google AMP: Cors

En este capítulo, intentaremos comprender CORS en AMP. Antes de profundizar en los detalles, comprendamos los conceptos básicos de CORS y su utilidad.

¿Qué es CORS?

CORS son las siglas de Cross Origin Resource Sharing. CORS es un proceso que necesita datos de encabezado HTTP adicionales para decirle al navegador si la solicitud realizada a la URL por la página web que se ejecuta en el origen de xyz.com debe tener permiso para acceder a los datos de la URL solicitada. Hacemos muchas solicitudes http desde la página web y para eso necesitamos tener CORS en su lugar para obtener los datos requeridos.

Cuando hacemos una solicitud http a un servidor diferente al host, lo llamamos solicitud de origen cruzado, lo que significa que el dominio, el protocolo y el puerto son diferentes del origen del host. En tal caso, debe haber un permiso de la URL solicitada para acceder a los datos; significa GET / PUT / POST / DELETE solicitud realizada.

Estos datos adicionales están disponibles en el encabezado del navegador para la llamada de solicitud http realizada. Este paso de permiso es básicamente necesario por razones de seguridad para que ninguna página web pueda crear u obtener datos de otro dominio sin el permiso requerido.

El encabezado del navegador debe tener detalles como Access-Control-Allow-Origin que puede tener valores como se muestra a continuación -

Access-Control-Allow-Origin : *

Tener un valor * en el encabezado de la URL de la solicitud significa que le dice a los navegadores que permitan solicitar datos de cualquier origen para acceder al recurso.

Access-Control-Allow-Origin: https://www.example.com

Tener el valor anterior le indica al navegador que la solicitud realizada desde la página web www.example.com solo podrá obtener los datos de la URL solicitada.

La configuración del servidor para CORS debe realizarse teniendo en cuenta cómo se utilizarán los datos que se comparten. Dependiendo de eso, los encabezados necesarios deben establecerse en el lado del servidor.

Ahora que sabemos qué es CORS, demos un paso más. En el caso de amp, tenemos componentes como amp-form, amp-list que usa extremos http para cargar datos dinámicamente.

En el caso de las páginas de amplificador, incluso si la solicitud http se realiza desde el mismo origen, necesitamos tener la configuración CORS en su lugar. Aquí surgen preguntas: ¿por qué deberíamos tener CORS habilitado incluso si la solicitud y la respuesta provienen del mismo origen? Técnicamente, no necesitamos CORS habilitado en tal caso porque estamos solicitando y mostrando datos para el mismo dominio, origen, etc.

Amp tiene una función llamada almacenamiento en caché que se agrega para que los datos lleguen más rápido al usuario que visita la página. En caso de que el usuario ya haya visitado la página, los datos se almacenarán en caché en el cdn de Google, el siguiente usuario obtendrá los datos de la caché.

Los datos se almacenan en el extremo del amplificador, que ahora tiene un dominio diferente. Cuando el usuario hace clic en cualquier botón para obtener datos nuevos, la URL de la caché de amp se compara con el dominio de la página web para obtener los datos nuevos. Aquí ahora, si el CORS no está habilitado, ya que se ocupa de la URL almacenada en caché de amp y el dominio de la página web, la solicitud no será válida y fallará para el permiso CORS. Esta es la razón por la que necesitamos tener CORS habilitado incluso para el mismo origen en el caso de páginas de amplificador.

Aquí se muestra un ejemplo práctico de cómo trabajar con formularios que tienen CORS habilitado:

<!doctype html>
<html amp lang = "en">
   <head>
      <meta charset = "utf-8">
      <script async src = "https://cdn.ampproject.org/v0.js">
      </script>
      <title>Google AMP - Form</title>
      <link rel = "canonical" href = "ampform.html">
      <meta name = "viewport" content = "width = device-width,
      minimum-scale = 1,initial-scale = 1">
      
      <style amp-boilerplate>
         body{
            -webkit-animation:
            -amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:
            -amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:
            -amp-start 8s steps(1,end) 0s 1 normal both;animation:
            -amp-start 8s steps(1,end) 0s 1 normal both
         }
         @-webkit-keyframes 
         -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes 
         -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes 
         -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes 
         -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes 
         -amp-start{from{visibility:hidden}to{visibility:visible}}
      </style>
      <noscript>
         <style amp-boilerplate>
            body{
               -webkit-animation:none;
               -moz-animation:none;
               -ms-animation:none;
               animation:none}
         </style>
      </noscript>
      <script async custom-element = "amp-form" 
         src = "https://cdn.ampproject.org/v0/amp-form-0.1.js">
      </script>
      <script async custom-template = "amp-mustache" 
         src = "https://cdn.ampproject.org/v0/amp-mustache-0.2.js">
      </script>
      <style amp-custom>
         form.amp-form-submit-success [submit-success],
         form.amp-form-submit-error [submit-error]{
            margin-top: 16px;
         }
         form.amp-form-submit-success [submit-success] {
            color: white;
            background-color:gray;
         }
         form.amp-form-submit-error [submit-error] {
            color: red;
         }
         form.amp-form-submit-success.hide-inputs > input {
            display: none;
         }
      </style>
   </head>
   <body>
      <h3>Google AMP - Form</h3>
      <form 
         method = "post" 
         class = "p2" 
         action-xhr = "submitform.php" 
         target = "_top">
            <p>AMP - Form Example</p>
            <div>
               <input 
                  type = "text" 
                  name = "name" 
                  placeholder = "Enter Name" required>
               <br/>
               <br/>
               <input 
                  type = "email" 
                  name = "email" 
                  placeholder = "Enter Email" 
                  required>
               <br/>
               <br/>
            </div>
            <input type = "submit" value = "Submit">
            <div submit-success>
               <template type = "amp-mustache">
                  Form Submitted! Thanks {{name}}.
               </template>
            </div>
            <div submit-error>
               <template type = "amp-mustache">
                  Error! {{name}}, please try again.
               </template>
            </div>
      </form>
   </body>
</html>

submitform.php

<?php
   if(!empty($_POST)){
      $domain_url = (isset($_SERVER['HTTPS']) ? "https" : "http") . 
         "://$_SERVER[HTTP_HOST]";
      header("Content-type: application/json");
      header("AMP-Access-Control-Allow-Source-Origin: " . $domain_url);
      header("Access-Control-Expose-Headers: 
         AMP-Access-Control-Allow-Source-Origin");
      $myJSON = json_encode($_POST);
      echo $myJSON;
   }
?>

Salida

Los detalles de los encabezados de respuesta agregados a submitform.php -

Para que el formulario funcione, necesitamos agregar encabezados como access-control-expose-headers con el valor AMP-Access-Control-Allow-Source-Origin y amp-access-control-allow-source-origin - http://localhost:8080.

Aquí estamos usando un archivo php y apache es el servidor utilizado. En el archivo php, hemos agregado los encabezados requeridos como se muestra a continuación:

<?php
   if(!empty($_POST)){
      $domain_url = (isset($_SERVER['HTTPS']) ? "https" : "http") .
         "://$_SERVER[HTTP_HOST]";
      header("Content-type: application/json");
      header("AMP-Access-Control-Allow-Source-Origin: " . $domain_url);
      header("Access-Control-Expose-Headers: 
         AMP-Access-Control-Allow-Source-Origin");
      $myJSON = json_encode($_POST);
      echo $myJSON;
   }
?>

Cuando se agregan los encabezados requeridos, el origen http://localhost:8080 se le permitirá interactuar y recuperar los datos.