FAQ: Middleware - Review

This community-built FAQ covers the “Review” exercise from the lesson “Middleware”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Web Development

Learn Express

FAQs on the exercise Review

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

Hello there!

I am facing a problem with this exercise, at step 3.
After transferring the code snippet to an app.use middleware, adding cardIndex to the request object and invoking next, I get a syntax error informing me that on line 78 cardId is not defined.
The code below saws the app.use middleware that I have written:

app.use('/cards/:cardId', (req, res, next) => {
  const cardId = Number(req.params.cardId);
  const cardIndex = cards.findIndex(card => card.id === cardId);
  if (cardIndex === -1) {
    return res.status(404).send('Card not found');
  }
  req.cardIndex = cardIndex;
  next();
});

the code on line 78 is from a put request

app.put('/cards/:cardId', (req, res, next) => {
  const newCard = req.body;
  const validSuits = ['Clubs', 'Diamonds', 'Hearts', 'Spades'];
  const validRanks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace'];
  if (validSuits.indexOf(newCard.suit) === -1 || validRanks.indexOf(newCard.rank) === -1) {
    return res.status(400).send('Invalid card!');
  }
  if (!newCard.id || newCard.id !== cardId) {
    newCard.id = cardId; //<------ THE ERROR
  }
  cards[req.cardIndex] = newCard;
  res.send(newCard);
});

Is there something that I am missing?
Do I need to include anything to next?

Thanks in advance!

You need to carry the cardId in middleware as a request property, such that it can be carried to the next app.put/whatever.

2 Likes

I also had the same error for step 3, telling me that ‘newCard is not defined’. My middleware function looked like this:

app.use(’/cards/:cardId’, (req, res, next) => {
const cardId = Number(req.params.cardId);
const cardIndex = cards.findIndex(card => card.id === cardId);
if (cardIndex === -1) {
return res.status(404).send(‘Card not found’);
}
req.cardIndex = cardIndex;
next();
});

Adding the cardId variable into this ‘put’ request as below fixed it and the green tick appeared on step 3. I think it’s because the step doesn’t make it obvious that cardId should also be assigned to a property of the request as well as cardIndex:

app.put(’/cards/:cardId’, (req, res, next) => {
const cardId = Number(req.params.cardId); //Added line
const newCard = req.body;
const validSuits = [‘Clubs’, ‘Diamonds’, ‘Hearts’, ‘Spades’];
const validRanks = [‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘10’, ‘Jack’, ‘Queen’, ‘King’, ‘Ace’];
if (validSuits.indexOf(newCard.suit) === -1 || validRanks.indexOf(newCard.rank) === -1) {
return res.status(400).send(‘Invalid card!’);
}
if (!newCard.id || newCard.id !== cardId) {
newCard.id = cardId;
}
cards[req.cardIndex] = newCard;
res.send(newCard);
});

I didn’t try but I suppose leaving that request code as is (without adding the cardId variable) but adding ‘req.cardId = cardId;’ next to the similar line in the previous middleware function may also fix it so that it exists as a property of the request object that can be accessed by the next callback, hope this helps.

For the finalized version of the application we worked on, I just want to validate the order of middleware processing so that I have it firmly set in my own head.

If a PUT request is made to:

http://locahost:4001/cards/1?suit=Hearts&rank=10

Then:

  1. app.use(morgan(‘dev’))
  2. app.use(bodyParser.json())
  3. app.use(“Validate the card’s existence”)
  4. app.put(validateCard)
  5. app.put(“Callback to update card properties to suit=‘Hearts’ and rank=‘10’”)
  • status and response object sent after execution

If this is correct, I assume there is also an implicit ‘next()’ in all the 3rd party middleware like morgan and body-parser?

This was not an enjoyable end to the lesson for me…

Can someone explain why it is necessary to declare cardId and newCard again in the app.put(), after they have already been declared in the app.use() and validateCard functions respectively? I couldn’t get past steps 3 or 4 without doing this, which I only figured out once I had checked the solution and resetted the code. :roll_eyes:

