URL shortener doesn't pass tests

Tell us what’s happening:
I can’t pass the second and the third tests and I don’t know why.

Your project link(s)

solution: https://2tfee1.sse.codesandbox.io
index.js source code: index.js - Pastebin.com

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0

Challenge: URL Shortener Microservice

Link to the challenge:

Any feedback on the project would also be appreciated.

It’s your URL regular expression, I believe, but I’m far too lazy to test it since it’s not in a repl. Log your route inputs and outputs and look at the URLs being passed in versus what your code says about their validity. Even if it is something else, the logged inputs and outputs should point you in the correct direction.

Also, don’t return console.error(...) (or console.log()) as their return value is undefined. You can return the error or the error message in JSON if you want.

Thanks for the feedback! Ill try that when I get back.

I changed the Regex and I also changed how the redirect endpoint works, it works for the second test now, thanks! But it still fails the third test because it times out.

So here’s the code for the redirect endpoint.

// Shortener redirect endpoint.
app.get("/api/shorturl/:id", async (req, res) => {
  try {
    let urlToRedirect = "";
    let urlFound = false;
    let attempts = 0;
    while (!urlFound && attempts < 100) {
      console.log("Trying to find URL to redirect...");
      await linkModel.findOne({ shortenedID: req.params.id }, (error, data) => {
        if (error) console.log(error);
        // We need 2 seperate if statements because if the data is null
        // and we try to read the url value it will cause an exception.
        if (data !== null) {
          if (data.url !== "") {
            urlToRedirect = data.url;
            console.log("URL found:", data.url);
            urlFound = true;
          }
        }
        attempts++;
      });
    }
    console.log("Redirecting to:", urlToRedirect);
    res.redirect(urlToRedirect);
  } catch (error) {
    console.log("Exception Caught.");
    console.log(error);
  }
});

The reason I made it this way is because I noticed there was a delay between the link been saved in the database, so the redirect endpoint wouldn’t work immediately.

So i changed it to that and I tried it both locally and in codesandbox and the redirect works almost instantly now, which is great but for some reason in freecodecamp the test times out and I noticed something strange.

image

I used a new link, and as you can see it logs the link once and then it redirects to it when both if statements are executed and it works almost instantly.

But strangely when it does it with the freecodecamp test link, it saves just fine, but when it tries to redirect it gets stuck and doesn’t redirect to anything.
image

image

I have a added a 100 attempt cap so that this doesn’t go indefinitely. I’m not sure what’s wrong.

Here’s the new index file with everything: new index.js - Pastebin.com

Your new pastebin link is 404. repl.it is your friend.

There shouldn’t be any delays between saving and fetching since there’s only one instance of the program unless you have missed an await on something async. Your id should be unique, so using findOne() should give you the one, so there shouldn’t be a need to iterate whilst finding. The easiest unique ID to use is the already supplied mongoDB _id.

You’ll need to log the ID (req.params) provided as input to the redirect route to see what is happening. My guess is the route is not getting what you expect as input. It should be whatever you are providing during the save as short_url in the JSON response.

My bad, here it is: index.js - Pastebin.com

I don’t use replit because it’s really slow for me and the tests time out for me but i made a repository anyways in case you want to test it there.

URL Shortener - Replit

There are several issues. First, you’ve mixed async and callbacks throughout the route. Try to stick with one style (either async/await or callbacks) and make sure you’re finishing all your asynchronous operations before constructing the response. I’m not sure if your routes will work with the mix as I rewrote them for testing.

Second, the URL regular expression is causing problems. With yours, the failing test produces

POST
req.body: {"url":"https://url-shortener.jeremyagray.repl.co/?v=1653450828787"}
req.params: {}
req.query: {}
bad URL
{ error: 'invalid url' }
GET
req.body: {}
req.params: {"id":"undefined"}
req.query: {}

when I add the appropriate logging. This type of URL passes the first time, but never the second. Using a more permissive regular expression works (with fixed async handling). Something is just not right with yours and I did not debug it.

So you can use a better regular expression or use the hostname based verification from the dns module.

1 Like

Yeah the regex didn’t work half the time now that I tested it properly, I changed it to a new one and it works fine now. I’ll keep that in mind for future projects. I also changed it to only use async await now instead of mixing it with callbacks like you said.

thank you for your help and your feedback!