mirror of
https://codeberg.org/buzzcode2007/FCC-Project-URLShortener.git
synced 2025-05-21 03:06:34 +00:00
Create the API and management
This commit is contained in:
parent
02709cccf4
commit
31e074a5a8
3 changed files with 213 additions and 0 deletions
95
scripts/API.js
Executable file
95
scripts/API.js
Executable file
|
@ -0,0 +1,95 @@
|
||||||
|
// Import modules
|
||||||
|
var URLManage = require(`./database/URLs`).URLManage;
|
||||||
|
var Messaging = require(`./utilities/messaging`).Messaging;
|
||||||
|
const bodyParser = require('body-parser');
|
||||||
|
|
||||||
|
class ShortenAPI {
|
||||||
|
/*
|
||||||
|
Paths used by this API.
|
||||||
|
*/
|
||||||
|
#paths = {
|
||||||
|
"create": ["/api/shorturl"],
|
||||||
|
"access": ["/:ID", "/api/shorturl/:ID"]
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create the URL shortener parser API.
|
||||||
|
|
||||||
|
@param {Express} INSTANCE - The Express instance
|
||||||
|
*/
|
||||||
|
constructor (INSTANCE) {
|
||||||
|
this[`instance`] = INSTANCE;
|
||||||
|
this[`instance`].use(bodyParser.json());
|
||||||
|
this[`instance`].use(bodyParser.urlencoded({extended: true}));
|
||||||
|
|
||||||
|
this[`management`] = new URLManage;
|
||||||
|
|
||||||
|
this.prepareRedirect();
|
||||||
|
this.startCreation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Redirect from the short link.
|
||||||
|
*/
|
||||||
|
prepareRedirect() {
|
||||||
|
const findRedirect = (REQUEST, RESPONSE) => {
|
||||||
|
const redirectBrowser = (URL) => {
|
||||||
|
return((URL) ? RESPONSE.redirect(URL) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
((Object.keys(REQUEST.params).length)
|
||||||
|
? REQUEST.params.ID
|
||||||
|
: false) ?
|
||||||
|
this[`management`].open(REQUEST.params.ID, redirectBrowser)
|
||||||
|
: false;
|
||||||
|
} catch(ERR) {
|
||||||
|
Messaging.exception(RESPONSE, ERR);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
this.#paths[`access`].forEach((PATH) => {
|
||||||
|
this[`instance`].get(PATH, findRedirect)
|
||||||
|
console.log(`Redirection ready on ${PATH}.`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Enable receiving requests.
|
||||||
|
*/
|
||||||
|
startCreation() {
|
||||||
|
const redirect = (REQUEST, RESPONSE) => {
|
||||||
|
try {
|
||||||
|
let QUERY = {};
|
||||||
|
if ((REQUEST.body) ? Object.keys(REQUEST.body).length : false) {
|
||||||
|
QUERY = REQUEST.body;
|
||||||
|
} else if ((REQUEST.query) ? Object.keys(REQUEST.query).length : false) {
|
||||||
|
QUERY = REQUEST.query;
|
||||||
|
}
|
||||||
|
|
||||||
|
let RESULT = {};
|
||||||
|
RESULT[`original_url`] = QUERY[`url`];
|
||||||
|
|
||||||
|
|
||||||
|
const sendRedirect = (HASH) => {
|
||||||
|
RESULT[`short_url`] = HASH;
|
||||||
|
RESPONSE.json(RESULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
this[`management`].create(RESULT[`original_url`], sendRedirect);
|
||||||
|
} catch(ERR) {
|
||||||
|
Messaging.exception(RESPONSE, ERR);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
[`get`, `post`].forEach((METHOD) => {
|
||||||
|
this.#paths[`create`].forEach((PATH) => {
|
||||||
|
this[`instance`][METHOD](PATH, redirect);
|
||||||
|
console.log(`Creation ready on ${PATH} for method ${METHOD}.`)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {ShortenAPI};
|
97
scripts/database/URLs.js
Executable file
97
scripts/database/URLs.js
Executable file
|
@ -0,0 +1,97 @@
|
||||||
|
const Mongoose = require(`mongoose`);
|
||||||
|
const DBManagement = require(`./management`).DBManagement;
|
||||||
|
const URLs = require(`../utilities/URLs`).URLs;
|
||||||
|
const CustomErrors = require(`../utilities/errors`).CustomErrors;
|
||||||
|
const HashTools = require(`../utilities/hash`).HashTools;
|
||||||
|
|
||||||
|
class URLManage extends DBManagement {
|
||||||
|
/*
|
||||||
|
Begin the URL management and connection.
|
||||||
|
*/
|
||||||
|
constructor () {
|
||||||
|
super(`localhost:27017`);
|
||||||
|
|
||||||
|
this.schema = new Mongoose.Schema({
|
||||||
|
"original": {"type": String, "required": true},
|
||||||
|
"shortened": {"type": String, "required": true}
|
||||||
|
});
|
||||||
|
|
||||||
|
this[`state`].then(() => {this.model = this[`connection`].model(`URL`, this[`schema`]);})
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Open the original URL given an identifier.
|
||||||
|
|
||||||
|
@param {string} ID the ID
|
||||||
|
@param {function} done the callback function when successful
|
||||||
|
@return {string} the original URL
|
||||||
|
*/
|
||||||
|
open (ID, done) {
|
||||||
|
this.state.then(() => {
|
||||||
|
this.model.findOne({"shortened": ID}).then((DATA) => {
|
||||||
|
console.log((DATA) ? `Lengthened shortened URL with ID ${ID} to ${DATA[`original`]}.` : `No shortened URL with ID ${ID}.`);
|
||||||
|
return done((DATA) ? DATA[`original`] : null);
|
||||||
|
}).catch((ERR) => {
|
||||||
|
throw ERR;
|
||||||
|
})
|
||||||
|
}).catch((ERROR) => {throw new CustomErrors.DBProblem(ERROR.message)});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Search for a short link given a URL.
|
||||||
|
|
||||||
|
@param {string} URL the URL to shorten
|
||||||
|
@param {function} done the callback function when successful
|
||||||
|
@return {string} ID the ID
|
||||||
|
*/
|
||||||
|
search(URL, done) {
|
||||||
|
// Throw an error for an incorrect URL.
|
||||||
|
if (!URLs.test(URL)) {
|
||||||
|
throw new CustomErrors.URL(null, URL);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.state.then(() => {
|
||||||
|
this.model.findOne({"original": URL}).then((DATA) => {
|
||||||
|
console.log((DATA) ? `The ID ${DATA[`shortened`]} refers to ${URL}.` : `No ID pertains to ${URL}.`);
|
||||||
|
return done((DATA) ? DATA[`shortened`] : null);
|
||||||
|
}).catch((ERR) => {
|
||||||
|
throw ERR;
|
||||||
|
});
|
||||||
|
}).catch((ERROR) => {throw new CustomErrors.DBProblem(ERROR.message)})
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Shorten the URL.
|
||||||
|
|
||||||
|
@param {string} URL the URL to shorten
|
||||||
|
@param {function} done the callback function
|
||||||
|
@return {string} ID the ID
|
||||||
|
*/
|
||||||
|
create(URL, done) {
|
||||||
|
// Throw an error for an incorrect URL.
|
||||||
|
if (!URLs.test(URL)) {
|
||||||
|
throw new CustomErrors.URL(null, URL);
|
||||||
|
};
|
||||||
|
|
||||||
|
let ENTRY = {"original": URL};
|
||||||
|
const save = (ID) => {
|
||||||
|
(ID)
|
||||||
|
? done(ID)
|
||||||
|
: HashTools.digest(URL, {"output": "Number"}).then((HASH) => {
|
||||||
|
ENTRY[`shortened`] = HASH;
|
||||||
|
|
||||||
|
let DOCUMENT = new this.model(ENTRY);
|
||||||
|
|
||||||
|
this.state.then(() => {
|
||||||
|
DOCUMENT.save().then((DATA) => {done(HASH)}).catch((ERR) => {throw ERR;})
|
||||||
|
}).catch((ERROR) => {throw new CustomErrors.DBProblem(ERROR.message)});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.search((ENTRY[`original`]), save);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {URLManage};
|
21
scripts/database/management.js
Normal file
21
scripts/database/management.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
const Mongoose = require(`mongoose`);
|
||||||
|
const CustomErrors = require(`../utilities/errors`).CustomErrors;
|
||||||
|
|
||||||
|
class DBManagement {
|
||||||
|
/*
|
||||||
|
Begin the connection.
|
||||||
|
|
||||||
|
@param {string} DOMAIN the domain
|
||||||
|
@param {string} DBNAME the database name
|
||||||
|
*/
|
||||||
|
constructor (DOMAIN, DBNAME) {
|
||||||
|
const throwError = (ERROR) => {throw ERROR;};
|
||||||
|
|
||||||
|
this[`state`] = Mongoose.connect(`mongodb://${DOMAIN}/${(DBNAME) ? DBNAME : ""}`, { useNewUrlParser: true, useUnifiedTopology: true }).then((CONNECTION) => {
|
||||||
|
this[`connection`] = CONNECTION.connection;
|
||||||
|
console.log(`Connection successful.`);
|
||||||
|
}).catch(throwError);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {DBManagement};
|
Loading…
Add table
Add a link
Reference in a new issue