httpStream.js 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. export const httpStreamOutput = function(readStream, name, http, downloadFlag, cacheControl) {
  2. readStream.on('data', data => {
  3. http.response.write(data);
  4. });
  5. readStream.on('end', () => {
  6. // don't pass parameters to end() or it will be attached to the file's binary stream
  7. http.response.end();
  8. });
  9. readStream.on('error', (err) => {
  10. console.error(`Download stream error for file '${name}':`, err);
  11. http.response.statusCode = 404;
  12. http.response.end('not found');
  13. });
  14. if (cacheControl) {
  15. http.response.setHeader('Cache-Control', cacheControl);
  16. }
  17. // Set Content-Disposition header
  18. http.response.setHeader('Content-Disposition', getContentDisposition(name, http?.params?.query?.download));
  19. // Add security headers to prevent XSS attacks
  20. const isSvgFile = name && name.toLowerCase().endsWith('.svg');
  21. if (isSvgFile) {
  22. // For SVG files, add strict CSP to prevent script execution
  23. http.response.setHeader('Content-Security-Policy', "default-src 'none'; script-src 'none'; object-src 'none';");
  24. http.response.setHeader('X-Content-Type-Options', 'nosniff');
  25. http.response.setHeader('X-Frame-Options', 'DENY');
  26. }
  27. };
  28. /** will initiate download, if links are called with ?download="true" queryparam */
  29. const getContentDisposition = (name, downloadFlag) => {
  30. // Force attachment disposition for SVG files to prevent XSS attacks
  31. const isSvgFile = name && name.toLowerCase().endsWith('.svg');
  32. const forceAttachment = isSvgFile || downloadFlag === 'true';
  33. const dispositionType = forceAttachment ? 'attachment;' : 'inline;';
  34. const encodedName = encodeURIComponent(name);
  35. const dispositionName = `filename="${encodedName}"; filename=*UTF-8"${encodedName}";`;
  36. const dispositionEncoding = 'charset=utf-8';
  37. return `${dispositionType} ${dispositionName} ${dispositionEncoding}`;
  38. };