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