Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serving static assets from a specific directory #2

Open
LebCit opened this issue Nov 5, 2023 · 3 comments
Open

Serving static assets from a specific directory #2

LebCit opened this issue Nov 5, 2023 · 3 comments

Comments

@LebCit
Copy link

LebCit commented Nov 5, 2023

Hello,
Thank you very much for your time and efforts to bring this minimalist and effective Node.js framework.
How to serve static assets like CSS, JS and images files from a specific directory using Velocy ?
Consider the following route:

app.get("/", (req, res) => {
	res.writeHead(200, { "Content-Type": "text/html" })
	const page = eta.render("test.html")
	res.end(page)
})

And test.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test page</title>
    <link rel="stylesheet" href="/static/styles/main.css">
</head>
<body>
    <h1>Just a test page</h1>
    <p>Created with Velocy, A blazing fast, minimal backend framework for Node.js, and Eta</p>
</body>
</html>

As you can see I want to load main.css from the styles folder which is in the static folder.
The idea is to have a way to load static assets from a specific folder like other frameworks.

Thanks a lot again for your time and efforts.
SYA

@LebCit
Copy link
Author

LebCit commented Nov 5, 2023

Hello,

Anyone looking for a simple solution, here is my code to load static assets from a folder called static at the root of the app :

import { readFileSync, readdirSync, statSync } from "fs"
import path from "path"

// Function to get files from their directory recursively.
const getFiles = (dirName) => {
	let files = []
	const items = readdirSync(dirName, { withFileTypes: true })

	for (const item of items) {
		if (item.isDirectory()) {
			files = [...files, ...getFiles(`${dirName}/${item.name}`)]
		} else {
			files.push(`${dirName}/${item.name}`)
		}
	}

	return files
}

// Function to support different content types
const getContentType = (file) => {
	const extname = path.extname(file)
	if (extname === ".css") {
		return "text/css"
	} else if (extname === ".js") {
		return "application/javascript"
	} else if (extname === ".png") {
		return "image/png"
	} else if (extname === ".jpg" || extname === ".jpeg") {
		return "image/jpeg"
	} else if (extname === ".gif") {
		return "image/gif"
	} else if (extname === ".avif") {
		return "image/avif"
	}
	return "application/octet-stream" // Default to binary data if the content type is not recognized
}

const staticAssets = getFiles("static")

staticAssets.forEach((el) => {
	app.get(`/${el}`, (req, res) => {
		const filePath = path.join(process.cwd(), `/${el}`)

		try {
			const stats = statSync(filePath)
			if (stats.isFile()) {
				const contentType = getContentType(filePath)
				res.setHeader("Content-Type", contentType)

				const fileContents = readFileSync(filePath)
				res.end(fileContents)
			} else {
				// If it's not a file, send a 404 Not Found response.
				res.end("Not Found")
			}
		} catch (err) {
			// Handle any potential errors.
			console.error(`Error while serving file: ${err.message}`)
			res.end("Internal Server Error")
		}
	})
})

Hope this will be useful.
SYA

@ishtms
Copy link
Owner

ishtms commented Nov 17, 2023

Hi @LebCit,
This framework is a product that we're building as a part of our open source Node.js book. We haven't made enough progress yet, so this does not tackle static file serving for now.

You may check the current progress at Learn Node.js the Hard Way

@LebCit
Copy link
Author

LebCit commented Nov 17, 2023

Hi @ishtms
Thank you for this reply. I now understand why some functionalities are not yet implemented.
As a side note on using Velocy, if I create a route with dynamic parameters:

app.get("/:folder/:filename", async (req, res) => {...})

where the folder parameter's value can be posts, and then I create a /posts route:

app.get("/posts", async (req, res) => {---})

The /posts route works but the route with dynamic parameters returns Route Not Found if the folder parameter's value is posts .

Velocy is great, straightforward, easy to use, without any dependency and lightweight.
Thanks again for your time and this amazing framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants