Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node itself can serve static files without express or any other module..?

Tags:

node.js

I am beginner in the field of node js.No idea how to send simple request from url Like :- http://localhost:9999/xyz/inde.html my file hierarchy is

server.js
xyz(folder)-
          |->index.html

And get the html page from my server.Which is running at post 9999

var http = require("http");
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.end();
}
http.createServer(onRequest).listen(9999);
console.log("Server has started.");

I know i can send string(having html template) from node js server and send it in response but how to send file without express and any other external module. Thanks

like image 326
squiroid Avatar asked Jan 21 '15 06:01

squiroid


People also ask

CAN node be used without Express?

It's possible to use NodeJS alone. But, you have to write more code that is provided by express or any other framework.

How static files are served in node?

Serve Static Resources using Node-static Module The node-static module is an HTTP static-file server module with built-in caching. First of all, install node-static module using NPM as below. After installing node-static module, you can create static file server in Node. js which serves static files only.

Which module is used to serve static resources NodeJS?

To serve static files such as images, CSS files, and JavaScript files, etc we use the built-in middleware in node.

Does Express allow you to serve static files?

Express offers a built-in middleware to serve your static files and modularizes content within a client-side directory in one line of code.


3 Answers

const http = require('http');
const fs = require("fs");
const path = require("path");

function send404(response){
  response.writeHead(404, {'Content-Type': 'text/plain'});
  response.write('Error 404: Resource not found.');
  response.end();
}

const mimeLookup = {
  '.js': 'application/javascript',
  '.html': 'text/html'
};

const server = http.createServer((req, res) => {
  if(req.method == 'GET'){

    let fileurl;
    if(req.url == '/'){
      fileurl = 'index.html';
    }else{
      fileurl = req.url;
    }
    let filepath = path.resolve('./' + fileurl);

    let fileExt = path.extname(filepath);
    let mimeType = mimeLookup[fileExt];

    if(!mimeType) {
      send404(res);
      return;
    }

    fs.exists(filepath, (exists) => {
      if(!exists){
        send404(res);
        return;
      }

      res.writeHead(200, {'Content-Type': mimeType});
      fs.createReadStream(filepath).pipe(res);

    });

  }
}).listen(3000);
console.log("Server running at port 3000");
like image 119
zaheer Avatar answered Sep 22 '22 12:09

zaheer


Heads up for anyone attempting to serve static files without Express or any other framework:

There is no benefit to skipping Express, in terms of performance or productivity. The only exception is to gain an understanding of how the server and client communicate with each other. Frameworks like Express abstract away all of those complexities, and beginners may not fully understand how they work.

Here is my approach to serving static files using Node.js only. Actually, the reason I did this is because a coding test I was given stipulated no framework whatsoever.

  1. First, decide what the URL path for those static files should look like. I want mine to be accessible under /assets/ path, such as https://example.com/assets/main.css, https://example.com/assets/cat.jpg.

  2. Decide the REGEX for matching those URL. `const assetPattern = /^/assets/[a-zA-Z]+.[a-zA-Z]+/;

The formula above will match urls which contains /assets/[filename].[file extension.

  1. Create a server with Node.js, taking a callback function as a parameter.
// ...
const http = require('http')
const server = http.createServer(requestListener).
  1. Extract url path, get the corresponding file path and configure your server to send the correct MIME types to the browser.
const path = require('path');
// ...
const requestListener = (req, response) => {
  // get the relative url for the request. For example, relative url for a request  
  // to https://example.com is /.
  const { url } = req;
  if (url.match(assetPattern)) {
  // Inside the project directory, the static files are located under the
  // /public/assets directory.
    const filePath = `./public/${url}`;
  // Get the extension name aka the string after the dot. For example, a url like 
  // https://example.com/assets/main.css will result in extension name of css.
    const extname = String(path.extname(filePath)).toLowerCase();
    const mimeTypes = {
      '.html': 'text/html',
      '.js': 'text/javascript',
      '.css': 'text/css',
      '.json': 'application/json',
      '.png': 'image/png',
      '.jpg': 'image/jpg',
      '.gif': 'image/gif',
      '.svg': 'image/svg+xml',
      '.wav': 'audio/wav',
      '.mp4': 'video/mp4',
      '.woff': 'application/font-woff',
      '.ttf': 'application/font-ttf',
      '.eot': 'application/vnd.ms-fontobject',
      '.otf': 'application/font-otf',
      '.wasm': 'application/wasm',
    };
    const contentType = mimeTypes[extname] || 'application/octet-stream';
    staticFileHandler(req, response, filePath, contentType);
  }
}
  1. Serve the static files with fs module
const fs = require('fs')
// ...
const staticFileHandler = (req, res, filePath, contentType) => {
  fs.readFile(filePath, (err, content) => {
    if (err) {
      res.writeHead(500);
      res.end(`Sorry, check with the site admin for error: ${err.code}`)
    } else {
      res.writeHead(200, { 'Content-Type': contentType }); // indicate the request was successful
      res.end(content, 'utf-8');
    }
  }
}
like image 33
bytrangle Avatar answered Sep 22 '22 12:09

bytrangle


I don't agree with the assertion in the accepted answer:

"It's ridiculous to attempt to create a node application without npm dependencies"

as having zero dependencies allows you to deploy an app to a system that runs node by just copying the javascript file(s), and without running npm install.

An example of when I found this useful in real life was writing a public API to compute the amount of income tax a business needs to withold from an employee's pay. You can read all about this fascinating topic here but in essence I had an api that was passed a gross income and returned how that gross income should be split between net income and tax.

I did this with one solitary index.js file, no package.json, and need to npm install:

index.js:

http = require('http');
url = require('url');
const port = 80; // make this a number over 1024 if you want to run `node` not run `sudo node` 
const debug = true;
const httpServer = http.createServer((request, response) => {
  response.setHeader('Content-Type', 'application/json');
  const parsedUrl = url.parse(request.url, true);
  let pathName = parsedUrl.pathname;
  if (pathName==='/favicon.ico') {
    // chrome calls this to get an icon to display in the tab. I want to ignore these request. They only happen when testing in a browser,
    // not when this api is called in production by a non-browser.
    if (debug) console.log('Browser requested favicon.ico')
    response.end();
    
  } else {
    if (debug) console.log('Request on path ' + pathName);
    const elements = pathName.split('/');
    if (elements.length == 3 && elements[0] === '' &&  elements[1]==='witholdcalc') {
      const grossString = elements[2];
      const gross = Number.parseInt(grossString);
      if (isNaN(gross)) {
        response.writeHead(400).end(JSON.stringify({error:'Gross salary must be an integer. found: ' + grossString}));
      } else {
        /*
         * The computation of the amount to withold is more complicated that this, but it could still be hard coded here:
         * For simplicity, I will compute in one line:
         */
        const withold = Math.floor((gross<1000)?0:((gross-1000)*.2));
        response.writeHead(200).end(JSON.stringify({net: (gross-withold), withold: withold, elements:(debug?elements:undefined)}));
      }
    } else {
      if (debug) console.log('Invalid path was: ' + pathName,elements);
      response.writeHead(404).end();
    }
  }
});
httpServer.listen(port), () => {
  console.log(`PAYG listening at http://localhost:${port}`)
}

I then could execute sudo node install.js on my linux computer, and in a browser, hit http://localhost/witholdcalc/6000, and it would return {"net":5000,"withold":1000} when debug is set to false.

like image 41
NULL pointer Avatar answered Sep 24 '22 12:09

NULL pointer