preface

The main content of this article is to learn koA’s source code with others by describing the author’s own process of learning koA’s source code. Koa was designed to be a smaller, more expressive, and more robust cornerstone of Web application and API development. Because of its high scalability, koA’s source code is relatively easy to read. If you follow my article to learn, it must be my bad writing.

In the listen method, a custom this.callback is called. Context, Request, and Response are called during callback execution, and this article looks at what is done.

Context

The source file for Context is only 252 lines, which is very simple. In addition to type judgment and error handling, the two most core parts of the file are cookies and delegates. This article focuses on these two parts.

cookies

Take a look at the relevant source code

const COOKIES = Symbol('context#cookies');
const Cookies = require('cookies');

  get cookies() {
    if(! this[COOKIES]) { this[COOKIES] = new Cookies(this.req, this.res, {  keys: this.app.keys,  secure: this.request.secure  });  }  return this[COOKIES];  },   set cookies(_cookies) {  this[COOKIES] = _cookies;  }  Copy the code

This code is mainly to encapsulate cookies into get, set form at the same time through the unique feature of symbol to create a singleton (this writing method is also very common and easy to use, recommend everyone to use in their own code) at the same time to create cookies, cookies object source address: Github.com/ScottHamper… , the main function is to get the cookie object in the header through the REQ object, as well as some changes to the RES object, we can see the source code and usage.

delegate

/ * * * Response delegation.
* /
delegate(proto, 'response')
 .method('attachment')  .method('redirect')  .method('remove')  .method('vary')  .method('has')  .method('set')  .method('append')  .method('flushHeaders')  .access('status')  .access('message')  .access('body')  .access('length')  .access('type')  .access('lastModified')  .access('etag')  .getter('headerSent')  .getter('writable');  / * * * Request delegation. * / delegate(proto, 'request')  .method('acceptsLanguages')  .method('acceptsEncodings')  .method('acceptsCharsets')  .method('accepts')  .method('get')  .method('is')  .access('querystring')  .access('idempotent')  .access('socket')  .access('search')  .access('method')  .access('query')  .access('path')  .access('url')  .access('accept')  .getter('origin')  .getter('href')  .getter('subdomains')  .getter('protocol')  .getter('host')  .getter('hostname')  .getter('URL')  .getter('header')  .getter('headers')  .getter('secure')  .getter('stale')  .getter('fresh')  .getter('ips')  .getter('ip');  Copy the code

Delegate delegates methods and properties on request and response to Context. Let’s cut this down a bit:

delegate(proto, 'response')
  .method('attachment')
  .access('status')
  .getter('headerSent')

Copy the code

There are three methods called: Method, Access, and getter. Let’s see what delegate does. Find the delegate source

function Delegator(proto, target) {
  if(! (this instanceof Delegator))return new Delegator(proto, target);
  
// ① Get proto and target  this.proto = proto;
 this.target = target;  // create methods, getters, setters, fluents array this.methods = [];  this.getters = [];  this.setters = [];  this.fluents = []; }  Delegator.prototype.method = function(name){  var proto = this.proto;  var target = this.target;  // ③ Push the passed method name into the methods array this.methods.push(name);  // mount the name of the passed method to proTO so that proTO can call the method of proto[target] directly proto[name] = function() { return this[target][name].apply(this[target], arguments);  };   return this; };  Copy the code

The method calling the delegator function and method basically does four things

  • Get proto (context) and target (‘request’ or ‘esponse’ in KOA)
  • ② Create methods, getters, setters, fluents array
  • ③ Push the passed method name into the methods array
  • (4) Mount the name of the passed method to proTO so that proTO can call the method of proTO [target] directly

Let’s look at getter and access again

Delegator.prototype.getter = function(name){
  var proto = this.proto;
  var target = this.target;
  this.getters.push(name);

 proto.__defineGetter__(name, function() { return this[target][name];  });   return this; };  Delegator.prototype.setter = function(name){  var proto = this.proto;  var target = this.target;  this.setters.push(name);   proto.__defineSetter__(name, function(val){  return this[target][name] = val;  });   return this; };  Delegator.prototype.access = function(name){  return this.getter(name).setter(name); };  Copy the code

A getter method implementation is a property that can be invoked directly on CTX (for example, Ctx.host === ctx.request.host) setters allow you to modify the properties of the request on CTX. Access mounts both getter and setter methods

Koa uses the Delegator pattern to make it easy for CTX to call methods and attributes on request and Response.

request&&response

Request and Response objects are essentially nothing special, and KOA encapsulates common methods and properties into two objects. The code of the two files adds up to a total of more than 1000 lines, and more than half of them are comments. I suggest that these two files simply have a look, and when needed, they can be checked as documents without further details.

conclusion

Koa source code we first analysis to here, this article is completely in accordance with the author of their own learning source code process to describe, the writing is not good to read it may have a little running account, but the author will try to describe clearly, and read the source code of some methods and skills to share, please collect points like support.

Related articles

Handy with you learn Koa source (a) – directory structure to learn with you holding Koa source (a) – directory structure to learn with you holding Koa source (2) — Appilication

This article is formatted using MDNICE