URL Shortener Microservice - Retrieving URL from Database and Shortening It?

Now there’s an original_url field but still no short_url field. I made this change to the schema:

const Schema = mongoose.Schema;
const urlSchema = new Schema({
  original_url: String,
  short_url: String
});

(added underscores in the names). What am I doing wrong? Code for app.post and app.get is the same as what I showed above.

Edit: I finally got it:

app.post("/api/shorturl/new", (req, res) => {
  const originalUrl = req.body.url;
  const domain = new URL(originalUrl).hostname;
  let shortUrl;
  Url.find({}, "original_url", (err, urls) => {
    if (err) {
      console.log(err);
    }
    shortUrl = urls.length;

    const url = new Url({
      original_url: originalUrl,
      short_url: shortUrl
    });

    dns.lookup(domain, (err) => {
      if (err) {
        res.json({ error: "invalid url" });
      }

      url.save((err, url) => {
        if (err) {
          console.log(err);
        }
      });

      res.json({
        original_url: originalUrl,
        short_url: shortUrl
      });
    });
  });
});

app.get("/api/shorturl/:short_url", (req, res) => {
  Url.findOne({ short_url: req.params.short_url }, (err, url) => {
    if (err) {
      console.log(err);
    }
    res.redirect(url.original_url);
  });
});

Well done! I hope you have learnt something out of this project :smiley:

Why do you have "original_url" in the argument list?

I thought I’d need that as a search key. I don’t need it?

I learned that Mongoose database operations don’t really need a done callback when you use them directly like this.

Is this not right?

dns.lookup(domain, (err) => {
      if (err) {
        res.json({ error: "invalid url" });
      }

      url.save((err, url) => {
        if (err) {
          console.log(err);
        }
      });

      res.json({
        original_url: originalUrl,
        short_url: shortUrl
      });
    });

I can’t pass the last user story test:

If you pass an invalid URL that doesn't follow the valid http://www.example.com format, the JSON response will contain { error: 'invalid url' }

What am I missing?

Well, what it is doing is filtering out documents that do not have that field. Hopefully, all of your docs have that field. So, it is redundant.


This is what the tests are sending as the input URL: ftp:/john-doe.org Try testing your app with that, to see what it does.

Hint:

What I ended up doing was specifically causing dns.lookup to fail, if the input URL did not match https?

Hope this clarifies

I tried this:

    dns.lookup(domain, (err) => {
      if (err) {
        res.json({ error: err });
      }

      if (parsedUrl.protocol !== "http" || parsedUrl.protocol !== "https") {
        res.json({ error: "invalid url" });
      }

      url.save((err, url) => {
        if (err) {
          console.log(err);
        }
      });

      res.json({
        original_url: originalUrl,
        short_url: shortUrl
      });
    });

But it gives {error: invalid url} response on valid URLs too.

parsedUrl is initialized as

const parsedUrl = new URL(originalUrl);

I changed that other if-condition to this:

if (!originalUrl.substr(0, 5).match("https") || !originalUrl.substr(0, 4).match("http")) {
        res.json({ error: "invalid url" });
      }

and now it works (at least locally).

Hmm…

I would try using the address parameter given to the dns.lookup callback:

dns.lookup(domain, (err, address) => {...

That is, instead of parsedUrl.

Just so you know, working with RegEx in this case would be must easier/shorter.

Yeah, I used a RegEx. With that all of the tests pass too (earlier, the test for the short URL didn’t pass).

@Sky020 I want to prevent duplicate records in my database. I tried marking original_url as a unique field but it just gave an error although the short_url which is set to be equal to the number of documents at the time is 1

There’s only one document in the database and it has short_url of 0, but I got a JSON response with the same original_url where the short_url is 1. Is there a way to use Model.find to check if a document with a given URL is already in the database and to not insert a new document if one with that URL is also present?

Thanks in advance.

Sure. This is the whole point of Model.find. Specifically, I would expect you to use Model.findOne. The Mongoose docs are quite helpful for seeing how to use it.

Would there be something in the err object if a document with the given URL is already there? Or is there some other check for it?

Edit: So since the first found document is passed to the callback, couldn’t I just check if it’s a truthy value or not? If it’s truthy, there’s a document with that URL already present. Otherwise there isn’t.

Yes, you can :+1: . This would be a nice way to do it.

I added this code before the res.json line:

      Url.findOne({ original_url: originalUrl }, (err, foundUrl) => {
        if (err) {
          console.log(err);
        }

        if (!foundUrl) {
          url.save((err, url) => {
            if (err) {
              console.log(err);
            }
          });
        }
      });

I’ll test this out now.

Edit: Yeah, I think it works.

By the way, I get these deprecation warnings in Visual Studio Code’s terminal while the server is running:

(node:11560) DeprecationWarning: Listening to events on the Db class has been deprecated and will be removed in the next major version.
(node:11560) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

These aren’t from my own code but from the implementation, right?

Difficult to tell. Do you have a GitHub repo, or similar, you could link to for your latest code?

The deprecation warnings are not something to be concerned about, unless you decide to update the package version.

I have the latest LTS version of Node and the latest versions of the MongoDB driver for Node, as well as the latest version of Mongoose.

Here’s my GitHub repo link.

Looks like the only way to remove the warnings is to downgrade MongoDB/Mongoose:

The issue is not with your code, but the fact that Mongoose uses MongoDB, and MongoDB have updated their code, but Mongoose have not made the equivalent update, yet.

Otherwise, the only way to make the warning go away on the latest version would be to edit the mongoose library in the node_modules folder.

Hope this helps

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.