Add Static Resource Hosting (#8)
* Add ability to host files from web API rather than using the static site files.hyperling.com. * Add details. * Prevent further files from being committed in the static resource folder. * Beginnings of a photo share from the website to replace PhotoPrism. * Fix log message for files route. * Allow customization of ports via shell script. * Update README goals and fix URLs. * FInalize the PHOTOS page, complete with video controls! * Moe enhancements, such as displaying README's and adding [VIDEO] tag. * Clean file a little. * Remove TODO.
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -105,3 +105,4 @@ dist | |||||||
|  |  | ||||||
| ## Above is Github's recommendations for Node.js. Below are my additions. ## | ## Above is Github's recommendations for Node.js. Below are my additions. ## | ||||||
| package-lock.json | package-lock.json | ||||||
|  | files/* | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								README.md
									
									
									
									
									
								
							| @@ -14,25 +14,29 @@ All content is formatted so that the page source is readible. | |||||||
|  |  | ||||||
| # How To Run | # How To Run | ||||||
|  |  | ||||||
| The install script is currently only set up for apt, and the package names only tested on Ubuntu.  | The install script is currently only set up for apt, and the package names only | ||||||
|  | tested on Ubuntu and Debian. | ||||||
|  |  | ||||||
| `git clone https://github.com/Hyperling/www www` | ``` | ||||||
|  | git clone https://github.com/Hyperling/website www | ||||||
|  | cd www | ||||||
|  | ./run.sh | ||||||
|  | ``` | ||||||
|  |  | ||||||
| `cd www` | Then in a web browser, navigate to `localhost:8080`. | ||||||
|  |  | ||||||
| `./run.sh` |  | ||||||
|  |  | ||||||
| Then in a web browser, navigate to `your_machines_ip_address:8080`. |  | ||||||
|  |  | ||||||
| ## TODO | ## TODO | ||||||
|  |  | ||||||
| All goals are currently completed. | All goals are currently completed. | ||||||
|  |  | ||||||
|  | - ~~Add support for Let's Encrypt without using `nginx` or `apache`.~~ | ||||||
|  |     - Going to continue using a reverse proxy, but may still be nice someday. | ||||||
|  |  | ||||||
| ## Inspiration | ## Inspiration | ||||||
|  |  | ||||||
| - [https://liquorix.net/] | - [Liquorix Kernel](https://liquorix.net/) | ||||||
|   - The linux-zen kernel, a really great one if you're running FOSS OS's! |   - The linux-zen kernel, a really great one if you're running FOSS OS's! | ||||||
| - [https://cahlen.org/] | - [Cahlen.org](https://cahlen.org/) | ||||||
|   - Also has really interesting and important content, it is highly recommended. |   - Also has really interesting and important content, it is highly recommended. | ||||||
| - [https://merkinvineyardsosteria.com/] | - [Merkin Vineyards Osteria](https://merkinvineyardsosteria.com/) | ||||||
|   - A winery website for MJ Keenan. |   - A winery website for MJ Keenan. | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								files/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								files/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | # Hyperling.com - Files | ||||||
|  |  | ||||||
|  | Place files into this folder which should be used as static resources. | ||||||
|  | Examples would be APKs, zip files, images, text files, etc. | ||||||
|  |  | ||||||
|  | For example, if `test.jpg` was placed here, it could be accessed via | ||||||
|  | `http://localhost:8080/files/test.jpg`. Depending on the file type the MIME type | ||||||
|  | may be detected automatically, otherwise it will be assumed a text file and | ||||||
|  | most likely ask to be downloaded by the browser. | ||||||
							
								
								
									
										55
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								main.js
									
									
									
									
									
								
							| @@ -25,7 +25,18 @@ const pages_dir = "./pages/"; | |||||||
| const file_types = ["php", "sh"]; | const file_types = ["php", "sh"]; | ||||||
|  |  | ||||||
| let ports = []; | let ports = []; | ||||||
| ports.push(8080); | // Check parameters for numeric port numbers. | ||||||
|  | process.argv.forEach(function (val, index, array) { | ||||||
|  | 	console.log("Parameter", index + ':', val, !isNaN(val)); | ||||||
|  | 	if (!isNaN(val)) { | ||||||
|  | 		console.log("Adding Port", val) | ||||||
|  | 		ports.push(val); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | // Default port if none were passed. | ||||||
|  | if (ports.length === 0) { | ||||||
|  | 	ports.push(8080); | ||||||
|  | } | ||||||
|  |  | ||||||
| //// Functions //// | //// Functions //// | ||||||
|  |  | ||||||
| @@ -170,6 +181,48 @@ async function main() { | |||||||
| 		res.send(sitemap_html); | 		res.send(sitemap_html); | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
|  | 	// Return a resource from the files folder. | ||||||
|  | 	console.log(" * Creating router for files"); | ||||||
|  | 	router.get('/files*', function (req, res) { | ||||||
|  | 		console.log("file response to", req.socket.remoteAddress, "asking for", req.url) | ||||||
|  |  | ||||||
|  | 		// Build variables. | ||||||
|  | 		const file = "." + req.path; | ||||||
|  | 		const extensions = req.path.split("."); | ||||||
|  | 		const extension = extensions[extensions.length-1]; | ||||||
|  |  | ||||||
|  | 		// Check extension and guess a MIME type. | ||||||
|  | 		let mime; | ||||||
|  | 		switch (extension) { | ||||||
|  | 			case "apk": | ||||||
|  | 				mime = "application/vnd.android.package-archive"; | ||||||
|  | 				break; | ||||||
|  | 			case "jpg" || "jpeg": | ||||||
|  | 				mime = "image/jpeg"; | ||||||
|  | 				break; | ||||||
|  | 			case "png": | ||||||
|  | 				mime = "image/png"; | ||||||
|  | 				break; | ||||||
|  | 			case "html": | ||||||
|  | 				mime = "text/html"; | ||||||
|  | 				break; | ||||||
|  | 			default: | ||||||
|  | 				mime = "text/*"; | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		console.log("- Extension", extension, "led to MIME", mime); | ||||||
|  |  | ||||||
|  | 		// Return the file | ||||||
|  | 		res.contentType(mime); | ||||||
|  | 		let f = fs.createReadStream(file) | ||||||
|  | 			.on("error", function(e) { | ||||||
|  | 				res.contentType("text/plain"); | ||||||
|  | 				res.send(404, "File Not Found"); | ||||||
|  | 			}) | ||||||
|  | 			.pipe(res) | ||||||
|  | 		; | ||||||
|  | 	}); | ||||||
|  |  | ||||||
| 	// Originally a test, now a catch-all redirection to Home! | 	// Originally a test, now a catch-all redirection to Home! | ||||||
| 	console.log(" * Creating router for redirection"); | 	console.log(" * Creating router for redirection"); | ||||||
| 	router.get('/*', function (req, res) { | 	router.get('/*', function (req, res) { | ||||||
|   | |||||||
							
								
								
									
										99
									
								
								pages/photos.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										99
									
								
								pages/photos.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | #!/bin/bash | ||||||
|  | # 2024-01-21 Hyperling | ||||||
|  | # Transition away from PhotoPrism. Helps to save system resources and downsize. | ||||||
|  |  | ||||||
|  | # Static Variables | ||||||
|  | header="<html>\n\t<header>\n\t\t<title>ALBUM</title>\n\t</header>\n\t<body>" | ||||||
|  | footer="\n\t</body>\n</html>" | ||||||
|  | HELPER_DIR=./pages/helpers | ||||||
|  |  | ||||||
|  | # Move to the main project directory. | ||||||
|  | cd `dirname $0`/.. | ||||||
|  |  | ||||||
|  | # Create the necessary HTML components for a web page. | ||||||
|  | $HELPER_DIR/body_open.php | ||||||
|  |  | ||||||
|  | # Give the page a description. | ||||||
|  | echo -e "\n\t\t<h1 class='col-12 title'>Photo Albums</h1>" | ||||||
|  | echo -en "\t\t<p class='col-12 text'>You may click on an album name to view " | ||||||
|  | echo -en "all of its files, or click on a specific image to bring up the full " | ||||||
|  | echo -en "resolution. On the album pages you may also click an image or video " | ||||||
|  | echo -e "name to pull up the full resolution for download.</p>" | ||||||
|  |  | ||||||
|  | # Display the album names descending. | ||||||
|  | ls files/photos/ | sort -r | while read album; do | ||||||
|  | 	# Clean album name. | ||||||
|  | 	album_name=${album} | ||||||
|  | 	album_name=${album_name//_/ } | ||||||
|  | 	album_name=${album_name//-/ } | ||||||
|  | 	echo -en "\t\t<h2 class='col-12 title'>" | ||||||
|  | 	echo -en "<a href='/files/photos/$album/index.html' " | ||||||
|  | 	echo -e "target='_blank' rel='noopener noreferrer'>$album_name</a></h2>" | ||||||
|  | 	echo -e "\t\t<div class='col-12 text'>" | ||||||
|  |  | ||||||
|  | 	# Create index for each photo album based on its contents. | ||||||
|  | 	page="" | ||||||
|  | 	subpage="files/photos/$album/index.html" | ||||||
|  | 	$HELPER_DIR/body_open.php > $subpage | ||||||
|  | 	echo -e "\n\t\t<h1 class='col-12 title'>$album_name</h1>" >> $subpage | ||||||
|  | 	ls files/photos/$album/* | sort | while read photo; do | ||||||
|  | 		# Do not include the index page. | ||||||
|  | 		if [[ $photo == *"index.html" ]]; then | ||||||
|  | 			continue | ||||||
|  | 		fi | ||||||
|  |  | ||||||
|  | 		# Clean filename to be a little more presentable. | ||||||
|  | 		# Going with CAPSLOCK. ;) | ||||||
|  | 		typeset -u filename | ||||||
|  | 		filename="`basename $photo`" | ||||||
|  | 		# Remove extension. | ||||||
|  | 		filename="${filename%%.*}" | ||||||
|  | 		# Remove special characters for spaces. | ||||||
|  | 		filename="${filename//_/ }" | ||||||
|  | 		filename="${filename//-/ }" | ||||||
|  |  | ||||||
|  | 		if [[ $photo == *"/README.md" || $photo == *"/README.txt" ]]; then | ||||||
|  | 			# If there is a README, show it on the PHOTOS page without a link. | ||||||
|  | 			echo -e "\t\t\t<p>`cat $photo`</p>" | ||||||
|  | 		else | ||||||
|  | 			# Otherwise put in the PHOTOS page list. | ||||||
|  | 			echo -en "\t\t\t<li class='indent'><a href=/$photo target='_blank' " | ||||||
|  | 			echo -en "rel='noopener noreferrer'>$filename" | ||||||
|  | 			if [[ $photo == *".mp4" ]]; then | ||||||
|  | 				echo -en " [VIDEO]" | ||||||
|  | 			fi | ||||||
|  | 			echo -e "</a></li>" | ||||||
|  | 		fi | ||||||
|  |  | ||||||
|  | 		# Put in the subpage HTML. | ||||||
|  | 		echo -e "\t\t<div class='col-6 center'>" >> $subpage | ||||||
|  | 		echo -en "\t\t\t<a href=/$photo target='_blank' " >> $subpage | ||||||
|  | 		echo -e "rel='noopener noreferrer'>" >> $subpage | ||||||
|  | 		if [[ $photo == *".mp4" ]]; then | ||||||
|  | 			echo -e "\t\t\t\t<video width='320px' controls>" >> $subpage | ||||||
|  | 			echo -e "\t\t\t\t\t<source src='/$photo' type=video/mp4>" >> $subpage | ||||||
|  | 			echo -e "\t\t\t\t\tYour browser does not support videos." >> $subpage | ||||||
|  | 			echo -e "\t\t\t\t</video>" >> $subpage | ||||||
|  | 		elif [[ $photo == *".md" || $photo == *".txt" ]]; then | ||||||
|  | 			echo -e "\t\t\t\t<p>`cat $photo`</p>" >> $subpage | ||||||
|  | 		else | ||||||
|  | 			echo -e "\t\t\t\t<img src='/$photo'/>" >> $subpage | ||||||
|  | 		fi | ||||||
|  |  | ||||||
|  | 		# Add a descriptive link. | ||||||
|  | 		echo -en "\t\t\t\t<p>$filename" >> $subpage | ||||||
|  | 		if [[ $photo == *".mp4" ]]; then | ||||||
|  | 			echo -en " [VIDEO]" >> $subpage | ||||||
|  | 		fi | ||||||
|  | 		echo -e "</p>\n\t\t\t</a>\n\t\t</div>" >> $subpage | ||||||
|  | 	done | ||||||
|  |  | ||||||
|  | 	# End album on PHOTOS page. | ||||||
|  | 	echo -e "\t\t</div>" | ||||||
|  |  | ||||||
|  | 	# Close out the ALBUM's page. | ||||||
|  | 	$HELPER_DIR/body_close.php >> $subpage | ||||||
|  | done | ||||||
|  |  | ||||||
|  | # Finish the web page. | ||||||
|  | $HELPER_DIR/body_close.php | ||||||
							
								
								
									
										51
									
								
								run.sh
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								run.sh
									
									
									
									
									
								
							| @@ -2,12 +2,46 @@ | |||||||
| # 2022-09-14 Hyperling | # 2022-09-14 Hyperling | ||||||
| # Ensure dependencies are met and start the webserver. | # Ensure dependencies are met and start the webserver. | ||||||
|  |  | ||||||
| # Ensure we are executing from this file's directory. | ## Setup ## | ||||||
| cd `dirname $0` |  | ||||||
|  |  | ||||||
| ### Can docker-compose do this rather than running a sh file on the host OS? | DIR=`dirname $0` | ||||||
| # Look at Dockerfile-ADD for doing git clones into a docker environment.  | PROG=`basename $0` | ||||||
| # Out of scope for this project, this project is just the site, leave for now. |  | ||||||
|  | ## Functions ## | ||||||
|  |  | ||||||
|  | function usage { | ||||||
|  | 	cat <<- EOF | ||||||
|  | 		$PROG calls the main Node.js program after ensuring the project can run. | ||||||
|  | 		  (PORTS) | ||||||
|  | 		    -p : Pass the port numbers that the API/website should listen at. | ||||||
|  | 		         Example: $PROG -p 80 -p 443 -p 8080 | ||||||
|  | 		  (HELP) | ||||||
|  | 		    -h : Show this usage output and exit successfully. | ||||||
|  | 	EOF | ||||||
|  | 	exit $1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ## Parameters ## | ||||||
|  |  | ||||||
|  | while getopts ':p:h' opt; do | ||||||
|  | 	case "$opt" in | ||||||
|  | 		p) (( OPTARG < 1024 )) && [[ $LOGNAME != "root" ]] && { | ||||||
|  | 				echo "WARNING: Port $OPTARG is privileged. Will need to be root." | ||||||
|  | 				exit 1 | ||||||
|  | 			} | ||||||
|  | 			ports="$ports $OPTARG" ;; | ||||||
|  | 		h) usage 0 ;; | ||||||
|  | 		*) echo "ERROR: Option $OPTARG not recognized." >&2 | ||||||
|  | 			usage 1 ;; | ||||||
|  | 	esac | ||||||
|  | done | ||||||
|  |  | ||||||
|  | ## Build Environment ## | ||||||
|  |  | ||||||
|  | # Ensure we are executing from this file's directory. | ||||||
|  | cd $DIR | ||||||
|  |  | ||||||
|  | # Check if any dependencies need installed. | ||||||
| if [[ ! `which php` || ! `which node`|| ! `which npm` ]]; then | if [[ ! `which php` || ! `which node`|| ! `which npm` ]]; then | ||||||
| 	sudo apt install -y php-fpm nodejs npm | 	sudo apt install -y php-fpm nodejs npm | ||||||
| fi | fi | ||||||
| @@ -25,7 +59,10 @@ done | |||||||
|  |  | ||||||
| npm install | npm install | ||||||
|  |  | ||||||
| ./main.js | ## Main ## | ||||||
| ### |  | ||||||
|  | ./main.js $ports | ||||||
|  |  | ||||||
|  | ## Finish ## | ||||||
|  |  | ||||||
| exit $? | exit $? | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 GitHub
						GitHub