-2

I am getting mime type mismatch messages while trying to serve an HTML file named index.html with NodeJS. The warnings are as followed:

The stylesheet http://localhost:8081/styling.css was not loaded because its MIME type, "text/html", is not "text/css".

The script from “http://localhost:8081/script.js” was loaded even though its MIME type (“text/html”) is not a valid JavaScript MIME type.

Error Screenshot:

enter image description here

Listing of Files Screenshot:

enter image description here


NodeJS Server Code:

#!/usr/bin/env node

const FS = require('fs')
const HTTP = require('http')
const Server = HTTP.createServer( response )
const Path = require('path')

let PORT = 8080

listen = () => {
    Server.listen(PORT, 'localhost').on('error', e => {
        console.log(`Trying to listen to port ${++PORT}`)
        listen()
    })
}

function response(r, c) {
    let d = new Date()
    console.log(`Respond Fired at ${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`)

    c.setHeader('Content-Type', 'text/plain')
    c.writeHead(200, { 'Content-Type': 'text/html' } )

    c.write(FS.readFileSync(Path.join(__dirname, 'index.html')))
    c.end()
}

listen()


Contents of index.html:

<!Doctype HTML>

<html>
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="styling.css">
    </head>

    <body>
        <p>Hello World!</p>
        <script type="application/javascript" src="script.js"></script>
    </body>
</html>

Contents of styling.css:

p {
    color: #f55 ;
}

Contents of script.js:

document.write('Hello World from JavaScript!')

Browser:

Firefox 73.0b9 (64-bit)

15 Volts
  • 1,946
  • 15
  • 37
  • It says the problem is that it is `text/html` and your code says `c.writeHead(200, { 'Content-Type': 'text/html' } )` … so yes. That's what I'd expect. Did you have a question? – Quentin Jan 30 '20 at 21:25
  • Yes. If I remove the line or change the type to css or javascript, the HTML is shown as plain text in the browser. – 15 Volts Jan 30 '20 at 21:26
  • Well yes. You have to say what type of file you are sending. – Quentin Jan 30 '20 at 21:27
  • How do I dynamically tell the server to load the css or js file when the index.html requests the css or the js file? – 15 Volts Jan 30 '20 at 21:28
  • Oh. I just noticed you hard coded `'index.html'` – Quentin Jan 30 '20 at 21:29
  • 1
    Duplicate: https://stackoverflow.com/questions/57572302/link-index-html-client-js-and-server-js – Quentin Jan 30 '20 at 21:29
  • Just started learning NodeJS, the instructors code works fine but scratching my head for 8 hours to get it working myself. https://stackoverflow.com/a/57572981/11089758 Does the answer solve the issue? – 15 Volts Jan 30 '20 at 21:33
  • Surely the error is similar to me. The OP was getting syntax error and I am getting everything combined. I have previously created a webserver with the crystal lang (https://stackoverflow.com/questions/58602639/a-webrick-like-server-with-crystal/58611439#58611439), which worked perfectly. I am not understanding the alternative of StaticFileHandler with pure NodeJS. (my system doesn't even have NPM installed). – 15 Volts Jan 31 '20 at 02:04

1 Answers1

0

The problem was in setting the correct mimetypes. The problem can be fixed by setting the mime type by reading the extension of the requested file.

The answer can be found here: https://stackoverflow.com/a/29046869/11089758

For example:

#!/usr/bin/env node

const FS = require('fs')
const HTTP = require('http')
const Server = HTTP.createServer( response )
const Path = require('path')
const URL = require('url')

let PORT = 8080

const ContentTypes = {
    '.ico': 'image/x-icon',
    '.html': 'text/html',
    '.js': 'application/javascript',
    '.json': 'text/json',
    '.css': 'text/css',
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.wav': 'audio/wav',
    '.mp3': 'audio/mp3',
    '.svg': 'image/svg+xml',
    '.pdf': 'application/pdf',
    '.doc': 'application/doc'
}

listen = () => {
    Server.listen(PORT, 'localhost').on('error', e => {
        console.log(`Trying to listen to port ${++PORT}`)
        listen()
    })
}

function response(r, c) {
    let d = new Date(), pathname = Path.join( __dirname, URL.parse(r.url).pathname )
    console.log(`Respond Fired at ${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`)

    try { var lstatSync = FS.lstatSync(pathname) } catch { return false }

    let readFile = lstatSync.isDirectory() ? Path.join(__dirname, 'index.html') : pathname
    let head = ContentTypes[Path.extname(readFile)] || 'text/plain', data = ''

    try { data = FS.readFileSync(readFile, 'utf-8') } catch(err) { console.log(err) }

    c.setHeader('Access-Control-Allow-Origin', '*')
    c.writeHead( 200, { 'Content-Type':  head } )
    c.end(data)
}

listen()

We also need to check if the current path is a directory, in such case, we are serving the index.html and sets the head to 'Content-Type': 'text/html', otherwise it looks up in the Object (Hash table), if the extension is not found, it's set to text/plain.

15 Volts
  • 1,946
  • 15
  • 37