Last active
October 14, 2023 21:28
-
-
Save mayankchoubey/1e02b1be665b710a43271290f51f5a40 to your computer and use it in GitHub Desktop.
Node.js - Native URL shortener service in PostgreSQL
This file contains hidden or 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
| import { DataTypes, Sequelize } from "sequelize"; | |
| const dbUser = process.env.dbUser; | |
| const dbUserPass = process.env.dbUserPass; | |
| const dbName = process.env.dbName; | |
| const sequelize = new Sequelize( | |
| `postgres://${dbUser}:${dbUserPass}@localhost:5432/${dbName}`, | |
| { | |
| logging: false, | |
| pool: { | |
| max: 10, | |
| min: 10, | |
| }, | |
| }, | |
| ); | |
| await sequelize.authenticate(); | |
| const ShortenedUrl = sequelize.define("shortenedurl", { | |
| id: { | |
| type: DataTypes.STRING, | |
| primaryKey: true, | |
| }, | |
| srcurl: DataTypes.STRING, | |
| created: DataTypes.DATE, | |
| lastaccessed: DataTypes.DATE, | |
| }, { | |
| timestamps: false, | |
| }); | |
| export async function save(id, srcUrl) { | |
| await ShortenedUrl.create({ | |
| id, | |
| srcurl: srcUrl, | |
| created: new Date(), | |
| lastaccessed: new Date(), | |
| }); | |
| return true; | |
| } |
This file contains hidden or 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
| import { shorten } from "./service.mjs"; | |
| export function handleRequest(req, res) { | |
| let rawBody = []; | |
| req | |
| .on("data", (chunk) => { | |
| rawBody.push(chunk); | |
| }) | |
| .on("end", () => { | |
| rawBody = Buffer.concat(rawBody).toString(); | |
| processRequest(req, res, rawBody); | |
| }); | |
| } | |
| async function processRequest(req, res, rawBody) { | |
| const ctHdr = req.headers["content-type"]; | |
| if (!(ctHdr && ctHdr.includes("application/json"))) { | |
| res.writeHead(415); | |
| return res.end(getErrJSON("Content type JSON is required")); | |
| } | |
| let reqBody; | |
| try { | |
| reqBody = JSON.parse(rawBody); | |
| } catch (e) { | |
| console.log(e); | |
| res.writeHead(400); | |
| return res.end(getErrJSON("Request body is not a valid JSON")); | |
| } | |
| if (!reqBody.srcUrl) { | |
| res.writeHead(400); | |
| return res.end(getErrJSON("Parameter 'srcUrl' is missing")); | |
| } | |
| const srcUrl = reqBody.srcUrl; | |
| if (srcUrl.length > 250) { | |
| res.writeHead(400); | |
| return res.end( | |
| getErrJSON("Parameter 'srcUrl' must not be more than 250 characters"), | |
| ); | |
| } | |
| if (!(srcUrl.startsWith("http://") || srcUrl.startsWith("https://"))) { | |
| res.writeHead(400); | |
| return res.end( | |
| getErrJSON("Parameter 'srcUrl' must start with http:// or https://"), | |
| ); | |
| } | |
| const shortenedUrl = await shorten(srcUrl); | |
| if (!shortenedUrl) { | |
| res.writeHead(500); | |
| return res.end(getErrJSON("Failed to shorten")); | |
| } | |
| res.writeHead(200); | |
| res.end(JSON.stringify({ srcUrl, shortenedUrl })); | |
| } | |
| function getErrJSON(errMsg) { | |
| return JSON.stringify({ errMsg }); | |
| } |
This file contains hidden or 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
| import http from "http"; | |
| import { handleRequest } from "./nativeController.mjs"; | |
| function requestListener(req, res) { | |
| if (req.method !== "POST") { | |
| res.writeHead(405); | |
| return res.end(JSON.stringify({ errMsg: `${req.method} not allowed` })); | |
| } | |
| if (req.url != "/shorten") { | |
| res.writeHead(404); | |
| return res.end(JSON.stringify({ errMsg: `${req.url} not supported` })); | |
| } | |
| handleRequest(req, res); | |
| } | |
| http | |
| .createServer(requestListener) | |
| .listen(3000, "localhost"); |
This file contains hidden or 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
| import { nanoid } from "nanoid"; | |
| import { save } from "./db.mjs"; | |
| const baseUrl = "http://test.short/"; | |
| export async function shorten(srcUrl) { | |
| if (!srcUrl) { | |
| return; | |
| } | |
| const urlId = nanoid(10); | |
| const shortenedUrl = `${baseUrl}${urlId}`; | |
| const dbStatus = await save(urlId, srcUrl); | |
| return dbStatus ? shortenedUrl : undefined; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment