Browse Source

Making soe improvements and housekeeping

Herton 4 years ago
parent
commit
4237c43bed
4 changed files with 133 additions and 35 deletions
  1. 94 0
      SimpleServerHelper.js
  2. 28 0
      public/404.html
  3. BIN
      public/sad.png
  4. 11 35
      server.js

+ 94 - 0
SimpleServerHelper.js

@@ -0,0 +1,94 @@
+
+
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+
+class SimpleServerHelper {
+    constructor(config, request, response) {
+        this.settings = {
+            ...{
+                publicFolder: 'public',
+                htmlIndexPath: 'public/index.html',
+                html404Path: 'public/404.html',
+                verbose: false,
+                allowedFiles: {
+                    txt: 'text/plain',
+                    json: 'text/json',
+                    css: 'text/css',
+                    gif: 'image/gif',
+                    jpg: 'image/jpeg',
+                    png: 'image/png',
+                    svg: 'image/svg+xml',
+                    ico: 'image/ico',
+                    js: 'application/javascript',
+                    html: 'text/html',
+                },
+            },
+            ...config
+        };
+        this.request = request;
+        this.response = response;
+        const uri = request.url.toLowerCase();
+        const publicPath = path.join(__dirname, this.settings.publicFolder);
+        this.mimeType = this.getType(uri);
+        this.filePath = this.isHtml() ? this.settings.htmlIndexPath : publicPath + uri;
+    }
+
+    getType(path) {
+        if (path == '/') return this.settings.allowedFiles['html'];
+        const extension = path.split('.').pop().split('?').shift();
+        return this.settings.allowedFiles[extension];
+    }
+
+    isHtml() {
+        return this.mimeType == this.settings.allowedFiles['html'];
+    }
+
+    isValid() {
+        return this.isHtml() || this.fileExist();
+    }
+
+    fileExist() {
+        let exists = false
+        try {
+            exists = fs.existsSync(this.filePath);
+        } catch (error) {
+            if (this.settings.verbose) console.error(error);
+        }
+        return exists;
+    }
+
+    handleLogs(isValid) {
+        if (this.settings.verbose) {
+            if (isValid) console.info(new Date().toString() + ' ' + this.filePath);
+            else console.error('Error accessing ' + this.request.url);
+        }
+    }
+
+    writeHead(isValid) {
+        if (isValid) {
+            this.response.writeHead(200, {
+                'Cache-Control': 'max-age=31536000',
+                'Content-Type': this.mimeType
+            });
+        } else {            
+            this.response.writeHead(404, {
+                'Content-Type': this.settings.allowedFiles['html']
+            });
+        }
+    }
+
+    respond() {
+        const isValid = this.isValid();
+        this.writeHead(isValid);
+        isValid ? fs.createReadStream(this.filePath).pipe(this.response)
+                : fs.createReadStream(this.settings.html404Path).pipe(this.response);
+        this.handleLogs(isValid);
+    }
+};
+
+module.exports = {
+    SimpleServerHelper
+};

+ 28 - 0
public/404.html

@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Simple 404 page not found</title>
+    <meta name="description" content="Simple 404 page not found">
+    <!-- Above the fold styles -->
+    <style>.wrapper {max-width:500px;margin:1rem auto;text-align:center;padding:0 1rem;}</style>
+    <!-- Non blocking styles -->
+    <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
+    <!-- Fallback when JavaScript is not available -->
+    <noscript><link rel="stylesheet" href="styles.css"></noscript>
+    <!-- Assync scripts -->
+    <script type="text/javascript" src="scripts.js" async></script>
+    <!-- PWA stuff -->
+    <link rel="manifest" href="manifest.json">
+    <meta name="theme-color" content="white">
+    <link rel="apple-touch-icon" href="apple-touch-icon.png">
+</head>
+<body>
+    <div class="wrapper">
+        <img src="sad.png" width="90" height="90" alt="icon"/>
+        <h2>Simple Node Server Not Found</h2>
+    </div>
+</body>
+</html>

BIN
public/sad.png


+ 11 - 35
server.js

@@ -1,40 +1,16 @@
 const http = require('http');
-const fs = require('fs');
-const port = 2222;
-const path = require('path');
-const public = path.join(__dirname, 'public');
-const htmlFile = 'public/index.html'; //Single page app file
-/* Allowed file types */
-const types = {
-    txt: 'text/plain',
-    json: 'text/json',
-    css: 'text/css',
-    gif: 'image/gif',
-    jpg: 'image/jpeg',
-    png: 'image/png',
-    svg: 'image/svg+xml',
-    ico: 'image/ico',
-    js: 'application/javascript'
+const { SimpleServerHelper } = require('./SimpleServerHelper.js');
+const port = process.env.PORT || 2222;
+const verbose = process.env.VERBOSE || false // To log errors and files accessed
+const config = {
+    publicFolder: 'public',
+    htmlIndexPath: 'public/index.html',
+    html404Path: 'public/404.html',
+    verbose 
 };
-/* Simple media path validation for single page app */
-function getType(path) {
-    if (path == '/' || path.indexOf(`.html`) != -1) return 'html';
-    for (const type in types) {
-        if (path.indexOf(`.${type}`) != -1) return type;
-    }
-    return false;
-}
-/* Server rules */
-const server = http.createServer((req, res) => {
-    const path = req.url.toLowerCase();
-    const mediaType = getType(path);
-    if (! mediaType) res.writeHead(404).end('Not found');
-    res.writeHead(200, {
-        'Cache-Control': 'max-age=31536000',
-        'Content-Type': mediaType == 'html' ? 'text/html' : types[mediaType]
-    });
-    const filePath = mediaType == 'html' ? htmlFile : public + path;
-    res.end(fs.readFileSync(filePath));
+
+const server = http.createServer((request, response) => {
+    new SimpleServerHelper(config, request, response).respond();
 });
 
 server.listen(port, '127.0.0.1');