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