script tags in Express - javascript

I have an index.html that has a couple script tags, but they are all returning 404 errors, and I can't figure out how to fix it. Currently they are in the top directory and referenced as such. e.g. <script type="text/javascript" src="./util.js"></script>.
I tried using require('./file.js'); but it would seem to me that this is not what I want. Would this not give me access only in the backend? It needs to be served with the html.

The root path that's given to express.static() is the directory that Express will begin at to match files on disk.
app.use(express.static(path.join(__dirname, 'static')));
That path also won't be part of the URL. It's combined with the req.path in a manner similar to:
var rootPath = 'orbit'; // from `express.static('orbit')`
console.log(path.join(rootPath, req.path));
// 'orbit/orbit/util.js'
Note that orbit appears twice and static is missing, compared to the path in your comment:
./static/orbit/util.js
Or, with the path suggested above:
var rootPath = path.join(__dirname, 'static');
console.log(path.join(rootPath, req.path));
// "/path/to/your/application/static/orbit/util.js"
// assuming `__dirname` is `/path/to/your/application/`

Related

How to res.sendFile() a file that is in a different directory for Express.js webapp?

I have this inside controllers folder:
//controler.js
exports.serve_sitemap = (req, res) => {
res.sendFile("../../sitemap.xml");
// or
// res.send(__dirname + "./sitemap.xml")
// But neither of these work
};
This exported function is imported in a file inside the routes directory
const { serve_sitemap } = require('../controllers/indexer')
var router = require('express').Router()
router.get("/sitemap", serve_sitemap)
module.exports = router
Currently I am getting a 404 error when I try to get the sitmap at localhost:3000/sitemap
Folder Structure:
Before, I had the same thing in index.js which is the entry point.
app.get("/sitemap", (req, res) => {
res.sendFile(__dirname + "/sitemap.xml");
});
This was working perfectly, until I decided to restructure the project
How can I refer to the sitemap.xml file that is located in the root directory from a file that is in a sub-directory when using res.send()?
How can I get the absolute path to the root of the project directory, then I can append the file name to the path. This can solve the issse
I maybe missing something obvious. In that case, please help me out.
Any suggestion gratefully accepted. Thanks in advance
Why do you think that res.sendFile(__dirname + "./sitemap.xml") would work?
First of all __dirname + "./sitemap.xml" is not how paths should be concatenated you should use join instead especially if your second path starts with ./. And there is no file sitemap.xml in the directory of the controller:
__dirname + "./sitemap.xml" would result in something like /path/to/project/src/controller/./sitemap.xml
And why should "../../sitemap.xml" work. If you only have "../../sitemap.xml" it is relative to the working directory which is the one where (i guess) index.js is located. So "../../sitemap.xml" will be resolved based on /path/to/project, so /path/to/project/../../sitemap.xml.
Due to that is either res.sendFile("./sitemap.xml") (relative to index.js) or res.sendFile(path.join(__dirname, "../../sitemap.xml")) (relative to the controller).

Static serving on express js not working when also using custom middleware

