Jammming cross-origin request blocked when trying to save Playlist

Hi everyone,
My brain is getting fully broken by this project. I’ve finally (with the help of the walkthrough and some answers to questions on here) got to the point where the search results are working etc., but there’s a brand new problem - when I try to save a playlist, my request gets blocked because of a cross-origin request. I get this in the console (hastily translated from German, bear with me):

Cross-origin request blocked: The same-source rule forbids access to the external resource at https://api.spotify.com/v1/users/undefined/playlist. (Reason: Headline ‘headers’ is not permissable as a result of the headline ‘Access-Control-Allow-Headers’ from the CORS-Preflight reply).

Here’s the code for the playlist bit (I’m sure the access token is fine because it works for the search bar). Thanks so much for your help…!

savePlaylist(name, uriArray) {
        if (!name || !uriArray){
            return;
        };
        
        const access = Spotify.getAccessToken();
        const headers = { headers: {Authorization: `Bearer ${access}`} };
        let userID;

        return fetch(`https://api.spotify.com/v1/me`, headers)
                .then(response => response.json())
                .then(jsonResponse => {
                     userID = jsonResponse.id;
                     return fetch(`https://api.spotify.com/v1/users/${userID}/playlists`, {
                        method: 'POST',
                        headers: headers,
                        body: JSON.stringify( {name: name} )
                    })
                .then(response => response.json())
                .then(jsonResponse => {
                    const playlistID = jsonResponse.id;
                    return fetch(`/v1/users/${userID}/playlists/${playlistID}/tracks`, {
                        method: 'POST',
                        headers: headers,
                        body: JSON.stringify( {uris: uriArray} ),
                    })
                })
                });
    } 

Check what’s happening to your headers after the first request. Here’s what I mean:

You set the value of headers to be

{ headers: {Authorization: `Bearer ${access}`} }

so if access was equal to: “myaccesstoken” then it works fine with your first fetch() to the /v1/me endpoint.

{
  headers: {Authorization: 'Bearer myaccesstoken'},
}

Now your next fetch() request:

{
  method: 'POST',
  headers: headers,
  body: JSON.stringify( {name: name} )
}

That becomes:

{
  method: 'POST',
  headers: { headers: { Authorization: 'Bearer myaccesstoken' } },
  body: JSON.stringify( {name: name} )
}

Notice that your headers are now malformed because they should look like this:

{
  method: 'POST',
  headers: { Authorization: 'Bearer myaccesstoken' },
  body: JSON.stringify( {name: name} )
}

Hi there,
Thanks so much for your reply - I had actually had that as you suggested originally, but then changed it because it’s the way with the malformed headers on the walkthrough. Now I’ve changed it and the playlist is still not working; posting the whole code to see if maybe there’s a problem I’m not seeing somewhere else. Thanks so much for your help.

let accessToken;
const clientID = '91e533c2c20d4256bdace4065cce4716';
const redirectURI = 'http://localhost:3000/';

const Spotify = {
    getAccessToken(){
        if (accessToken){
            return accessToken;
        };

        const accessInURL = window.location.href.match(/access_token=([^&]*)/);
        const expirationTime = window.location.href.match(/expires_in=([^&]*)/);

        if (accessInURL && expirationTime){
            accessToken = accessInURL[1];
            const expires = Number(expirationTime);
            window.setTimeout(() => accessToken = '', expires * 1000);
            window.history.pushState('Access Token', null, '/');
            return accessToken;
        } else {
        window.location = 
        `https://accounts.spotify.com/authorize?client_id=${clientID}&response_type=token&scope=playlist-modify-public&redirect_uri=${redirectURI}`;
        }
    },


    search(searchTerm) {
        const accessToken = Spotify.getAccessToken();
        return fetch(`https://api.spotify.com/v1/search?type=track&q=${searchTerm}`,  {
                        headers: {Authorization: `Bearer ${accessToken}`}
                    }
                    ).then(response => {
                        return response.json()
                        })
                    .then(jsonresponse => {
                        if (!jsonresponse.tracks){
                            return [];
                        }
                        return jsonresponse.tracks.items.map(track => ({
                            id: track.id,
                            name: track.name,
                            artist: track.artists[0].name,
                            album: track.album.name,
                            uri: track.album.uri})
                            )       
                    });
                },

   savePlaylist(name, uriArray) {
        if (!name || !uriArray){
            return;
        };
        
        const accessToken = Spotify.getAccessToken();
        const headers = { headers: {Authorization: `Bearer ${accessToken}`} };
        let userID;

        return fetch(`https://api.spotify.com/v1/me`, headers)
                .then(response => response.json())
                .then(jsonResponse => {
                     userID = jsonResponse.id;
                     return fetch(`https://api.spotify.com/v1/users/${userID}/playlists`, {
                        method: 'POST',
                        headers: {Authorization: `Bearer ${accessToken}`},
                        body: JSON.stringify( {name: name} )
                    })
                .then(response => response.json())
                .then(jsonResponse => {
                    const playlistID = jsonResponse.id;
                    return fetch(`/v1/users/${userID}/playlists/${playlistID}/tracks`, {
                        method: 'POST',
                        headers: { Authorization: `Bearer ${accessToken}` },
                        body: JSON.stringify( {uris: uriArray} ),
                    })
                })
                });
    } 
};

export default Spotify;

Try running a console.log(expires) after you assign the value. It isn’t going to be what you think it is.

Once you fix that, you’ll be able to start debugging your next issue

Thank you, you are a legend. There are multiple mistakes in the Walkthrough, seemingly (actually, there are a couple of really obvious mistakes in the code for saving the playlist that mean it definitely can’t work (Authorization misspelled as Auhorization, for one), but for some reason it’s about the only thing he doesn’t really check works, so he just goes ‘Cool, done’ and moves on), but once I changed this to Number(expirationTime[1]) everything else kind of fell into place. Got it all working now!

Thanks so much for your help.

1 Like