问题描述
我在 Heroku 上部署了一个应用程序,可以播放音频文件.您可以在此处查看 https://telecurve.herokuapp.com/manage.在我在 Heroku 中播放文件没有问题之前,但在我修改了 server.js 文件(我的应用程序是一个 Express 应用程序,它部署了一个内置的 Create React 应用程序)之后,我收到了这个错误.您可以尝试播放音频文件并查看响应.但是,我仍然可以使用下载按钮从 s3 下载文件并且没有问题.
这是一些相关的代码:
server.jsrequire('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());//让 Node 为我们构建的 React 应用程序提供文件app.use(express.static(path.resolve(__dirname, 'build')));//允许来自任何来源和凭据的 cors 请求app.use(cors({ origin: (origin, callback) => callback(null, true), credentials: true }));//添加了导致播放机制问题的更改.另一个需要这些标题app.use(function(req, res, next) {res.header(Cross-Origin-Embedder-Policy", require-corp");res.header(Cross-Origin-Opener-Policy", 同源");下一个();});//文件api路由app.use('/accounts', require('./accounts/accounts.controller'));//之前未处理的所有其他 GET 请求将返回我们的 React 应用程序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'));});//确实有效,cors 标头按预期响应//启动服务器const port = process.env.PORT ||2000;app.listen(port, () => console.log('服务器监听端口' + 端口));
这是我在 server.js 中添加的特定更改:
//添加的更改导致播放机制出现问题.另一个需要这些标题app.use(function(req, res, next) {res.header(Cross-Origin-Embedder-Policy", require-corp");res.header(Cross-Origin-Opener-Policy", 同源");下一个();});
也许我需要为 s3 添加额外的标头?
我最近也删除了此代码:
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");下一个();});
这是我在后端使用的预签名方法,用于生成要播放/下载的网址:
const customer_id = data['customer-id'];const sound_id = data['sound-id'];返回新的承诺((解决,拒绝)=> {//获取预签名的urlvar myBucket = process.env.NODE_APP_BUCKET_NAME;var myKey = "sounds/";+ customer_id + "/";+ sound_id + ".wav";const signedUrlExpireSeconds = 120;尝试 {const url = s3.getSignedUrl('getObject', {桶:我的桶,密钥:myKey,ResponseContentDisposition: '附件',过期时间:signedUrlExpireSeconds});解析(网址)}抓住 {console.log('S3 对象不存在');解决('');}});
然后我使用这个 url,用 var audio = new Audio(url)
创建一个新的音频对象并播放它.
如果您发现任何问题或我遗漏了什么,请告诉我.
你好像直接使用了指向你 S3 上音频文件的 URL,意思是:
- 您的音频(在您的网页看来)是一种跨源资源.使用
Cross-Origin-Embedder-Policy
设置为require-corp
,添加一个crossorigin
属性到您的(包括
Audio
对象)是必需的. - 您的存储桶可能需要配置其 CORS 以允许您的站点访问它,如在另一个问题中所述.AWS 文档 解释了如何配置它.
当我写这篇文章时,您的应用程序已关闭,因此我无法实际验证它是由 S3 跨域资源引起的,但根据您的问题,这是最有可能的问题.>
I have a deployed app on Heroku that allows me to play audio files. You can check it out here https://telecurve.herokuapp.com/manage. Before I had no issues playing the files in Heroku but after I modified my server.js file (my app is an Express app that is deployed with a built Create React app), I get this error. You can try playing an audio file and seeing the response. However, I am still able to download files from s3 with the download button and have no issues.
Here is some relevant code:
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));
this is the particular change in server.js that I added:
//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();
});
Maybe I need to add an additional header for s3?
I also recently removed this code:
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();
});
Here is my presigning method in the backend that I use to generate urls to play/download from:
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('');
}
});
I then take this url, create a new audio object with var audio = new Audio(url)
and play it.
Let me know if you see anything going wrong or if im missing anything.
You seem to directly use the URL pointing at your audio file on S3, meaning that:
- Your audio is (in the eyes of your webpage) a cross-origin resource. With
Cross-Origin-Embedder-Policy
set torequire-corp
, adding acrossorigin
attribute to your<audio/>
(includingAudio
object) is required. - Your bucket might needs its CORS configured to allow your site to access it, as mentioned in this other question. The AWS documentation explains on how you can configure that.
Your app was down when I wrote this, so I couldn't actually validate it's caused by S3 cross-origin resources, but based on your question, it is the most likely issue.
这篇关于在已部署的应用程序上播放来自 s3 的文件时出现跨源资源策略问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!