I am trying to write a middleware for my express js website so that I can use subdomains. I also want to use static image, css, and js serving. My HTML pages load just fine but whenever I try to call a .js file, I get a long page load time and the js doesn't load.
Any help is appreciated, thanks! :)
app.use("/assets", express.static(path.join(__dirname, "assets")));
app.get("*", (req, res, next) => {
let host = req.get("host").split(".");
console.log(req.originalUrl);
let url = req.originalUrl.split("/");
url.shift();
console.log(url);
if (host.length > 2) {
res.send("myWebsite.com");
} else {
const pages = Page.getPages();
pages.forEach(page => {
if ((url[0] == "" ? "home" : url[0] ?? "home").toLowerCase() == page.name) {
if (url.length == 1 || (url.length == 2 && url[1] == "")) {
page.publish(res);
}
}
});
}
});
So, in Pages.html, you have this:
<script type="text/javascript" src="/assets/js/Pages.js"></script>
That looks like it would generally be compatible with your express.static() statement (shown below) to load Pages.js from your assets/js folder:
app.use("/assets", express.static(path.join(__dirname, "assets")));
But, then that Pages.js script immediately starts out with this:
import Page from '../../Page.js';
That will not work when requested by the browser. Remember paths in import statements from Javascript running in the browser are relative to the current URL of the web page. The browser will attempt to combine that relative URL with the URL of the web page and then make a request to your server for that newly constructed URL.
In this case, you'll end up with something like a request for http://somehost/../../Page.js. But, you don't have any route in your server that will handle that. By default express.static() skips any routes that contain ../ because that can be a nasty security issues (allowing attackers to fetch things around your server file system). So, you'll probably end up with a 404 error when trying to fetch that file.
ALL files you want the browser to be able to load, including imports embedded within other JS files must be in your public assets folder (or some other folder you've explicitly enabled public access to with something like express.static()).
FYI, if you look in the browser console, you probably see error messages that would have indicated to you where to look for the error.
__dirname is an environment variable that tells you the absolute path of the directory containing the currently executing file. You have to make sure that the final bundle (your asset folder) is present in that directory. Try to hard code the assets absolute path, if it works then use the below snippet instead:-
app.use("/assets", "express.static(process.cwd() + '/assets'));

HTML <script> src url no longer works after rearranging files

I'm working on a personal project in order to learn web dev, and I've run into a strange (and hopefully easily solved) problem. In my index.html file I've included a reference to a main.js file, and that's been working just fine for a while now. However, I've recently rewritten the project in Typescript and I've decided to rearrange the folder structure. The problem is that when I move my index.html file (and some other files) down one directory and append a '../' to the script's 'src' tag, I get a 404 error when the html attempts to load the script.
This works just fine:
.
|-scripts
|-Main.ts
|-Main.js
|-SlideShowView.ts
|-SlideShowView.js
|-Server.ts
|-Server.js
|-index.html -> <script src="scripts/Main.js" type="module"></script>
This does not:
.
|-scripts
|-Main.ts
|-Main.js
|-SlideShowView.ts
|-SlideShowView.js
|-services
|-Server.ts
|-Server.js
|-index.html -> <script src="../scripts/Main.js" type="module"></script>
Connecting to the site when using the second scheme gives this error:
GET http://localhost:8000/scripts/Main.js net::ERR_ABORTED 404 (Not Found)
Is index.html not allowed to look above it's own directory? Is there a permissions issue or something? It's such a simple thing that's failing to work I figure there must be something small I'm missing.
Thanks in advance for the help!
Found the answer!
After I moved index.html back to root, the problem wasn't in my html or main.js, but in the express server I was using:
import path from "path";
import express from "express";
const serverPortNum = 8000;
const htmlFile = path.join(__dirname + '/../index.html'); //Added an escape here...
// Create html server
var app = express();
app.use(express.static(__dirname));// ...but not here.
app.get('/', function(req: any, res: any)
{
res.sendFile(htmlFile);
});
app.listen(serverPortNum, function()
{
console.log("Listening! (port " + serverPortNum + ")");
});
Basically, I had changed the path to the html file correctly but I forgot to make the change in app.use() as well. Changing that line to app.use(express.static(__dirname + "/..")); corrected the problem.
This should be simple as moving the index.html file outside of both file structures
|-scripts
|-Main.ts
|-Main.js
|-SlideShowView.ts
|-SlideShowView.js
|-services
|-Server.ts
|-Server.js
|-index.html -> <script src="scripts/Main.js" type="module"></script>

Why Node.js only recognizes absolute paths? [duplicate]

This question already has answers here:
What is the difference between __dirname and ./ in node.js?
(2 answers)
Closed 3 years ago.
I created a file called nodes, then initialized the file with npm init and the main js file is called main.js. I also created index.html and index.css in the file, after that I want to use Node.js Render this index.html, so I wrote in main.js:
const http = require('http');
const fs = require('fs');
const hostname = '127.0.0.1';
const port = 9000;
const mainHTML = './index.html';
const server = http.createServer((req, res) => {
fs.stat(`./${mainHTML}`, (err, stats) => {
if(stats) {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
fs.createReadStream(mainHTML).pipe(res);
}
});
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
I opened the server with the node desktop/nodes command, but node.js could not find the file.
Until I changed the relative path to an absolute path, Node.js will recognize it:
const mainHTML = 'desktop/nodes/index.html';
Why is this? If I want to use a relative path, how do I do it?
When you access a file in node.js with a relative path, the file is accessed relative to the value of the current working directory for the process. Note, in the modular world of node.js, the current working directory may or may not be the same as the directory where your module was located. And, your code can change the current working directory to be whatever you want it to be.
It is common in modular node.js code to have a programming desire to access things relative to the directory where the current module's code was loaded from. This gives you the ability to use relative paths so the app/module can work anywhere, but it gives you certainty that you'll get the files you want. To do this, one typically uses the module-specific variable __dirname. This is the directory that the current module was loaded from. If it's the main script that node.js was started with then, it's the directory of that script.
So, to get a file from the same directory as the script you are current in, you would do this:
const mainHTML = 'index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
To access a file in a subdirectory public below where the script is, you could do this:
const mainHTML = 'public/index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
To access a file in a different subdirectory at the same level (common parent directory) as where the script is, you could do this:
const mainHTML = '../public/index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
All of these use paths that are relative to where the script itself is located and do not depend upon how the module/script was loaded or what the current working directory of the app is.
You are creating http server, which creates it's path as base, so it understands only paths taking that base path as relative path. If you want to use relative path, then you need to resolve that path.
You can use 'path' library.
const path = require('path')
// To resolve parent path
path.resolve('..', __dirname__)

Node.js + Express.js : express.static not serving image (contains errors)

I'm trying to use express.static to serve an image at http://localhost:3000/logo/logo.jpg.
The image logo.jpg is in /public/images and my code is:
app.use("/logo", express.static(__dirname + '/public/images'));
The page loads, but the image is broken. Firefox says: The image at http://localhost:3000/logo/logo.jpg cannot be displayed because it contains errors. When I look at the page info, Firefox tells me the image dimensions for logo.jpg are 0x0. I've tried using various images and different browsers, but they all have the same issue.
How can I get the image to load properly?
I couldn't get my directory with static files served, but when I started to use path.join it began to work as expected. Try this:
var path = require('path');
app.use('/logo', express["static"](path.join(__dirname, 'public/images')));
I found the culprit. For some reason, if I placed the line:
app.use("/logo", express.static(__dirname + '/public/images'));
after this code:
// load liveReload script only in development mode
// load before app.router
// development only
if ('development' == app.get('env')) {
var liveReloadPort = 35729;
var excludeList = ['.woff', '.flv'];
app.use(require('connect-livereload')({
port: liveReloadPort,
excludeList: excludeList
}))
}
It didn't work. However, if I moved the app.use("/logo")... line before the liveReload code, it works.
Don't exactly understand why the position affected how the code works, but at least it does!

Categories