Hello everyone! I am trying to render two pages in a simple toy application to better understand Node.js and TypeScript. The index page is supposed to display a simple message when going to localhost:3000
or /
while the 404 page is supposed to display an error message whenever an invalid URL is entered.
Error Message
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be one of type string, Buffer, or URL. Received type undefined
at Object.open (fs.js:406:10)
Summary
The two issues I am encountering are properly using the fs module's readStream()
method and absolute vs relative directory paths.
What I've already tried so far
I've done a lot of Googling and found a lot of StackOverflow posts. The majority that I have read are either relevant to other modules or are using readFile()
. The only thing I've taken away from my searches is to use Node's path
module for resolving directory / file names.
Additionally, I have tried using console.log()
to log my requests to the server and the path that path.join()
is reading.
Here is my project structure:
server_html (top level aka root directory)
-- node_modules
-- src
β³ index.ts
-- views
β³ 404.html
β³ index.html
package-lock.json
package.json
prettier.config.json
tsconfig.json
tslint.json
Code Snippets
Here are my imports, status codes, route map, and port:
import * as http from 'http';
import * as fs from 'fs';
import * as path from 'path';
const httpOkStatus: number = 200;
const httpNotFoundStatus: number = 404;
const routeMap: any = {
"/": path.join(__dirname, "..", "views", "index.html"),
"/index": path.join(__dirname, "..", "views", "index.html")
};
const port: number = 3000;
Here's the code for my server:
const app: http.Server = http
.createServer((req: http.IncomingMessage, res: http.ServerResponse) => {
res.writeHead(httpOkStatus, {
"Content-Type": "text/html"
});
const pathToIndexView: string = routeMap[req.url as string];
const sendToErrorPage: boolean = !routeMap[req.url as string];
if (sendToErrorPage) {
res.writeHead(httpNotFoundStatus, {
"Content-Type": "text/html"
});
let errorPageFileStream: fs.ReadStream = fs.createReadStream(path.join(__dirname, "..", "views", "404.html") as string, "utf8");
errorPageFileStream.pipe(res);
res.end();
}
const src: fs.ReadStream = fs.createReadStream(pathToIndexView, "utf8");
src.pipe(res);
res.end();
});
app.listen(port);
console.log(`The server has started and is listening on port number: ${port}`);
FYI, my Index View is boilerplate HTML with a simple <h1>Welcome!</h1>
.
Since the error is coming from Object.open(fs.js:406:10)
, my guess is that this error is happening within one of the fs.createReadStream()
methods. The questions I have are:
Why is the path to my Error page a type of undefined
?
Why is my index page not rendering my message of "Welcome!"?
Here are my logged paths for both my error page and my index page:
Error: C:\Users\Daniel\Documents\TypeScript\serve_html\views\404.html
Index: C:\Users\Daniel\Documents\TypeScript\serve_html\views\index.html
Next Steps
- I am going to go through Node's official API documentation to see what I can learn about the fs, path, and http modules.
- I may need to dig into the network traffic to see where my requests are going to. I've already looked at some calls in Chrome's Network tab, but I am considering using separate tools to see all data paths.
I'm new to Node.js and would appreciate even glances at this problem. In the meantime, I will keep searching to find answers and / or stumble onto a working version of this.
Top comments (4)
I'm not familiar with Typescript but with vanilla Node you'd normally get the function stack when you have an error, which would help to pinpoint which line of your code causes the error. You have two calls to
fs.createReadStream
, are you sure which one is called? I would check the value ofpathToIndexView
andsendToErrorPage
and maybe addconsole.log
before and after each createReadStream to be sure of what is going on.Very good call on adding the additional
console.log
's!I changed my server code to no longer use
res.end()
asI learned that this is automatically taken care of by the
.pipe()
method.The server looks like this now:
When I start the server and make a request to the home page, these are the results:
The path to the index view is changing with each request.
Additionally, if I try to have my 404 page appear,
I receive the following,
When the path to the index changes, it attempts to find something that isn't there and becomes
undefined
.I feel that I'm a lot closer than I was before. I'll keep logging and stepping through to see what's causing this.
Two things:
if (sendToErrorPage)
block sosendToErrorPage
is not set totrue
.createReadStream
be wrapped in anelse
? It's only supposed to be called when the path is correct, right?Wrapping the second
createReadStream
inside anelse
got everything working.For good measure, I added the
favicon
tags in both HTML<head>
tags.Thank you so much for your help!! ππ