Let's create a URL expander with Node.JS
Shuvo
Posted on November 19, 2021
Yep we are creating a URL expander not a URL shortener
There are many tools like bitly, shorturl etc. through which we can convert our long and messy URL into a short and better looking URL. For example https://www.youtube.com/c/AngleBrace can become shorturl.at/asIW4.
But URL expander will do the opposite.
So we can get the original long URL from the short URL using it.
But why?
Well some bad guy can take this virus download link eg. https://www.badsite.com/virus.exe and shorten it to https://shorturl.at/wDPZ5. And now just by seeing the short URL you won't be able to tell that this link downloads a virus. So sometimes to prevent viruses and inappropriate websites we can use a URL Expander.
Lets start.
You can also see the video version on YouTube
So create a folder for the project. And open it up in the terminal. And then run npm init -y
to create a new node js project. This will also create a package.json.
After that we need to install some packages. We will need express and request. So install them by running npm i express request
We will also install nodemon as our dev dependency. So we won't have to rerun the JavaScript file each time we make a change. So install it by running npm i nodemon -D
Now in the package.json we will delete the test script and create a start script.
{
"name": "url_expander",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"request": "^2.88.2"
},
"devDependencies": {
"nodemon": "^2.0.15"
}
}
Okay now lets create a index.js file and setup a basic NodeJS and Express project
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})
So now we can create a public folder. Inside that we will create our HTML, CSS and JS file. So our folder structure will look something like this
Okay now in out HTML let's write some markup. We will have 3 main elements
- A input where we can enter the short URL
- Button that will send the request to expand URL
- A element were we will show our expanded URL ```html
<!DOCTYPE html>
Node JS URL Expander
expand
<!-- Expanded URl will be shown here -->
<script src="main.js"></script>
Now lets style it in our **style.css**
```css
*{
margin: 0;
padding: 0;
}
html, body{
height: 100%;
}
body{
background-color: rgb(239, 131, 84);
display: flex;
justify-content: center;
align-items: center;
}
.container{
width: 320px;
padding: 3em;
background-color: rgba(255, 255, 255, 0.3);
}
.input-box{
height: 35px;
display: flex;
}
input{
flex-grow: 1;
}
button{
background-color: rgb(233, 95, 35);
color: white;
text-transform: uppercase;
}
input, button{
padding: 0 1em;
display: block;
border: none;
outline: none;
}
#result{
color: white;
word-break: break-all;
font-size: 1.2em;
text-align: center;
display: block;
margin-top: 1em;
}
So now if we start our server by running npm start
and go to localhost:3000
we should see this page
Great Now in our main.js lets make it so when we click on the button it sends a request to /expand
and displays the response.
const input = document.querySelector('#input')
const expandBtn = document.querySelector('#expand-btn')
const result = document.querySelector('#result')
expandBtn.addEventListener('click', () => {
// Initally set the result to loading
result.innerText = 'Loading ...'
fetch(`/expand`)
.then(res => res.text())
.then(text => {
// Display the result send from the server
result.innerText = text
})
.catch(err => {
console.log(err)
result.innerText = 'Error'
})
})
Now in our index.js lets create the /expand
route.
const express = require('express')
const app = express()
app.use(express.static('public'))
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
app.get('/expand', (req, res) => {
res.send("hello")
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})
So now if we click on the button it should display hello
Okay now in out main.js when sending request to /expand
lets also send our inputs value as a query parameter.
const input = document.querySelector('#input')
const expandBtn = document.querySelector('#expand-btn')
const result = document.querySelector('#result')
expandBtn.addEventListener('click', () => {
result.innerText = 'Loading ...'
// passing the input value to the server as shortUrl query string
fetch(`/expand?shortUrl=${input.value}`)
.then(res => res.text())
.then(text => {
result.innerText = text
})
.catch(err => {
console.log(err)
result.innerText = 'Error'
})
})
So now we can get the input value in our index.js
app.get('/expand', (req, res) => {
let shortUrl = req.query.shortUrl
res.send("hello")
})
And now finally we can use the request package we installed earlier to get the original URL of our short URL
const express = require('express')
const request = require('request')
const app = express()
app.use(express.static('public'))
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
app.get('/expand', (req, res) => {
let shortUrl = req.query.shortUrl
// If the shortUrl doesn't start with http, add add https:// in front of it
// So eg. example.com becomes https://example.com
if(!shortUrl.startsWith('http')) shortUrl = 'https://' + shortUrl
request({
url: shortUrl,
method: "HEAD",
followAllRedirects: true
},
(err, response, body) => {
if (err) {
console.log(err)
res.send("Error")
} else {
// Sending back the full url
res.send(response.request.href)
}
})
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})
And now our project is complete. So enter a short URL like shorturl.at/aoqyO and click on expand and it should display the full URL
You can the finished codes here
Make sure you checkout my other articles and YouTube Channel
Was it helpful? Support me on Patreon
Posted on November 19, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.