Create the API and management

This commit is contained in:
buzzcode2007 2025-03-23 07:48:47 +00:00
parent 02709cccf4
commit 31e074a5a8
3 changed files with 213 additions and 0 deletions

95
scripts/API.js Executable file
View 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
View 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};

View 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};