1. The HTTP server is introduced
Sometimes the web address bar needs to use HTTP protocol, this time can be through the HTTP-server plug-in to achieve the effect. To install http-server globally, enter NPM i-g http-server.
npm i -g http-server
Copy the code
After installation, type in the directory of the file you want to openhttp-server
You can turn it onhttp
Agreement.
Let’s say I open a command line in a project directory
Enter http-server to start the service
And then open this uphttp://127.0.0.1:8081/You can see this effect, the current folder directory deconstruct and files.
This is the simplest usage scenario, and it can be configured with many options. For example, http-server –port 3000 can be used to set the port number of the service. You can also use –directory to specify the directory.Github.com/http-party/…
2. Code implementation
1. Requirements analysis and implementation
- in
package.json
In the configurationbin
Field, and then usenpm link
Connect to globalnpm
Package, so you can use your own commands globally, you can use the chalk toolchalk
Sets the file color for the prompt - The introduction of
commander
The package takes the parameters entered by the user on the command line to override the default parameters, set command line prompts, colors, and so on. - with
http-server
Create a service that reads the directory according to the requested path and determines whether it is a file or folder. If it is a file, return the corresponding file, otherwise return a current directory structurehtml
. The returnedhtml
You can useejs
This package is generated from a template, and different types of files require different response headersContent-Type
Type, can be usedmime
The package resolves.
2. Code implementation
1. Initialize the project
npm init -y
Copy the code
Then change the project name to my-http-server, configure the bin field in package.json, add a bin folder to create WWW and config.js files, the bin directory is the tool startup directory, and execute the my-hs command to directly execute the code in WWW. Create a SRC directory and add a server.js file to handle the client’s request and response logic. Create template. HTML to handle the HTML case where the directory is a directory to return to. Then install chalk, Commander, EJS, and MIME.
The directory structure is as follows:
| - bin | | - config. Js -- -- -- -- -- -- -- -- -- -- -- -- - the default configuration services | | - WWW -- -- -- -- -- -- -- -- -- -- -- -- -- service startup file | | - SRC | | - server. Js -- -- -- -- -- -- -- -- - | service logic processing | - template. HTML -- -- -- -- -- -- -- -- -- -- the HTML template, is used to render folder directory structure | | - package. JsonCopy the code
package.json
{
"name": "my-hs"."version": "1.0.0"."description": ""."bin": {
"my-hs": "./bin/www"
},
"main": "index.js"."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": []."author": ""."license": "ISC"."dependencies": {
"chalk": "^ 4.1.0." "."commander": "^ 6.2.1." "."ejs": "^ 3.1.5." "."mime": "^ 2.4.7." "}}Copy the code
Config.js default configuration file
// Customize the commands to be displayed on the command line
const config = { // Set the parameters for yourself
'port': {option:'-p,--port <n>'.//
represents a value
descriptor:'set your server port'.default: 8080.usage:'my-hs --port <n>'
},
'directory': {option:'-d,--directory <n>'.descriptor:'set your server start directory'.default: process.cwd(),
usage: 'my-hs --directory <n>'
},
'cache': {option:'-c,--cache <n>'.descriptor:'set your server cache'.default:'no-cache'.usage: 'my-hs --cache <n>'}}module.exports = config;
Copy the code
WWW file note: the #! /usr/bin/env node is a fixed form that tells the system to execute the file using node,
#! /usr/bin/env node
const program = require('commander');
const chalk = require('chalk');
const config = require('./config');
const Server = require('.. /src/server')
// The name used for the configuration
program.name('my-hs');
// The default configuration object
const defaultConfig = {};
// Use the sample collection
const usageList = [];
// Go through the configuration to the current program
Object.entries(config).forEach(([key, value]) = > {
defaultConfig[key] = value.default;
usageList.push(value.usage)
program.option(value.option, value.descriptor);
});
// Listen for the --help event to display the sample on the command line
program.on('--help'.function () {
console.log('Examples:');
usageList.forEach(line= >{
console.log(` ${chalk.green(line)} \r`); })})// Parse the user's execution parameters
program.parse(process.argv);
// Make a configuration based on the user's parameters and default values
function mergeOtions(defaultConfig,newConfig){
const options = {}
for(let key in defaultConfig){
if(! (keyin newConfig)){
options[key] = defaultConfig[key]
}else{
// Verify that newConfig meets my expectations
options[key] = newConfig[key]
}
}
return options
}
let options = mergeOtions(defaultConfig,program);
// Get the user's parameters to create a service and start it
let server = new Server(options);
server.start();
Copy the code
Server. The js file
const http = require('http');
const url = require('url'); // Parse url parameters
const path = require('path');
const fs = require('fs').promises; // Get the FS module's Promise method
const { createReadStream, createWriteStream } = require('fs'); // Get the read/write stream method
const chalk = require('chalk'); // Chalk tool
const mime = require('mime'); // Parses the file mime type package
const ejs = require('ejs'); // Generate the HTML package
/ / service class
class Server {
constructor(options) {
this.port = options.port;
this.directory = options.directory;
this.cache = options.cache;
}
async handleRequest(req, res) {
let { pathname } = url.parse(req.url);
pathname = decodeURIComponent(pathname); // Set base64 to Chinese
// List all folders
let requestUrl = path.join(this.directory, pathname); // Resolve will return to the root path
try {
const statObj = await fs.stat(requestUrl); // Read the path of the corresponding type, directory or file
// If it is a directory, return an HTML for that directory
if (statObj.isDirectory()) {
// Get all files and folders in this directory
let dirs = await fs.readdir(requestUrl);
let content = await ejs.renderFile(path.resolve(__dirname, 'template.html'), {
dirs: dirs.map(dir= > ({
name: dir,
pathname: path.join(pathname, dir) // Prefix to get the deep folder structure}}))); res.setHeader('Content-Type'.'text/html; charset=utf-8');
res.end(content);
} else {
// file reads files
this.sendFile(requestUrl, req, res, statObj)
}
} catch (e) {
console.log(e)
this.sendError(e, req, res); }}// Error response
sendError(err, req, res) {
res.statusCode = 404;
res.end('Not Found')}// Set the response header based on the file type and return the file
sendFile(filePath, req, res, stat) {
res.setHeader('Content-Type'.`${mime.getType(filePath)}; charset=utf-8`)
createReadStream(filePath).pipe(res);
}
// Start the service method
start() {
const server = http.createServer(this.handleRequest.bind(this));
server.listen(this.port, () = > {
console.log(`${chalk.yellow('Starting up http-server, serving')}`);
console.log(` http://127.0.0.1:${chalk.green(this.port)}`)}); }}module.exports = Server;
Copy the code
File directory HTML template
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<%dirs.forEach(dir=>{%>
<li><a href="<%=dir.pathname%>"><%=dir.name%></a></li>The < %}) % ></body>
</html>
Copy the code
Use 3.
Enter in the command toolmy-hs --help
We’re listening in the code--help
Event showing the use sample.
Enter in the command toolmy-hs -d /Users/xujian/workPlace/vue-better-drawer
In/Users/xujian/workPlace/vue – better – the drawer launched an HTTP service directory
Browser openhttp://127.0.0.1:8080/This address gives access to the file structure in this directory
Can display specific file file class capacity:
And access to deeper directories:
An easy versionhttp-server
Github address:Github.com/Itherma/my-…