react node funciona example ejemplos como javascript google-chrome-extension http2 fetch-api

javascript - funciona - node-fetch



¿Cómo puedo inhabilitar la inserción del servidor HTTP/2 cuando uso fetch? (1)

Estoy escribiendo una aplicación básica en Javascript que utiliza la nueva API de búsqueda. Aquí hay un ejemplo básico de la porción relevante del código:

function foo(url) { const options = {}; options.credentials = ''omit''; options.method = ''get''; options.headers = {''Accept'': ''text/html''}; options.mode = ''cors''; options.cache = ''default''; options.redirect = ''follow''; options.referrer = ''no-referrer''; options.referrerPolicy = ''no-referrer''; return fetch(url, options); }

Al realizar una solicitud de recuperación, ocasionalmente veo errores en la consola que se parecen a los siguientes:

Se negó a cargar el script ''<url>'' porque viola la siguiente directiva de Política de seguridad de contenido ...

Después de leer y aprender sobre HTTP / 2, parece que este mensaje aparece porque la respuesta está rechazando un script precargado. Usando devtools, puedo ver el siguiente encabezado en la respuesta:

enlace: <path-to-script>; rel = precarga; como = script

Aquí está la parte relevante del archivo manifest.json de mi extensión de Chrome:

{ "content_security_policy": "script-src ''self''; object-src ''self''" }

Aquí está la documentación sobre el formato manifest.json de Chrome y cómo se aplica la política de seguridad de contenido a las recuperaciones realizadas por la extensión: https://developer.chrome.com/extensions/contentSecurityPolicy

Hice algunas pruebas y pude determinar que este mensaje de error ocurre durante la búsqueda, no más tarde al analizar el texto de respuesta. No hay ningún problema cuando un elemento de script se carga en un DOM en vivo, todo esto sucede en el momento de la búsqueda.

Lo que no pude encontrar en mi investigación fue cómo evitar este comportamiento. Parece que en la prisa por dar soporte a esta gran nueva característica, las personas que hicieron HTTP / 2 y fetch no consideraron el caso de uso en el que no estoy recuperando la página remota con el propósito de mostrarla o cualquiera de sus recursos asociados como css / imagen / guión. Yo (la aplicación) nunca usaré ningún recurso asociado; Sólo el contenido del recurso en sí.

En mi caso de uso, este empuje (1) es un desperdicio total de recursos y (2) ahora está causando que en la consola aparezca un mensaje realmente molesto e inductor de estrés.

Dicho esto, aquí está la pregunta con la que me gustaría recibir ayuda: ¿Hay alguna forma de indicar al navegador, mediante un manifiesto o un script, que no me interesa el empuje de HTTP / 2? ¿Hay un encabezado que puedo configurar para la solicitud de recuperación que le dice al servidor web que no responda con push? ¿Hay alguna configuración de CSP que pueda usar en mi manifiesto de aplicación que de alguna manera provoque una respuesta de no empujar?

He mirado https://w3c.github.io/preload/ sección 3.3, no fue de mucha ayuda. Veo que puedo enviar encabezados como Link: </dont/want/to/push/this>; rel=preload; as=script; nopush Link: </dont/want/to/push/this>; rel=preload; as=script; nopush Link: </dont/want/to/push/this>; rel=preload; as=script; nopush El problema es que aún no sé qué encabezados de enlace se incluirán en la respuesta, y no estoy seguro si Fetch incluso permite establecer encabezados de enlace en la solicitud inicial. Me pregunto si puedo enviar algún tipo de solicitud que pueda ver los encabezados de enlace en la respuesta, pero los evita, luego enviar una solicitud de seguimiento que agregue todos los encabezados nopush apropiados.

Aquí hay un caso de prueba simple para reproducir el problema:

  1. Obtén una versión dev de la última versión o la última versión de Chrome.
  2. Crear una carpeta de extensión
  3. Crear manifiesto con CSP similar
  4. Cargar la extensión como desempaquetado en cromo
  5. Abre la página de fondo para la extensión en devtools
  6. En la consola, escriba fetch ('' https://www.yahoo.com '').
  7. Examine el mensaje de error resultante que aparece en la consola: Se negó a cargar el script '' https://www.yahoo.com/sy/rq/darla/2-9-20/js/g-r-min.js '' porque viola la siguiente directiva de política de seguridad de contenido: "script-src ''self''".

Notas adicionales:

  • No quiero usar un servidor proxy. Una explicación clara de por qué esa sería mi única opción sería una respuesta aceptable.
  • No conozco las direcciones URL que se buscarán en el momento de configurar el CSP.
  • Consulte https://tools.ietf.org/html/rfc7540#section-6.5.1 que indica en la parte relevante que "SETTINGS_ENABLE_PUSH (0x2): esta configuración se puede usar para deshabilitar el empuje del servidor (Sección 8.2). Un punto final NO DEBE envíe un marco PUSH_PROMISE si recibe este conjunto de parámetros a un valor de 0. " ¿Hay alguna forma de especificar esta configuración desde el script o el manifiesto o se incluye en Chrome?

Después de seguir con su caso de prueba, pude resolver este (ejemplo del) problema de la siguiente manera, aunque no sé si se aplica a todos los casos más generales:

  1. Use chrome.webRequest para interceptar respuestas a las solicitudes de la extensión.
  2. Utilice la forma de bloqueo de onHeadersRecieved para eliminar los encabezados que contienen rel=preload
  3. Permitir que la respuesta proceda con los encabezados actualizados.

Debo admitir que pasé mucho tiempo tratando de averiguar por qué esto parecía funcionar, ya que no creo que quitar los encabezados de enlace deba funcionar en todos los casos. Pensé que Server Push solo comenzaría a insertar archivos después de que se envíe la solicitud.

Como mencionó en su nota adicional sobre SETTINGS_ENABLE_PUSH gran parte de esto está de hecho integrado en Chrome y oculto a nuestra vista. Si quieres profundizar más, encontré los detalles en chrome://net-internals/#http2 . Quizás Chrome está matando los archivos enviados por Server Push que no tienen un encabezado de enlace correspondiente en la respuesta inicial.

Esta solución depende de los Docs chrome.webRequest

El script de fondo de la extensión:

let trackedUrl; function foo(url) { trackedUrl = url; const options = {}; options.credentials = ''omit''; options.method = ''get''; options.headers = { ''Accept'': ''text/html'' }; options.mode = ''cors''; options.cache = ''default''; options.redirect = ''follow''; options.referrer = ''no-referrer''; options.referrerPolicy = ''no-referrer''; return fetch(url, options) } chrome.webRequest.onHeadersReceived.addListener(function (details) { let newHeaders; if (details.url.indexOf(trackedUrl) > -1) { newHeaders = details.responseHeaders.filter(header => { return header.value.indexOf(''rel=preload'') < 0; }) } return { responseHeaders: newHeaders }; }, { urls: [''<all_urls>''] }, [''responseHeaders'', ''blocking'']);

El manifiesto de la extensión:

{ "manifest_version": 2, "name": "Example", "description": "WebRequest Blocking", "version": "1.0", "browser_action": { "default_icon": "icon.png" }, "background": { "scripts": [ "back.js" ] }, "content_security_policy": "script-src ''self''; object-src ''self''", "permissions": [ "<all_urls>", "background", "webRequest", "webRequestBlocking" ] }

Notas adicionales:

  • Solo estoy ingenuamente limitando esto a la última url de solicitud de la extensión, hay webRequest.requestFilters en chrome.webRequest que puedes consultar here

  • Probablemente también querrás ser mucho más específico sobre los encabezados que eliminas. Siento que quitar todos los enlaces tendrá algunos efectos adicionales.

  • Esto evita proxys y no requiere configurar un encabezado de enlace en la solicitud.

  • Esto hace que para una extensión bastante poderosa, personalmente evito las extensiones con permisos como <all_urls> , y espero que puedas limitar el alcance.

  • No probé los retrasos causados ​​por el bloqueo de las respuestas para eliminar encabezados.