Неверный запрос при использовании spotify-web-api-node несколько раз без перезапуска сервера, ошибка 400 - PullRequest
0 голосов
/ 30 мая 2019

Я создаю страницу, на которой после нажатия кнопки она получает кучу данных из 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 нажатий на эту кнопку.

...