Я создаю страницу, на которой после нажатия кнопки она получает кучу данных из Spotify. Изначально все отлично работает. Но если эта кнопка нажата 3 или более раз без перезапуска сервера, я получаю следующую ошибку:
{ [WebapiError: Bad Request] name: 'WebapiError', message: 'Bad Request', statusCode: 400 }
И я имею в виду не быстрое нажатие на кнопку, а просто обычное нажатие несколько раз после того, как оно будет выполнено каждый раз. Ниже я приведу очень простой код для воспроизведения этой проблемы со следующей структурой:
.
├── .env
├── index.js
├── package.json
└── views
├── error.html
└── index.html
По сути, он сначала получает некоторую общую информацию о пользователе. Затем он получает самые последние сохраненные песни, самые последние воспроизводимые песни и лучшие песни прошлого месяца для этого пользователя. Для всех этих песен он выбирает соответствующие им аудио функции:
index.js
require('dotenv').config();
const SpotifyWebApi = require('spotify-web-api-node');
const express = require('express');
const url = require('url').URL;
const scopes = ['user-library-read', 'user-read-recently-played', 'user-top-read'];
const state = 'some-state-of-my-choice';
const spotifyApi = new SpotifyWebApi({
clientId: process.env.SPOTIFY_CLIENT_ID,
clientSecret: process.env.SPOTIFY_CLIENT_SECRET,
redirectUri: process.env.SPOTIFY_REDIRECT_URI
});
const authorizeURL = spotifyApi.createAuthorizeURL(scopes, state);
const app = express();
app.set('port', process.env.PORT || 3000);
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(express.static(__dirname + '/views'));
let saved_songs_ID = [];
let played_songs_ID = [];
let top_songs_ID = [];
function obtain_results(success, fail) {
let results = {};
// get user info
spotifyApi.getMe().then(function(data) {
results['display_name'] = data.body['display_name'];
results['followers'] = data.body['followers']['total'];
return spotifyApi.getMySavedTracks({limit:50});
}, function(err) { console.error(err); fail(); })
// get user's recently SAVED tracks
.then(function(data) {
console.log("gathering recently SAVED...");
let items = data.body['items'];
results['most_recent_saved_song'] = items[0]['track']['name'];
for(let i=0; i<items.length; i++) {
saved_songs_ID.push(items[i]['track']['id']);
}
return spotifyApi.getMyRecentlyPlayedTracks({limit:50});
}, function(err) { console.error(err); fail(); })
// get user's recently PLAYED tracks
.then(function(data) {
console.log("gathering recently PLAYED...");
let items = data.body['items'];
results['most_recent_played_song'] = items[0]['track']['name'];
for(let i=0; i<items.length; i++){
played_songs_ID.push(items[i]['track']['id']);
}
return spotifyApi.getMyTopTracks({limit:50, time_range:'short_term'})
}, function(err) { console.error(err); fail(); })
// get user's TOP songs
.then(function(data) {
console.log("gathering last month's TOP...");
let items = data.body['items'];
results['top_song'] = items[0]['name'];
for(let i=0; i<items.length; i++){
top_songs_ID.push(items[i]['id']);
}
return spotifyApi.getAudioFeaturesForTracks(saved_songs_ID);
}, function(err) { console.error(err); fail(); })
// get FEATURES for user's SAVED songs
.then(function(data) {
console.log("gathering FEATURES for SAVED tracks...");
console.log(data.body['audio_features'][0]['danceability']);
return spotifyApi.getAudioFeaturesForTracks(played_songs_ID);
}, function(err) { console.error(err); fail(); })
// get FEATURES for user's PLAYED songs
.then(function(data) {
console.log("gathering FEATURES for PLAYED tracks...");
console.log(data.body['audio_features'][0]['danceability']);
return spotifyApi.getAudioFeaturesForTracks(top_songs_ID);
}, function(err) { console.error(err); fail(); })
// get FEATURES for user's TOP songs
.then(function(data) {
console.log("gathering FEATURES for TOP tracks...");
console.log(data.body['audio_features'][0]['danceability']);
success(results);
}, function(err) { console.error(err); fail(); })
}
app.get('/',function(req, res){
res.render('index.html');
});
app.post('/',function(req, res){
res.redirect(authorizeURL);
});
app.get('/home',function(req, res){
const current_url = new url('localhost:' + process.env.PORT + req.url);
const code = current_url.searchParams.get('code');
// Retrieve an access token and a refresh token
spotifyApi.authorizationCodeGrant(code).then(
function(data) {
// Set the access token on the API object to use it in later calls
spotifyApi.setAccessToken(data.body['access_token']);
spotifyApi.setRefreshToken(data.body['refresh_token']);
console.log('-------------------------------------------------------------');
console.log('\nThe access token is ' + data.body['access_token'] + '\n');
console.log('It expires in ' + data.body['expires_in'] + '\n');
console.log('The refresh token is ' + data.body['refresh_token'] + '\n');
obtain_results(
function(results){
console.log("all data gathered successfully");
console.log(results);
res.redirect('/');
},
function(){ res.render('error.html'); }
);
},
function(err) { console.log('Something went wrong!'); }
);
});
app.listen(app.get('port'), function(){
console.log('started on http://localhost:' + app.get('port') + ' press Ctrl-C to terminate');
});
package.json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^7.0.0",
"ejs": "^2.6.1",
"express": "^4.16.4",
"spotify-web-api-node": "^4.0.0"
}
}
.env
SPOTIFY_CLIENT_ID=your-client-id
SPOTIFY_CLIENT_SECRET=your-client-secret
SPOTIFY_REDIRECT_URI=your-redirect-url
PORT=3000
index.html
<!DOCTYPE html>
<html>
<head>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<br><br>
<center>
<form method="post">
<input class="btn btn-primary" type="submit" value="BEGIN">
</form>
</center>
</body>
</html>
error.html
<!DOCTYPE html>
<html>
<head>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<br><br>
<center>
<h3>Something went wrong.</h3>
</center>
</body>
</html>
Чтобы повторить это самостоятельно, просто сделайте
npm install
npm start
Я хочу, чтобы этот сайт был в сети и использовался многими разными людьми или даже одним и тем же человеком несколько раз. Поэтому мне действительно нужно решить эту проблему, иначе вся система перестанет работать после 3 нажатий на эту кнопку.