DEV Community

Daniel Medina
Daniel Medina

Posted on

Node.js server fails to render pages

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;
Enter fullscreen mode Exit fullscreen mode

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}`);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Next Steps

  1. I am going to go through Node's official API documentation to see what I can learn about the fs, path, and http modules.
  2. 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)

Collapse
 
sfiquet profile image
Sylvie Fiquet

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 of pathToIndexView and sendToErrorPage and maybe add console.log before and after each createReadStream to be sure of what is going on.

Collapse
 
dwmedina profile image
Daniel Medina • Edited

Very good call on adding the additional console.log's!

I changed my server code to no longer use res.end() as
I learned that this is automatically taken care of by the .pipe() method.

The server looks like this now:

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"
            });
            console.log("Path to error view: \n" + "\t" + path.join(__dirname, "..", "views", "404.html") + "\n");
            let errorPageFileStream: fs.ReadStream = fs.createReadStream(path.join(__dirname, "..", "views", "404.html") as string, "utf8");
            errorPageFileStream.pipe(res);
        }
        console.log("Request url: " + req.url + "\nTime:" + Date.now());
        console.log("Path to index view: \n" + "\t" + pathToIndexView + "\n");
        const src: fs.ReadStream = fs.createReadStream(pathToIndexView, "utf8");

        src.pipe(res);
    });

When I start the server and make a request to the home page, these are the results:

The server has started and is listening on port number: 3000
Request url: /
Time:1580704003783
Path to index view:
        C:\Users\Daniel\Documents\TypeScript\serve_html\views\index.html

Request url: /favicon.ico
Time:1580704004292
Path to index view: 
        C:\Users\Daniel\Documents\TypeScript\serve_html\favicon.ico

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,

Request url: /error
Time:1580704087558
Path to index view: 
        undefined

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.

Collapse
 
sfiquet profile image
Sylvie Fiquet

Two things:

  • looks like it's not stepping inside the if (sendToErrorPage) block so sendToErrorPage is not set to true.
  • shouldn't the second createReadStream be wrapped in an else? It's only supposed to be called when the path is correct, right?
Thread Thread
 
dwmedina profile image
Daniel Medina

Wrapping the second createReadStream inside an else got everything working.

For good measure, I added the favicon tags in both HTML <head> tags.

Thank you so much for your help!! 🎉🎉