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

前端 未结 5 2262
眼角桃花
眼角桃花 2021-02-20 06:28

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         


        
相关标签:
5条回答
  • 2021-02-20 06:42

    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');
        }
      }
    }
    
    0 讨论(0)
  • 2021-02-20 06:43

    It's ridiculous to attempt to create a node application without npm dependencies, because the base of nodejs is just that -- a base. Unless you feel like implementing entire protocols, you're better off using a minimal, well maintained npm module that does that for you. That said, here is the very basic thing you asked for (without MiME, eTags, caching, etc, etc):

    var basePath = __dirname;
    var http = require('http');
    var fs = require('fs');
    var path = require('path');
    
    http.createServer(function(req, res) {
        var stream = fs.createReadStream(path.join(basePath, req.url));
        stream.on('error', function() {
            res.writeHead(404);
            res.end();
        });
        stream.pipe(res);
    }).listen(9999);
    
    0 讨论(0)
  • 2021-02-20 06:49

    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.

    0 讨论(0)
  • 2021-02-20 06:50

    its very simple, node already provide fs module from which u can read that html file and append on response obj like this:

    response.writeHead(200, {"Content-Type": "text/plain"});
    //here is the code required
    fs.readFile("./xyz/index.html", (err,fileContent) =>
    {
      response.end(fileContent);
    });
    

    but the problem here is you will only get the HTML document not the resources inside that HTML files which are stored in different folders like if you have this code in your index.html

    <link rel="stylesheet" href="../css/index.css" />

    this index.css will not be allowed by the node server. But i guess your question is solved.

    0 讨论(0)
  • 2021-02-20 07:01

    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");

    0 讨论(0)
提交回复
热议问题