Created
August 18, 2021 13:30
-
-
Save flacial/d925d9fb41a4c3bb4b667a9a36b1ad83 to your computer and use it in GitHub Desktop.
URL Shortener - ExpressJS/Postgresql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Steps: | |
0. Choose a method to save the shortUrl and originalUrl (Database or file) | |
1. Create an endpoint (GET "/pathName/:shortUrlParameter") to validate the shortUrl and redirect | |
the user to the corresponding originalUrl | |
2. Create an endpoint (POST "/pathName") to create new shorten links | |
*/ | |
// Backend Framework. | |
import express from "express"; | |
// SQL query builder. | |
import Knex from "knex"; | |
// Random ids generator. | |
import shortid from "shortid"; | |
// Secure Express app by setting various headers. | |
import helmet from "helmet"; | |
// Initialize express instance. | |
const app = express(); | |
// Middleware to parse body (JSON) before handler. | |
app.use(express.json()); | |
// Middleware to secure the app. | |
app.use(helmet()); | |
// Connect to a database. | |
const db = Knex({ | |
// Database client (Postgres, MongoDB, Mysql,...etc). | |
client: "pg", | |
connection: { | |
// connectionString has all the required details (user, password, port, database) to make a connection. | |
connectionString: process.env.DATABASE_URL, | |
ssl: { | |
// rejectUnauthorized is used specifically for free Heroku postgress database. | |
rejectUnauthorized: false, | |
}, | |
}, | |
}); | |
// Endpoint that run a handler function whenever it's called with a shortLink parameter (E.g., potato.com/urls/someParameter). | |
app.get("/urls/:shortLink", (req, res) => { | |
// Extract the shortLink from the req.params. | |
const { shortLink } = req.params; | |
// Check if the database has the shortLink. | |
db.select("longurl") | |
.from("links") | |
.where("shorturl", shortLink) // return the records that are equal to shortLink from shorturl column. | |
.then((record) => { | |
// record is an array with the records as objects [{record}]. | |
if (record.length) return res.status(301).redirect(record[0].longurl); | |
// Object has to be turned into a string for it to be sent. | |
res.status(400).send( | |
JSON.stringify({ | |
error: { | |
message: "Provide a valid shorten link", | |
}, | |
}) | |
); | |
}) | |
.catch((err) => { | |
return res.status(500).send({ | |
message: "Server Error", | |
}); | |
}); | |
}); | |
/* | |
Endpoint that run a handler function whenever it's called with a POST request body containing | |
an originUrl variable (E.g., potato.com/urls) | |
Example request body for POST request: | |
{ | |
"originUrl": "https://google.com" | |
} | |
*/ | |
app.post("/urls", (req, res) => { | |
const { originUrl } = req.body; | |
if (originUrl) { | |
const shortUrl = shortid.generate(); | |
// The current host full URL (E.g., https://nyaasi-url-shortener.herokuapp.com/) | |
const hostUrl = `${req.protocol}://${req.get("Host")}${req.originalUrl}/`; | |
// It reads like "Insert longUrl and shortUrl into links table" | |
db("links").insert([{ longurl: originUrl, shorturl: shortUrl }]).catch(err => {throw err}) | |
// Send back shortenUrl and originUrl to the requester | |
return res.status(201).send({ | |
shortenUrl: hostUrl + shortUrl, | |
originUrl, | |
}); | |
} | |
}); | |
// Port for the app (server) to run/listen on for requests | |
app.listen(process.env.PORT || 3000); | |
/* | |
Additional info: | |
GET request method is used to literally get data from an API. | |
POST request method is used to create new data. | |
process.env.X is the (secret) environment variable. In original script, they were used for Heroku. | |
res.status(CODE).send(): used to send a reponse (text, json, file) with a status code like 200 for successful requests or | |
401 for unauthorized requests. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment