Skip to content

Commit cd3e68c

Browse files
authored
Adding UrlShortener (thombergs#219)
1 parent 06af47e commit cd3e68c

26 files changed

+30995
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
MONGO_URI= mongodb+srv://ajibadee:[email protected]/?retryWrites=true&w=majority
2+
DOMAIN_URL=http://localhost:3333
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const mongoose = require("mongoose");
2+
3+
const UrlSchema = new mongoose.Schema({
4+
urlId: {
5+
type: String,
6+
required: true,
7+
},
8+
origUrl: {
9+
type: String,
10+
required: true,
11+
},
12+
shortUrl: {
13+
type: String,
14+
required: true,
15+
},
16+
clicks: {
17+
type: Number,
18+
required: true,
19+
default: 0,
20+
},
21+
date: {
22+
type: String,
23+
default: Date.now,
24+
},
25+
});
26+
27+
module.exports = mongoose.model("Url", UrlSchema);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
function validateUrl(value) {
2+
var urlPattern = new RegExp(
3+
"^(https?:\\/\\/)?" + // validate protocol
4+
"((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|" + // validate domain name
5+
"((\\d{1,3}\\.){3}\\d{1,3}))" + // validate OR ip (v4) address
6+
"(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*" + // validate port and path
7+
"(\\?[;&a-z\\d%_.~+=-]*)?" + // validate query string
8+
"(\\#[-a-z\\d_]*)?$",
9+
"i"
10+
);
11+
12+
return !!urlPattern.test(value);
13+
}
14+
15+
module.exports = { validateUrl };
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
const dotenv = require("dotenv");
2+
const express = require("express");
3+
const cors = require("cors");
4+
const mongoose = require("mongoose");
5+
const shortid = require("shortid");
6+
const Url = require("./Url");
7+
const utils = require("./Util/util");
8+
9+
// configure dotenv
10+
dotenv.config();
11+
const app = express();
12+
13+
// cors for cross origin requesters to the frontend application
14+
app.use(cors());
15+
//
16+
app.use(express.json());
17+
18+
// Database connection
19+
mongoose
20+
.connect(process.env.MONGO_URI, {
21+
useNewUrlParser: true,
22+
useUnifiedTopology: true,
23+
})
24+
.then(() => {
25+
console.log(`Db Connected`);
26+
})
27+
.catch(err => {
28+
console.log(err.message);
29+
});
30+
31+
// get all saved URLs
32+
app.get("/all", async (req, res, next) => {
33+
Url.find((error, data) => {
34+
if (error) {
35+
return next(error);
36+
} else {
37+
res.json(data);
38+
}
39+
});
40+
});
41+
42+
// URL shortener endpoint
43+
app.post("/short", async (req, res) => {
44+
console.log("HERE", req.body.url);
45+
const { origUrl } = req.body;
46+
const base = process.env.DOMAIN_URL;
47+
48+
const urlId = shortid.generate();
49+
if (utils.validateUrl(origUrl)) {
50+
try {
51+
let url = await Url.findOne({ origUrl });
52+
if (url) {
53+
res.json(url);
54+
} else {
55+
const shortUrl = `${base}/${urlId}`;
56+
57+
url = new Url({
58+
origUrl,
59+
shortUrl,
60+
urlId,
61+
date: new Date(),
62+
});
63+
64+
await url.save();
65+
res.json(url);
66+
}
67+
} catch (err) {
68+
console.log(err);
69+
res.status(500).json("Server Error");
70+
}
71+
} else {
72+
res.status(400).json("Invalid Original Url");
73+
}
74+
});
75+
76+
// redirect endpoint
77+
app.get("/:urlId", async (req, res) => {
78+
try {
79+
const url = await Url.findOne({ urlId: req.params.urlId });
80+
console.log(url);
81+
if (url) {
82+
url.clicks++;
83+
url.save();
84+
return res.redirect(url.origUrl);
85+
} else res.status(404).json("Not found");
86+
} catch (err) {
87+
console.log(err);
88+
res.status(500).json("Server Error");
89+
}
90+
});
91+
92+
// Port Listenning on 3333
93+
const PORT = process.env.PORT || 3333;
94+
app.listen(PORT, () => {
95+
console.log(`Server is running at PORT ${PORT}`);
96+
});

0 commit comments

Comments
 (0)