run route proyecto node crear app another node.js nginx amazon-s3 express fileserver

node.js - route - post express node



Servir archivos almacenados en S3 en la aplicaciĆ³n express/nodejs (4)

Con respecto a su segunda opción, debería poder configurar los encabezados de control de caché directamente en S3 .

Respecto a tu primera opción. ¿Has considerado asegurar tus imágenes de una manera diferente? Cuando almacena una imagen en S3, ¿no podría utilizar un nombre de archivo aleatorio y aleatorio? Sería bastante sencillo hacer que el nombre del archivo sea difícil de adivinar + de esta manera no tendrá problemas de rendimiento al ver las imágenes de nuevo.

Esta es la técnica de uso de facebook. Aún puede ver una imagen cuando se desconecta, siempre que conozca la URL.

Tengo aplicación donde las fotos de los usuarios son privadas. Almaceno las fotos (miniaturas también) en AWS s3. Hay una página en el sitio donde el usuario puede ver sus fotos (es decir, miniaturas). Ahora mi problema es cómo sirvo estos archivos. Algunas opciones que he evaluado son:

  • Sirviendo archivos desde CloudFront (o AWS) usando la generación de URL firmada. Pero el problema es que cada vez que el usuario actualiza la página, tengo que crear tantas URL firmadas nuevamente y cargarla. Por lo tanto, no podré almacenar las imágenes en el navegador, lo que hubiera sido una buena elección. ¿Hay alguna forma de hacerlo todavía en javascript? No puedo tener la validez de esas URL por más tiempo debido a problemas de seguridad. Y, en segundo lugar, dentro de ese período de tiempo, si alguien se apoderó de esa URL, puede ver el archivo sin ejecutar la autenticación desde la aplicación.
  • Otra opción es entregar el archivo desde mi propia aplicación Express después de transmitirlo desde los servidores S3. Esto me permite tener encabezados de caché http, por lo tanto habilitar el almacenamiento en caché del navegador. También se asegura de que nadie pueda ver un archivo sin estar autenticado. Idealmente, me gustaría transmitir el archivo y estoy alojando usando el proxy NGINX y retransmitiendo el otro lado de la transmisión a NGINX. Pero como veo, eso solo es posible si el archivo existe en los archivos del mismo sistema. Pero aquí tengo que transmitirlo y volver cuando termine la transmisión. No quiero almacenar los archivos localmente.

¿No puedo evaluar cuál de las dos opciones sería una mejor opción? Quiero redirigir tanto trabajo como sea posible a S3 o cloudfront, pero incluso utilizando URLs individuales, también hago la solicitud primero a mis servidores. También quiero características de almacenamiento en caché.

Entonces, ¿cuál sería la forma ideal de hacer? ¿Con las respuestas a las preguntas particulares relacionadas con esos métodos?


Me preocuparía usar la opción CloudFront si las fotos realmente necesitan permanecer privadas. Parece que tendrás mucha más flexibilidad para administrar tu propia política de seguridad. Creo que la configuración de nginx puede ser más compleja de lo necesario. Express debe proporcionarle un buen rendimiento trabajando como un proxy remoto donde utiliza la solicitud para obtener elementos de S3 y transmitirlos a los usuarios autorizados. Recomendaría encarecidamente echar un vistazo a Asset Rack, que utiliza firmas hash para habilitar el almacenamiento en caché permanente en el navegador. No podrá usar los Racks predeterminados porque necesita calcular el MD5 de cada archivo (¿quizás en la carga?) Que no puede hacer cuando se está transmitiendo. Pero dependiendo de su aplicación, podría ahorrar mucho esfuerzo para que los navegadores nunca necesiten recuperar las imágenes.


Si redirigirás al usuario a una url firmada usando 302 Found navegador 302 Found almacenará en caché la imagen resultante de acuerdo con su encabezado de cache-control y no la preguntará la segunda vez.

Para evitar que el navegador almacene en caché la url firmada, debe enviar el encabezado de Cache-Control junto con este:

Cache-Control: private, no-cache, no-store, must-revalidate

Por lo tanto, la próxima vez enviará una solicitud a la URL original y será redirigido a una nueva URL firmada.

Puede generar url firmado con knox usando el método signedUrl .

Pero no olvide configurar los encabezados adecuados para cada imagen cargada. Le recomendaría que use los encabezados Cache-Control y Expires , ya que algunos navegadores no admiten Cache-Control encabezado Cache-Control y Expires permite establecer solo un tiempo de caducidad absoluto.