// Update a Card
app.put('/cards/:cardId', validateCard, (req, res, next) => {
  const newCard = req.body;
  const cardId = Number(req.params.cardId);
  if (!newCard.id || newCard.id !== cardId) {
    newCard.id = cardId;
  }
  cards[req.cardIndex] = newCard;
  res.send(newCard);
});
1 Like

const and let variables have ‘block scope’. This means that if they have been declared inside a function block they won’t be recognised anywhere else. In this exercise you can see how it affects three variables: newCard, cardId, and cardIndex.
Unfortunately the instructions only mention the last one.

By extracting the fragment of code and pasting it into your custom validateCard and app.use() functions you made them unrecognisable for all other middleware using it.

One way of fixing ‘cardId’ would be to assign its value to the request object:

app.use('/cards/:cardId', (req, res, next) => {
  const cardId = Number(req.params.cardId);
  const cardIndex = cards.findIndex(card => card.id === cardId);
  if (cardIndex === -1) {
    return res.status(404).send('Card not found');
  }
  req.cardIndex = cardIndex;
  req.cardId = cardId;                     // <====
  next();
});

Then rename all instances of ‘cardId’ in remaining middleware to ‘req.cardId’

You could do the same with ‘newCard’, however given that its value is already a part of the request body…

const validateCard = (req, res, next) => {
  const newCard = req.body;                               // <====
  const validSuits = ['Clubs', 'Diamonds', 'Hearts', 'Spades'];
...

you might simply rename all instances of it in other functions to ‘req.body’ like here:

/ Update a Card
app.put('/cards/:cardId', validateCard, (req, res, next) => {
  if (!req.body.id || req.body.id !== req.cardId) {
    req.body.id = req.cardId;
  }
  cards[req.cardIndex] = req.body;
  res.send(req.body);
});

Finally, you could just redeclare and reassign ‘newCard’ variable in each middleware that uses it.

5 Likes

Cheers for the help mate. I think this part was what I had forgotten about:

const and let variables have ‘block scope’.

Assigning cardId to the request object is a nice solution!

2 Likes

A walkthrough of this exercise would be very useful. Completely lost on already on step 3 :sob:

I got tripped up by this as well!

If you look at the //Update a Card .put() route and refactor it as instructed based off what they show you, you’ve probably deleted “const cardId = Number(req.params.cardId);”

However if you look down the callback function you’ll see that theres an if statement that checks against “cardId” which you’ve now deleted…

You can either add cardId to the req object like your told to with cardIndex using “req.cardId = cardId;” and then refactor it that way or just leave “const cardId = Number(req.params.cardId);” at the top of the .put() route

I feel like there were a few badly written instructions in this lesson or perhaps were just a lil nooby :sweat_smile:

Hope this helps though :v:

2 Likes

This solved my issue. The instructions really were not clear enough for this lesson. I was looking at the diff for ages and refused to just accept the solution as I wanted to follow the lesson all the way through.

1 Like

Hi there,

Is there a way to accept single or double quotation as correct, or are single quotation some sort of industry standard? I keep getting errors for using double quotes and it’s usually causing me to take much more time to complete tasks. After I have exhausted all possible faults in my code, it always comes down to the quotation style chosen by the course programmer

1 Like

Thanks for the help…

Hi,
Why in the step 3. I need add card to req.cardIndex outside the if statement? It’s correct solution:

if (cardIndex === -1) {
    return res.status(404).send('Card not found');
  } 
  req.cardIndex = cardIndex;

my solution is considered wrong:

if (cardIndex === -1) {
    return res.status(404).send('Card not found');  // If the card not exists
  } else { 
  req.cardIndex = cardIndex;     // else, i.e. If the card exists
  }

For anyone else baffled by why correct code doesn’t work (I just had to troubleshoot why my requiring in body-parser didn’t work), this is the root cause for anyone who typically uses " " rather than ’ ’

I can’t answer your question I’m afraid, but I’ve been using " " pretty much exclusively because they make sense to me visually, with the added benefit of making it very easy to quickly identify things that I typed when scrolling through the swathes of ’ ’ in the provided starter code

Personally using " " also makes more sense as a standard because I’m far more likely to use an apostrophe in a string than quotations, so I don’t need to go back and correct my string being prematurely terminated when I’m typing in text that contains apostrophes