node.js - 在已部署的应用程序上播放来自 s3 的文件时的跨源资源策略问题
问题描述
我在 Heroku 上部署了一个应用程序,允许我播放音频文件。你可以在这里查看https://telecurve.herokuapp.com/manage。在我在 Heroku 中播放文件没有问题之前,但在我修改了我的 server.js 文件(我的应用程序是一个使用内置的 Create React 应用程序部署的 Express 应用程序)之后,我收到了这个错误。您可以尝试播放音频文件并查看响应。但是,我仍然可以使用下载按钮从 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 添加一个额外的标题?
我最近也删除了这段代码:
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();
});
这是我在后端用于生成要播放/下载的 URL 的后端预签名方法:
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 以允许您的站点访问它。AWS 文档解释了如何配置它。
当我写这篇文章时,您的应用程序已关闭,因此我实际上无法验证它是由 S3 跨域资源引起的,但根据您的问题,这是最有可能的问题。
推荐阅读
- java - 递归划分三角形中的 NullPointerException
- mysql - 有没有办法判断 MySQL 联合查询中的结果集何时发生变化?
- ios - 将标签放在 UIView 的中间三分之一处
- google-cloud-platform - 如何联系 Google 支持以获取 MarketPlace 支持
- ios - FCM 通知在 iOS Cordova 应用程序中突然停止工作
- c - 打印列表并用逗号分隔值并以点结尾
- c - 数据结构化的 C 语言中的两个编程问题
- swagger - Swagger Hub `Try it out` 返回 TypeError: Failed to fetch for localhost when using browser option
- notifications - Moodle 限制提交 通知指定老师
- python - 在python中检查列表中的字符串时减少for循环的使用