Quote API Challenge Project (JavaScript)

Here is my solution. I decided to go with a modularized router and to write most of it in short form. It took me about 2 hours.

The last half hour or so was triaging to get the {quotes} object formed for the site to receive. The dev console showed it was working fine, but the site wasn’t rendering. There is good information earlier in this thread for resolving the issue by forming the object into an object like {quote:quoteObject}.

1 Like

This is my version of the required steps nothing more. I plan on adding the extra steps as soon as I can get what I have to start working. No matter which request I make on the Quote API site I get the same error. After I couldn’t figure it out I compared it to a couple other versions and even though I might have over complicated it, I don’t see why it isn’t working.

Error Message

Your request returned an error from the server:
Code: 404
Not Found

The isEmpty() function I required from the underscore module checks wether or not an object is empty and returns true or false.

Server.js

const express = require('express');
const app = express();

const { quotes } = require('./data');
const { getRandomElement } = require('./utils');
const underscore = require('underscore');
const { everyQuote } = require('./utils');

const PORT = process.env.PORT || 4001;

app.use(express.static('public'));

app.get('api/quotes/random', (req, res, next) => {
  const obj = {};
  const randomQuote = getRandomElement(quotes);
  obj[quote] = randomQuote;
  res.send(obj);
});

app.get('api/quotes', (req, res, next) => {
  const specificAuthor = req.query;
  const obj2 = {};
  const authorCheck = underscore.isEmpty(specificAuthor);
  if (authorCheck) {
    obj2[quotes] = everyQuote(quotes);
    res.send(obj2);
  } else {
    const specificAuthorQuotes = [];
    for (let i = 0; i < quotes.length; i++) {
      if (quotes[i].person === specificAuthor.person) {
        specificAuthorQuotes.push(quotes[i].quote);
      }
    }
    obj2[quotes] = specificAuthorQuotes;
    return obj2;
  }
});

app.post('api/quotes', (req, res, next) => {
  const newData = req.query;
  const obj3 = {};
  if (!Object.keys(newData).length < 1 || !newData.quote === undefined || !newData.person === undefined) {
    quotes.push(newData);
    obj3[quote] = {quote: newData.quote, person: newData.person};
    res.status(201).send(obj3);
  } else {
    res.status(400).send();
  }
})

app.listen(PORT, () => {
  console.log(`Server listening at port ${PORT}.`);
});

Helper Function
Returns every quote in the Quotes array.

const everyQuote = arr => {
  let quotes = [];
  arr.forEach((obj) => {
    quotes.push(obj.quote);
    return quotes;
  });
};
1 Like

I’m not sure if this is the answer but I noticed your route parameters are written as such:

