node.js - 在已部署的应用程序上播放来自 s3 的文件时出现跨源资源策略问题

标签 node.js reactjs amazon-s3 cors cross-origin-resource-policy

我在 Heroku 上部署了一个应用程序,可以播放音频文件。你可以在这里查看 https://telecurve.herokuapp.com/manage .在我在 Heroku 中播放文件没有问题之前,但在我修改了 server.js 文件之后(我的应用程序是一个 Express 应用程序,它部署了一个内置的 Create React 应用程序),我收到了这个错误。您可以尝试播放音频文件并查看响应。但是,我仍然可以使用下载按钮从 s3 下载文件并且没有问题。
这是一些相关的代码:

server.js

    require('rootpath')();
    const path = require('path');
    const express = require('express');
    const app = express();
    const bodyParser = require('body-parser');
    const cookieParser = require('cookie-parser');
    const cors = require('cors');
    
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    app.use(cookieParser());
    
    // Have Node serve the files for our built React app
    app.use(express.static(path.resolve(__dirname, 'build')));
    
    // allow cors requests from any origin and with credentials
    app.use(cors({ origin: (origin, callback) => callback(null, true), credentials: true }));
    
   //change added that caused issues with the playing mechanism. Needed these headers for another 
    app.use(function(req, res, next) {
      res.header("Cross-Origin-Embedder-Policy", "require-corp");
      res.header("Cross-Origin-Opener-Policy", "same-origin");
      next();
    });
    
    
    // file api routes
    app.use('/accounts', require('./accounts/accounts.controller'));
    
    
    // All other GET requests not handled before will return our React app
    app.get('*', (req, res) => {
        res.sendFile(path.resolve(__dirname, 'build', 'index.html'));
    });
    
    app.get('/app', async (req, res) => {
      res.sendFile(path.join(__dirname, 'public/index.html'));
    });
    // does work, cors headers in response as expected
    
    
    // start server
    const port = process.env.PORT || 2000;
    app.listen(port, () => console.log('Server listening on port ' + port));
这是我在 server.js 中添加的特定更改:
   //change added that caused issues with the playing mechanism. Needed these headers for another 
    app.use(function(req, res, next) {
      res.header("Cross-Origin-Embedder-Policy", "require-corp");
      res.header("Cross-Origin-Opener-Policy", "same-origin");
      next();
    });
也许我需要为 s3 添加一个额外的 header ?
我最近还删除了此代码:
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});
这是我在后端的预签名方法,我用来生成要播放/下载的网址:
  const customer_id = data['customer-id'];
  const sound_id = data['sound-id'];
  
  return new Promise((resolve, reject) => {
    //get presigned url

    var myBucket = process.env.NODE_APP_BUCKET_NAME;
    var myKey = "sounds/" + customer_id + "/" + sound_id + ".wav"; 
    const signedUrlExpireSeconds = 120;
    try {
      const url = s3.getSignedUrl('getObject', {
        Bucket: myBucket,
        Key: myKey,
        ResponseContentDisposition: 'attachment',
        Expires: signedUrlExpireSeconds
      });
      resolve(url)
    }
    catch {
      console.log('S3 Object does not exist');
      resolve('');
    }
  });
然后我使用这个 url,用 var audio = new Audio(url) 创建一个新的音频对象并播放它。
如果您发现任何问题或我遗漏了什么,请告诉我。

最佳答案

您似乎直接使用指向您在 S3 上的音频文件的 URL,这意味着:

  • 您的音频(在您的网页看来)是一种跨域资源。与 Cross-Origin-Embedder-Policy 设置为 require-corp ,添加一个 crossorigin 归因于您的 <audio/> (包括 Audio 对象)是必需的。
  • 您的存储桶可能需要配置其 CORS 以允许您的站点访问它,如 in this other question 所述。 . AWS documentation解释了如何配置它。

  • 当我写这篇文章时,您的应用程序已关闭,因此我实际上无法验证它是由 S3 跨域资源引起的,但根据您的问题,这是最有可能的问题。

    关于node.js - 在已部署的应用程序上播放来自 s3 的文件时出现跨源资源策略问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68591422/

    相关文章:

    javascript - React.js - 受控输入 toLocaleString()

    javascript - Node 跨 3 个文件导出

    javascript - 如何使用 C++ 插件中内置的 node.js 模块

    javascript - 如何在 ReactJS 中使用 youtube onPlay={} 函数?

    reactjs - 将多个 redux 子状态连接到 React 组件

    hadoop - 估算并行计算的计算成本

    node.js - 如何对存储桶聚合阶段的输出进行排序?

    node.js - 如何从 GridFS 中的 block 和文件中删除文件?

    node.js - AWS S3 生成签名 URL '' AccessDenied''

    scala - 您可以对 s3 写入进行单元测试吗?