Using the Node HTTP module to build a server has been used as a project practice and development, after in-depth study, the node to build HTTP server has a new understanding and understanding, write a summary listing

  • Supports GZIP compression
  • Cache support/control
  • Yargs with automation

Gzip

GZIP was first created by Jean-Loup Gailly and Mark Adler for file compression on UNIX systems. In Linux we often use files with the suffix.gz, which are in GZIP format. Nowadays, it has become a very popular data compression format, or file format, used on the Internet. GZIP encoding over the HTTP protocol is a technique used to improve the performance of WEB applications. High-traffic WEB sites often use GZIP compression technology to give users a sense of speed. This usually refers to a feature installed in WWW servers that compresses the content of web pages to display in the visiting computer’s browser when someone visits a web site on the server. Generally for plain text content can be compressed to 40% of the original size. This transfer is fast, the effect is that you click on the url will be quickly displayed. Of course, this also increases the load on the server. General server are installed with this functional module.

The HTTP request header accept-encoding informs the client about the Encoding method, usually some kind of compression algorithm. In Content negotiation mode, the server selects a client-proposed method and notifying the client of this choice in the content-Encoding header of the response message.

Accept-encoding :gzip, deflate, br// The current request supports the format of gzip,defalte,br

Content-encoding :gzip // The current Content compression format is gzip

The request accept-Encoding header can be set on the command line

curl -v -H "Accept-Encoding:deflate" http://localhost:8080/msg.txt

HTTP and Gzip

function request(req, res) {
    let{ pathname } = url.parse(req.url); // /msg.txt //D:\vipcode\201801\16.http\msg.txtlet filepath = path.join(__dirname, pathname);
    try {
        // await is only valid in async function
        let statObj = await stat(filepath); // We can return different content-type res.setheader ('Content-Type', mime.getType(pathname)); // To be compatible with different browsers, Node converts all request headers to lowercaselet acceptEncoding = req.headers['accept-encoding']; // Content negotiationif (acceptEncoding) {
            if(acceptencoden.match (/\bgzip\b/)) {// The server tells the client what compression method I used to compress res.setheader ('Content-Encoding'.'gzip');
                fs.createReadStream(filepath).pipe(zlib.createGzip()).pipe(res);
            } else if (acceptEncoding.match(/\bdeflate\b/)) {
                res.setHeader('Content-Encoding'.'deflate');
                fs.createReadStream(filepath).pipe(zlib.createDeflate()).pipe(res);
            } else{ fs.createReadStream(filepath).pipe(res); }}else{ fs.createReadStream(filepath).pipe(res); } } catch (e) { res.statusCode = 404; res.end(); }}Copy the code

Headers [‘accept-encoding’]; Type Compresses the requested static resource of the same type

fs.createReadStream(filepath).pipe(zlib.xxx()).pipe(res);
Copy the code
Use the util module to transfer an asynchronous method to a method that returns a promise (node V8 +).
let { promisify } = require('util'); 
let stat = promisify(fs.stat);
Copy the code

cache

Caching can reduce requests to the server and speed up request efficiency

  • lastModify
  • etag
  • expires
LastModify determines whether the cache is available by the time it was last modified
fs.stat(filepath, (err, stat) = > {if (err) {
            return sendError(req, res);
        } else {
            let ifModifiedSince = req.headers['if-modified-since']; // Time when the header resource was last modifiedletLastModified = stat.ctime.toGMTString(); // Time when the file was last modifiedif (ifModifiedSince == LastModified) {// If equal, return 304 res.writehead (304); res.end(' ');
            } else {
                return send(req, res, filepath, stat); }}});Copy the code
ETag is short for entity tag. It is a hash string generated based on entity content to identify the resource status. When a resource changes, the ETag changes with it. The ETag is generated by the Web server and sent to the browser client.
fs.stat(file, (err, stat) = > {if (err) {
            sendError(err, req, res, file, stat);
        } else {
            let ifNoneMatch = req.headers['if-none-match'];
            let etag = crypto.createHash('sha1').update(stat.ctime.toGMTString() + stat.size).digest('hex');
            if (ifNoneMatch) {
                if (ifNoneMatch == etag) {
                    res.writeHead(304);
                    res.end();
                } else{ send(req, res, file, etag); }}else{ send(req, res, file, etag); }}});Copy the code
Sets the server response header field Expires
res.setHeader('Expires', expires.toUTCString());
res.setHeader('Cache-Control'.'max-age=60');
Copy the code

automation

MAC new automated shell scripts differ from Windows

$ touch hello.sh

$ chmod +x hello.sh

$ ./hello.sh

Install yargs

The YARgs module solves the problem of how to handle command-line arguments. It also needs to be installed.
npm i yargs --save
Copy the code

Edit the hello. Sh

let yargs = require('yargs'); -n --name -n --name -n --name -n --namelet argv = yargs.options('n', {
    alias: 'name', / / alias demand:true, / / will fill the default:'yuanyuan',
    description: 'Please enter your name'
})
    .usage('hellp [opitons]').help()// Specify help information. Example ()'hello -name yuanyuan'.'Execute the hello command and pass in the name parameter for Yuanyuan')
    .alias('h'.'help')
    .argv;
console.log(argv);

console.log('hello ' + argv.name);
Copy the code

Add package.json and add the following

{
  "name": "hello"."bin": {
    "hello": "hello"}}Copy the code

Run the NPM link command.

$ npm link
Copy the code

You can execute the Hello command directly