Con la segunda opción (transmisión de imágenes a través de tu aplicación) tendrás un mejor control sobre la situación. Por ejemplo, podrá generar el encabezado Expires para cada respuesta de acuerdo con la fecha y la hora actuales.

Pero ¿qué pasa con la velocidad? Usar urls firmados tiene dos ventajas que pueden afectar la velocidad de carga de la página.

Primero, no sobrecargarás tu servidor. La generación de urls firmados es rápida, ya que simplemente está modificando sus credenciales de AWS. Y para transmitir imágenes a través de su servidor, deberá mantener muchas conexiones adicionales durante la carga de la página. De todos modos, no hará ninguna diferencia real a menos que su servidor esté cargado.

En segundo lugar, los navegadores mantienen solo dos conexiones paralelas por nombre de host durante la carga de la página. Por lo tanto, el navegador seguirá resolviendo las urls de imágenes en paralelo mientras las descarga. También evitará que la descarga de imágenes bloquee la descarga de cualquier otro recurso.

De todos modos, para estar absolutamente seguro de que debe ejecutar algunos puntos de referencia. Mi respuesta se basó en mi conocimiento de la especificación HTTP y en mi experiencia en el desarrollo web, pero nunca intenté mostrar imágenes de esa manera. Servir imágenes públicas con una larga vida útil de la memoria caché directamente desde S3 aumenta la velocidad de la página, creo que la situación no cambiará si lo hace a través de redirecciones.

Y debe tener en cuenta que la transmisión de imágenes a través de su servidor hará que todos los beneficios de Amazon CloudFront sean nulos. Pero mientras esté sirviendo contenido directamente desde S3, ambas opciones funcionarán bien.

Por lo tanto, hay dos casos en los que utilizar urls firmados debería acelerar su página:

  • Si tienes muchas imágenes en una sola página.
  • Si estás sirviendo imágenes usando CloudFront.

Si solo tiene unas pocas imágenes en cada página y las sirve directamente desde S3, probablemente no verá ninguna diferencia.

Actualización importante

Hice algunas pruebas y descubrí que estaba equivocado acerca del almacenamiento en caché. Es cierto que los navegadores almacenan en caché las imágenes a las que fueron redirigidos. Pero asocia la imagen almacenada en caché con la URL a la que se redirigió y no con la original. Por lo tanto, cuando el navegador carga la página por segunda vez, solicita la imagen del servidor nuevamente en lugar de recuperarla del caché. Por supuesto, si el servidor responde con la misma URL de redireccionamiento que respondió la primera vez, el navegador usará su caché, pero no es el caso de las URL firmadas.

Encontré que obligar al navegador a almacenar en caché la URL firmada, así como los datos que recibe, resuelve el problema. Pero no me gusta la idea de almacenar en caché la URL de redireccionamiento no válida. Quiero decir, si el navegador pierde la imagen de alguna manera, tratará de solicitarla nuevamente usando una URL no válida firmada del caché. Entonces, creo que no es una opción.

Y no importa si CloudFront sirve imágenes más rápido o si los navegadores limitan el número de descargas paralelas por nombre de host, la ventaja de usar el caché del navegador supera todas las desventajas de canalizar imágenes a través de su servidor.

Y parece que la mayoría de las redes sociales resuelven el problema con imágenes privadas ocultando sus URL reales detrás de algunos proxies privados. Entonces, almacenan todo su contenido en servidores públicos, pero no hay manera de obtener una url para una imagen privada sin autorización. Por supuesto, si abres la imagen privada en una nueva pestaña y le envías la url a tu amigo, él también podrá ver la imagen. Entonces, si no es una opción para ti, entonces será mejor para ti usar la solución de Jonathan Ong .


Simplemente lo transmitiría desde S3. Es muy fácil, y las URL firmadas son mucho más difíciles. solo asegúrese de configurar los encabezados de content-length y content-type content-length cuando cargue las imágenes a S3.

var aws = require(''knox'').createClient({ key: '''', secret: '''', bucket: '''' }) app.get(''/image/:id'', function (req, res, next) { if (!req.user.is.authenticated) { var err = new Error() err.status = 403 next(err) return } aws.get(''/image/'' + req.params.id) .on(''error'', next) .on(''response'', function (resp) { if (resp.statusCode !== 200) { var err = new Error() err.status = 404 next(err) return } res.setHeader(''Content-Length'', resp.headers[''content-length'']) res.setHeader(''Content-Type'', resp.headers[''content-type'']) // cache-control? // etag? // last-modified? // expires? if (req.fresh) { res.statusCode = 304 res.end() return } if (req.method === ''HEAD'') { res.statusCode = 200 res.end() return } resp.pipe(res) }) })