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:
Cross-Origin-Embedder-Policy
set to require-corp
, adding a crossorigin
attribute to your <audio/>
(including Audio
object) is required.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.