app.get('api/quotes', (req, res, next) => {...}

Try rewriting them is this format:

app.get('/api/quotes', (req,res,next) => {...}

I think it might be the missing backslash. Not sure, but it’s easy enough to give it a try.
Hope that helps. :slightly_smiling_face:

1 Like

This was a tough one for me, a lot of new concepts. Learned a lot. I only did the required steps as well. It really helped looking at others’ code in this thread.

const express = require('express');
const app = express();

const { quotes } = require('./data');
const { getRandomElement  } = require('./utils');

const PORT = process.env.PORT || 4001;

app.use(express.static('public'));

//RETURN RANDOM QUOTE
app.get('/api/quotes/random',(req,res,next)=>{  
  const random = getRandomElement(quotes);
  res.send(random);
});

//RETURN ALL QUOTES Or
//RETURN QUOTES FROM SPECIFIC PERSON
app.get('/api/quotes',(req,res,next)=>{
  const authorName = req.query.person;
  if(authorName){
    const authorArray = quotes.filter((quotes)=>{
     return quotes.person === authorName;       
    });      
    res.send({quotes: authorArray});
  } else {
    res.send({quotes:quotes});
  } 
});

//ADD NEW QUOTES
app.post('/api/quotes',(req,res,next)=>{
  const receivedQuote = req.query;
  if(receivedQuote.quote && receivedQuote.person){
    quotes.push(receivedQuote);
    res.status(201).send({quote: receivedQuote});
  } else{
    res.status(400).send();
  }
});

app.listen(PORT,()=>{
    console.log(`Server is listening on ${PORT}`);
});

Thanks i’ll give that a try and see what happens! Its probably one of many obvious mistakes I made hah

1 Like

Cool solution code, one small thing though. The example code contains a Cross-site Scripting vulnerability in add-quote.js on lines 16 and 17.

You should use the DOM API to programmatically build the new DOM nodes, using document.createElement and friends instead of innerHTML.

Hi everyone!
Just completed the project.

const {includes} = require('lodash')
const express = require('express');
const app = express();

const { quotes } = require('./data');
const { getRandomElement } = require('./utils');


app.get("/api/quotes/random", (req, res, next) => {
    res.send(getRandomElement(quotes))
} )

app.get("/api/quotes", (req, res, next) => {
    res.send(quotes)
})

app.get("/api/quotes/:author", (req, res, next) => {
    const author = req.params.author
    const findPerson = quotes.filter(({person}) => includes(person, author));
    findPerson.length !== 0 ? res.send(findPerson) :res.send([])
})

app.post("/api/quotes", (req, res, next) =>{
    console.log(req.query)
    res.send(req.query).end()
})

// /api/quotes?person=Grace Hopper
const PORT = process.env.PORT || 4001;
app.use(express.static('public'));
app.listen(PORT, () => console.log(`Listening on port ${PORT}`))

Even with the solution, I’m still getting these errors when trying to run off-platform. Any ideas?

I’ve tried adding CORS. There seems to be a disconnect between the html button and the script. But I’m not sure how to fix. My route on postman returns all quotes (ie
GET http://localhost:4001/api/quotes)

When you run node server.js, why and how do the files in the ‘public’ folder get loaded in the browser? I get that it makes a request to the localhost + port that you set up, but I don’t get how it receives a response with the fronted data ( nothing is set up to work like that, only if it is a default behavior? )

Hey guys,
this is my solution for the Quote API challenge

Hello beautiful people.

Challenge completed.

Quote API

Keep coding. :heart:

Here’s my solution! Thanks guys!

Here’s my solution to the project. I also refactored the starting code to use async/await instead of chaining .then()

Here is my finished quote api project!
https://github.com/albarrank/Quote_API

Hello,
I’m using Postman for this project and when I use the post request it gives me bad request, I’m using the solution code and the json request I use is
{“quote”: {“quote”:“blabla”, “person”: “me”}}
If someone can tell me why is not working would be much appreciated .
Thank you!

Hey all,

Here is my finished quote api project! Any feedback is appreciated.

Please message me if you are interested in a Code Review.

Thanks!

Chris DeCleene

Hello everybody,

It took me around 3 hours to finish this project.

It was challenging but it was also fun and I have learnt many new things.

This is my solution :smiling_face_with_three_hearts:

Just finished it. Didn’t bother with adding a delete or put since that would require messing with the data structure
https://github.com/EmmaSecrest/apiQuotes`

const express = require('express'); const app = express(); const { quotes } = require('./data'); const { getRandomElement } = require('./utils'); const PORT = process.env.PORT || 4001; app.use(express.static('public')); app.listen(PORT, () =>{ console.log(`listening at http://localhost:${PORT}`) }) // get a random quote app.get('/api/quotes/random' , (req,res) => { const randomQuoteRequest = getRandomElement(quotes) console.log({qoute:randomQuoteRequest}) res.send({quote: randomQuoteRequest}) }) // return a quote with params or if none are provided return all app.get('/api/quotes' , (req,res) => { // the query in this case is for a person so const requestedAuthor = req.query.person if(requestedAuthor !== undefined){ // filters through all the quotes const authoursQuotes = quotes.filter(quote => quote.person === requestedAuthor) // sending quotes res.send({quotes:authoursQuotes}) } else { res.send({quotes}) } }) app.post('/api/quotes' , (req,res) => { // need to check and make sure all fields are filled before adding the quote const newQuote = req.query.quote const newAuthor = req.query.person // checking to make sure both of these are filled if(newQuote !== '' && newAuthor !== ''){ // neither field is empty console.log(newQuote) console.log(newAuthor) const newQuoteToSend = { quote: { quote: newQuote, person: newAuthor } } // working correctly quotes.push(newQuoteToSend) res.status(201).send(newQuoteToSend) } else { res.status(400).send("Can't send quote with empty person or quote") } })

`

Hi everybody,

This is my solution to the ‘Quote API Challenge Project (JavaScript)’. I added a ‘PUT’ route, a ‘DELETE’ route, and extra information about the quotes. I included extensive comments in ‘server.js’ so that anybody who is interested in the ‘PUT’ and ‘DELETE’ routes can follow along with my coding logic. I also included 13 images of the app in action in my README.md file.

Hope this helps and I hope everybody is enjoying their course :slight_smile:

1 Like

Hi everyone!
I’m so glad that I could upload my solutions finally.
I have put Gif files that show how my Quote-API works on this GitHub page.

As an option, I’ve added PUT route which is possible to edit the existing quote. And to help this feature, I’ve added IDs on each quote and an extra GET route that can fetch a particular quote by these ID.

Hope you’ll enjoy seeing them!
Happy coding :blush: