We need to create a RESTful API using Express.js that handles various operations for artists, albums, and songs. The application needs to:
Core Requirements:
Input Types:
Expected Output:
// Initial setup of Express application
const express = require('express');
const app = express();
// Enable JSON parsing for incoming requests
app.use(express.json());
// Basic debugging middleware
app.use((req, res, next) => {
console.log('Request Body:', req.body);
next();
});
Think of JSON parsing middleware like a postal worker who opens envelopes (requests) and organizes the contents (JSON data) into a neat stack (req.body) before delivering it to the intended recipient (your route handlers).
// Import data functions
const { getAllArtists, addArtist } = require('./data.js');
// GET /artists - Retrieve all artists
app.get('/artists', (req, res) => {
// Get array of all artists from data layer
const artists = getAllArtists();
// Send JSON response
res.json(artists);
});
// POST /artists - Create a new artist
app.post('/artists', (req, res) => {
// Extract artist data from request body
const artistData = req.body;
// Create new artist using data function
const newArtist = addArtist(artistData);
// Send 201 status with new artist data
res.status(201).json(newArtist);
});
// Import additional functions
const { getLatestArtist, getAlbumsForLatestArtist } = require('./data.js');
// GET /artists/latest - Get most recently added artist
app.get('/artists/latest', (req, res) => {
const latest = getLatestArtist();
res.json({ latest });
});
// GET /artists/latest/albums - Get albums of latest artist
app.get('/artists/latest/albums', (req, res) => {
const albums = getAlbumsForLatestArtist();
res.json({ latest: { albums } });
});
// Import required functions
const {
getArtistByArtistId,
editArtistByArtistId,
deleteArtistByArtistId
} = require('./data.js');
// GET /artists/:artistId - Get specific artist
app.get('/artists/:artistId', (req, res) => {
const { artistId } = req.params;
const artist = getArtistByArtistId(Number(artistId));
res.json(artist);
});
// PUT /artists/:artistId - Update artist
app.put('/artists/:artistId', (req, res) => {
const { artistId } = req.params;
const updatedArtist = editArtistByArtistId(Number(artistId), req.body);
res.json(updatedArtist);
});
// DELETE /artists/:artistId - Remove artist
app.delete('/artists/:artistId', (req, res) => {
const { artistId } = req.params;
deleteArtistByArtistId(Number(artistId));
res.json({ message: "Successfully deleted" });
});
// Import album-related functions
const {
getAlbumByAlbumId,
addAlbumByArtistId,
editAlbumByAlbumId,
deleteAlbumByAlbumId,
getFilteredAlbums
} = require('./data.js');
// GET /albums/:albumId - Get album details
app.get('/albums/:albumId', (req, res) => {
const { albumId } = req.params;
const album = getAlbumByAlbumId(Number(albumId));
res.json(album);
});
// POST /artists/:artistId/albums - Create album
app.post('/artists/:artistId/albums', (req, res) => {
const { artistId } = req.params;
const newAlbum = addAlbumByArtistId(Number(artistId), req.body);
res.status(201).json(newAlbum);
});
// GET /albums - Get filtered albums
app.get('/albums', (req, res) => {
const { startsWith } = req.query;
const albums = getFilteredAlbums(startsWith);
res.json(albums);
});
// Import song-related functions
const {
getSongBySongId,
addSongByAlbumId,
getSongsByArtistId,
editSongBySongId,
deleteSongBySongId
} = require('./data.js');
// GET /songs/:songId - Get song details
app.get('/songs/:songId', (req, res) => {
const { songId } = req.params;
const song = getSongBySongId(Number(songId));
res.json(song);
});
// POST /albums/:albumId/songs - Add song to album
app.post('/albums/:albumId/songs', (req, res) => {
const { albumId } = req.params;
const newSong = addSongByAlbumId(Number(albumId), req.body);
res.status(201).json(newSong);
});
Think of route parameters like house numbers on a street - they're part of the address itself (e.g., /artists/1). Query parameters are more like special instructions left for the delivery person (e.g., /albums?startsWith=S).
We can think of HTTP methods like different types of interactions in a library:
HTTP status codes are like different types of responses you might get at a store:
For each endpoint, you can use Postman to test:
To deepen your understanding of Express routing, try these extensions: