URL Shortener Microservice issue

Hi everyone, this is my firs topic on FCC, until now i’ve always found help from your posts.
In any case, i have a problem with the third test of this challenge:

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' }

Even if i use dns.lookup or valid-url i not pass this test, and when i insert a wrong link to the url shortener site, i got an error message like this:

TypeError [ERR_INVALID_URL]: Invalid URL: fersa
at onParseError (internal/url.js:258:9)
at new URL (internal/url.js:334:5)
at /home/runner/Barabba-URL-Shortener-FCC/server.js:45:16
at Layer.handle [as handle_request] (/home/runner/Barabba-URL-Shortener-FCC/node_modules/express/lib/router/layer.js:95:5)
at next (/home/runner/Barabba-URL-Shortener-FCC/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/runner/Barabba-URL-Shortener-FCC/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/runner/Barabba-URL-Shortener-FCC/node_modules/express/lib/router/layer.js:95:5)
at /home/runner/Barabba-URL-Shortener-FCC/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/home/runner/Barabba-URL-Shortener-FCC/node_modules/express/lib/router/index.js:335:12)
at next (/home/runner/Barabba-URL-Shortener-FCC/node_modules/express/lib/router/index.js:275:10)

but not a json response…

Here the code:

require('dotenv').config();
const express = require('express');
const cors = require('cors');
const mongodb = require('mongodb');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const app = express();
const dns = require('dns');
const URL = require('url').URL;
const { nanoid } = require('nanoid');

const MONGO_URI="mongodb+srv://BarabbaFDM:" + process.env['PW'] + "@cluster0.43tgt.mongodb.net/db1?retryWrites=true&w=majority";

mongoose.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });

// Basic Configuration
const port = process.env.PORT || 3000;

app.use(cors());

app.use('/public', express.static(`${process.cwd()}/public`));

app.get('/', function(req, res) {
  res.sendFile(process.cwd() + '/views/index.html');
});

//Schema and model to store saved URLS
var ShortURL = mongoose.model('ShortURL', new mongoose.Schema({
  original_url: String,
  short_url: String,
}));

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

//Post data to the server, request URL, check if it is valid,
//send the shortened url to DB
app.post("/api/shorturl/", (req, res, next) => {

  let original_url = req.body.url;
  //Variable for dns.lookup
  let newURL = new URL(original_url);

  //Validate URL
  dns.lookup(newURL.hostname, (err, address, family) => {
    if (err) {
      res.json({
        error: 'invalid url'
      });
    } else {
      let short_url = nanoid()
          
      //Create an object and save it to the DB
      let newURL = new ShortURL({
        original_url: original_url,
        short_url: short_url
      });

      newURL.save((err, data) => {
        if (err) return console.error(err);
      });

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

app.get("/api/shorturl/:short_url", (req, res) => {
  let short_url = req.params.short_url;

  ShortURL.findOne({short_url: short_url}, (err, data) => {
    if (err) return console.log(err);
    
    res.redirect(301, data.original_url);
    });
  });

// Your first API endpoint
app.get('/api/hello', function(req, res) {
  res.json({ greeting: 'hello API' });
});

app.listen(port, function() {
  console.log(`Listening on port ${port}`);
});

Thank you everyone for your help!

Your project link(s)

code: Barabba - URL Shortener - FCC - Replit

Your browser information:

User Agent is: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0

Challenge: URL Shortener Microservice

Link to the challenge:

The error message shows which line is throwing an error:

at /home/runner/Barabba-URL-Shortener-FCC/server.js:45:16

Which is the following line:

let newURL = new URL(original_url);

If you look at the documentation for new URL():

A TypeError will be thrown if the input or base are not valid URLs.

So, if you use new URL() you will have to catch that error.

2 Likes

I tryed but now the page load forever :thinking:

Not entirely sure what the problem is with your code, but since there is only one line that trows an exception it might be better to just wrap that one line inside a try/catch block:

let newUrl;
try {
  newURL = new URL(original_url);
} catch(e) {
  return res.json({
    error: 'invalid url'
  });
}
1 Like

Like this the code work on replit, but the test on fcc doesn’t pass anyway…I’m going crazy

You can find the exact code that FCC is running for each test here: https://github.com/freeCodeCamp/freeCodeCamp/blob/main/curriculum/challenges/english/05-back-end-development-and-apis/back-end-development-and-apis-projects/url-shortener-microservice.md

The failing test (invalid url) expects the url ‘ftp:/john-doe.org’ to be invalid. However, if you POST this url, it will actually return a short url instead of an error message.

1 Like

I tryed to POST the url ‘ftp:/john-doe.org’ on the example site from the challenge and the page is loading forever. In my case instead i get a short url. In any case i don’t know how to complete this challenge :sweat_smile:
Thank you for your patience!

Ok i finally solved the challenge thanks to another user’s solution ! :grin:

Now it works.

The code:

require('dotenv').config();
const express = require('express');
const cors = require('cors');
const mongodb = require('mongodb');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const app = express();
const dns = require('dns');
//const URL = require('url').URL;
const { nanoid } = require('nanoid');

const MONGO_URI="mongodb+srv://BarabbaFDM:" + process.env['PW'] + "@cluster0.43tgt.mongodb.net/db1?retryWrites=true&w=majority";

mongoose.connect(MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });

// Basic Configuration
const port = process.env.PORT || 3000;

app.use(cors());

app.use('/public', express.static(`${process.cwd()}/public`));

app.get('/', function(req, res) {
  res.sendFile(process.cwd() + '/views/index.html');
});

//Schema and model to store saved URLS
var ShortURL = mongoose.model('ShortURL', new mongoose.Schema({
  original_url: String,
  short_url: String,
}));

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

let urlExtractor = function(url) {
  var urlSplit = url.split("https://");
  if (urlSplit[1] == undefined) {
    return urlSplit[0].split("/")[0];
  } else {
    return urlSplit[1].split("/")[0];
  }
};

//Post data to the server, request URL, check if it is valid,
//send the shortened url to DB
app.post("/api/shorturl/", (req, res, next) => {
  let original_url = req.body.url;
  let extractedUrl = urlExtractor(original_url);
  
  /*//Variable for dns.lookup
  let newURL;

  try{
    newURL = new URL(original_url);
  } catch (err){
    return res.json({
      error: "invalid url"
    });
  }*/

  //Validate URL
  dns.resolveAny(extractedUrl, (err) => {
    if (err) {
      res.json({
        error: 'invalid url'
      });
    } else {
      let short_url = nanoid()
          
      //Create an object and save it to the DB
      let newURL = new ShortURL({
        original_url: original_url,
        short_url: short_url
      });

      newURL.save((err, data) => {
        if (err) return console.error(err);
      });

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

app.get("/api/shorturl/:short_url", (req, res) => {
  let short_url = req.params.short_url;

  ShortURL.findOne({short_url: short_url}, (err, data) => {
    if (err) return console.log(err);
    
    res.redirect(301, data.original_url);
    });
  });

// Your first API endpoint
app.get('/api/hello', function(req, res) {
  res.json({ greeting: 'hello API' });
});

app.listen(port, function() {
  console.log(`Listening on port ${port}`);
});

Thank you very much for your availability!

1 Like

Glad the solution helped you ! :innocent:

1 Like

Definitely, learned a lot with this one!

1 Like

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