diff --git a/lesson18/README.md b/lesson18/README.md
new file mode 100644
index 0000000..ba18d16
--- /dev/null
+++ b/lesson18/README.md
@@ -0,0 +1,518 @@
+#《何为 connect 中间件》
+
+##目标
+
+1. 理解中间件的概念
+2. 了解Connect的实现
+
+
+##课程内容
+
+1. 原生httpServer遇到的问题
+2. 中间件思想
+3. Connect实现
+4. Express简介
+
+这是从httpServer到Express的升级过程。
+
+#HTTP
+Nodejs的经典httpServer代码
+
+```js
+var http = require('http');
+
+var server = http.createServer(requestHandler);
+function requestHandler(req, res) {
+ res.end('hello visitor!');
+}
+server.listen(3000);
+```
+
+里面的函数`requestHandler`就是所有http请求的响应函数,即所有的请求都经过这个函数的处理,是所有请求的入口函数。
+
+通过requestHandler函数我们能写一些简单的http逻辑,比如上面的例子,所有请求都返回`hello visitor!`。
+
+`然而`,我们的业务逻辑不可能这么简单。例如:需要实现一个接口,要做的是当请求过来时,先判断来源的请求是否包含请求体,然后判断请求体中的id是不是在数据库中存在,最后若存在则返回true,不存在则返回false。
+
+```
+1. 检测请求中请求提是否存在,若存在则解析请求体;
+2. 查看请求体中的id是否存在,若存在则去数据库查询;
+3. 根据数据库结果返回约定的值;
+```
+
+我们首先想到的,抽离函数,每个逻辑一个函数,简单好实现低耦合好维护。
+
+实现代码:
+
+```js
+function parseBody(req, callback) {
+ //根据http协议从req中解析body
+ callback(null, body);
+}
+function checkIdInDatabase(body, callback) {
+ //根据body.id在Database中检测,返回结果
+ callback(null, dbResult);
+}
+function returnResult(dbResult, res) {
+ if (dbResult && dbResult.length > 0) {
+ res.end('true');
+ } else {
+ res.end('false')
+ }
+}
+function requestHandler(req, res) {
+ parseBody(req, function(err, body) {
+ checkIdInDatabase(body, function(err, dbResult) {
+ returnResult(dbResult, res);
+ });
+ });
+}
+```
+上面的解决方案解决了包含三个步骤的业务问题,出现了3个`});`还有3个`err`需要处理,上面的写法可以得达到预期效果。
+
+`然而`,业务逻辑越来越复杂,会出发展成30个回调逻辑,那么就出现了30个`});`及30个`err`异常。更严重的是,到时候写代码根本看不清自己写的逻辑在30层中的哪一层,极其容易出现**多次返回**或返回地方不对等问题,这就是**回调金字塔**问题了。
+
+大多数同学应该能想到解决回调金字塔的办法,朴灵的《深入浅出Node.js》里讲到的三种方法。下面列举了这三种方法加上ES6新增的Generator,共四种解决办法。
+
+- [EventProxy](https://github.com/JacksonTian/eventproxy) —— 事件发布订阅模式(第四课讲到)
+- [BlueBird](https://github.com/petkaantonov/bluebird) —— Promise方案(第十七课讲到)
+- [Async](https://github.com/caolan/async) —— 异步流程控制库(第五课讲到)
+- [Generator](http://es6.ruanyifeng.com/#docs/generator) —— ES6原生Generator
+
+理论上,这四种都能解决回调金字塔问题。而Connect和Express用的是`类似异步流程控制的思想`。
+
+
+关于异步流程控制库下面简要介绍下,或移步[@第五课](https://github.com/alsotang/node-lessons/tree/master/lesson5)。
+异步流程控制库首先要求用户传入待执行的函数列表,记为funlist。流程控制库的任务是让这些函数**顺序执行**。
+
+callback是控制顺序执行的关键,funlist里的函数每当调用callback会执行下一个funlist里的函数……如下图
+
+```
+使用cb表示callback,cb()表示调用;w1表示wait 函数1,即等待函数1调用callback;run()表示该函数正在执行。
+
+时序 1 2 3 4 5 6
+fun1 cb() - - - - -
+fun2 run() cb() - - - -
+fun3 w2 run() cb() - - -
+fun4 w3 w3 run() cb() - -
+fun5 w4 w4 w4() run() cb() -
+fun6 w5 w5 w5 w5 run() end()
+
+执行顺序为
+fun1->fun2->fun3->fun4->fun5->fun6
+他们通过callback的调用完成了链式调用
+```
+
+我们动手实现一个类似的链式调用,其中`funlist更名为middlewares`、`callback更名为next`,码如下:
+
+
+```js
+var middlewares = [
+ function fun1(req, res, next) {
+ parseBody(req, function(err, body) {
+ if (err) return next(err);
+ req.body = body;
+ next();
+ });
+ },
+ function fun2(req, res, next) {
+ checkIdInDatabase(req.body.id, function(err, rows) {
+ if (err) return next(err);
+ res.dbResult = rows;
+ next();
+ });
+ },
+ function fun3(req, res, next) {
+ if (res.dbResult && res.dbResult.length > 0) {
+ res.end('true');
+ }
+ else {
+ res.end('false');
+ }
+ next();
+ }
+]
+
+function requestHandler(req, res) {
+ var i=0;
+
+ //由middlewares链式调用
+ function next(err) {
+
+ if (err) {
+ return res.end('error:', err.toString());
+ }
+
+ if (i源码看下面的函数介绍。
+
+|函数名 |作用 |
+| -------------|:----------------------------:|
+|createServer |包装httpServer形成app |
+|listen |监听端口函数 |
+|use |向middlewares里面放入业务逻辑 |
+|handle |上一章的requestHandler函数增强版|
+|call |业务逻辑的真正执行者 |
+
+##createServer()
+**输入**:
+
+无
+
+**执行过程**:
+
+1. app是一个函数对象(包含handle方法)
+2. app具有Event所有属性(详见[utils-merge](https://github.com/jaredhanson/utils-merge),十行代码)
+3. app有route属性(路由)、和stack属性(用于存储中间件,类似上面的[middlewares](#middlewares))
+
+**输出**:
+
+```
+ app is function(req, res, next) {...};
+ |
+ +---+---+
+ | has |
+ route stack
+```
+
+##app.use(route, fn)
+作用是向stack中添加`逻辑处理函数`(中间件)。
+
+**输入**:
+
+1. route 可省略,默认'/'
+2. fn 具体的业务处理逻辑
+
+**tips:**
+
+上面的fn表示处理逻辑,它可以是
+
+1. 一个普通的`function(req,res[,next]){}`;
+2. 一个[httpServer](https://lodejs.org/api/http.html#http_class_http_server);
+3. 另一个connect的app对象(**sub app特性**);
+
+由于它们的本质都是`处理逻辑`,都可以用一个`function(req,res,next){}`将它们概括起来,Connect把他们都转化为这个函数,然后把它们存起来。
+
+如何将这三种分别转换为function(req, res, next) {}的形式呢?
+
+1. 不用转换;
+2. httpServer的定义是“对事件'request'后handler的对象”,我们可以从httpServer.listeners('request')中得到这个函数;
+3. 另一个connect对象,而connect()返回的app就是function(req, res, out) {};
+
+
+**执行过程**:
+
+1. 将三种`处理逻辑`统一转换为`function(req,res,next){}`的形式表示。
+2. 把这个`处理逻辑`与route一起,放入`stack`中(存储处理逻辑,route用来匹配路由)
+
+核心代码片段
+
+```js
+//route是路由路径,handle是一个`function(req, res, next) {...}`形式的业务逻辑
+this.stack.push({ route: path, handle: handle });
+```
+
+**返回**:
+
+```js
+//返回自己,可以完成链式调用
+return this;
+```
+
+**总结:**:
+
+```js
+var app = connect();
+app.use('/api', function(req, res, next) {});
+```
+
+等价于
+
+```js
+var app = connect();
+app.stack.push({route: '/api', handle: function(req, res, next) {}});
+```
+
+最后,app.stack里**顺序存储**了所有的**逻辑处理函数**(中间件)。
+
+```js
+app.stack = [function1, function2, function3, ... function30];
+```
+
+##app.handle(req, res, out)
+这个函数就是请求到达时,负责`顺序调用`我们存储在stack中的`逻辑处理函数`(中间件)函数,类似上一章的requestHandler。
+
+**输入:**
+
+1. req是Nodejs本身的可读流,不做过多介绍
+2. res是Nodejs本身的可写流,不做过多介绍
+3. out是为了Connect的**sub app特性**而设计的参数,这个特性可以暂时忽略,这个参数我们暂时不关心
+
+**处理过程:**
+
+可以回头看一下上面的[requestHandler函数](#middlewares),handle的实现是这个函数的增强版
+
+1. 取得stack(存储`逻辑处理函数`列表),index(列表下标)
+2. 构建next函数,next的作用是执行下一个`逻辑处理函数`
+3. 触发第一个next,触发链式调用
+
+**next函数实现:**
+
+next函数实现在handle函数体内,用来`顺序执行处理逻辑`,它是异步流程控制库的核心,不明白它的作用请看[上面的异步流程控制库简介](#next)
+
+path是请求路径,route是`逻辑处理函数`自带的属性。
+
+1. 取得下一个`逻辑处理函数`;
+2. 若路由不匹配,跳过此逻辑;
+3. 若路由匹配[下面的call](#call)执行匹配到的`逻辑处理函数`
+
+tips: 跟上一章最后的代码一样,每个`逻辑处理函数`调用`next`来让后面的函数执行,存储在stack中的函数就实现了`链式调用`。不一定所有的函数都在返回的时候才调用`next`,为了不影响效率,有的函数可能先调用next,然而自己还没有返回,继续做自己的事情。
+
+核心代码:
+
+```js
+//取下一个逻辑逻辑处理函数
+1: var layer = stack[index++];
+//不匹配时跳过
+2: if (path.toLowerCase().substr(0, route.length) !== route.toLowerCase()) {
+ return next(err);
+ }
+//匹配时执行
+3: call(layer.handle, route, err, req, res, next);
+```
+
+**返回:**
+
+无
+
+**总结:**
+
+画图总结
+
+```
+request come
+ |
+ v
+middleware1 : 不匹配路由,skip
+ |
+ v
+middleware2 : 匹配路由,执行
+ |
+ v
+middleware3 : 匹配路由,执行
+ |
+ v
+middleware4 : 不匹配路由,skip
+ |
+ v
+ end
+```
+
+
+##call(handle, route, err, req, res, next)
+
+>这里有个比较有趣的知识,`console.log(Function.length)`会返回函数定义的参数个数。值跟在函数体内执行`arguments.length`一样。
+
+Connect中规定`function(err, req, res, next) {}`形式为错误处理函数,`function(req, res, next) {}`为正常的业务逻辑处理函数。那么,可以根据Function.length以判断它是否为错误处理函数。
+
+**输入:**
+
+|参数名 |描述 |
+|------|:---------------:|
+|handle|逻辑处理函数 |
+|route |路由 |
+|err |是否发生过错误 |
+|req |Nodejs对象 |
+|res |Nodejs对象 |
+|next |next函数 |
+
+**处理过程:**
+
+1. 是否有错误,本次handle是否是错误处理函数;
+2. 若有错误且handle为错误处理函数,则执行handle,本函数返回;
+3. 若没错误且handle不是错误处理函数,则执行handle,本函数返回;
+4. 如果上面两个都不满足,不执行handle,本函数调用next,返回;
+
+**返回:**
+
+无
+
+**总结:**
+
+call函数是一个执行者,根据当前`错误情况`和`handle类型`决定`是否执行`当前的handle。
+
+##listen
+
+创建一个httpServer,将Connect自己的业务逻辑作为requestHandler,监听端口
+
+代码
+
+```js
+var server = http.createServer(this);
+return server.listen.apply(server, arguments);
+```
+
+##图解Connect
+
+Connect将中间件存储在app.stack中,通过构造handle中的next函数在请求到来时依次调用这些中间件。
+
+图形总结
+
+```
+request app(out)
+ | yes
+ +------------------>match?----->middleware1
+ | no |
+ v |
+ next<----------+
+ |
+ v yes
+ match?------>middleware2
+ | no |
+ v |
+ next<----------+
+ |
+ v yes
+ match?------>middleware3
+ | no |
+ v |
+ out<-----------+
+ |
+ +---------------------+
+ |
+ v
+ end(response在处理过程中已经返回了)
+```
+
+##Connect的subapp特性
+
+我们再看看Connect是怎么实现subapp的,比较有趣。
+
+什么是subapp?
+
+```
+var sub_app = connect();
+var app = connect();
+
+app.use('/route1', sub_app);
+// request path: '/route1/route2'
+// 由app接收到请求后,切割 path为'/route2'转交给sub_app的处理逻辑处理
+// 再由sub_app返回到app,由app继续向下执行处理逻辑
+```
+
+结合上面的函数画图
+
+```
+request app(out1) sub_app(out2)
+ |
+ +--------------->middleware1 +------------>middleware1
+ | | |
+ next | next
+ | | |
+ v | v
+ middleware2-----+ middleware2
+ |
+ next<--------+ next
+ | | |
+ v | v
+ middleware3 | middleware3
+ | | |
+ v | v
+ out1 | out2
+ | | |
+ +---------------------+ +-----------------+
+ |
+ v
+ end(response在处理过程中已经返回了)
+```
+
+完成上面的sub_app只需要做到两点:
+
+1. 从app的调用链进入到sub_app的调用链中;
+2. 从sub_app的逻辑回到app的调用链中;
+
+connect在handle函数中的第三个参数`out`为这个特性实现提供可能。`out`的特点是`在middlewares链式调用完成以后调用`。**那么将app的next作为sub_app的out传入sub_app的handle中**可以做到sub_app自己的业务逻辑处理完后调用`out`,即处理权回到了本app的`next`手里。
+
+上面图中的`sub_app.out2===app.next`,所以能完成逻辑的交接和sub app调用。
+
+#[Express](https://github.com/strongloop/express)
+大家都知道Express是Connect的升级版。
+
+Express不只是Connect的升级版,它还封装了很多对象来方便业务逻辑处理。Express里的Router是Connect的升级版。
+
+Express大概可以分为几个模块
+
+|模块 |描述 |
+|-----------|:---------------------:|
+|router |路由模块是Connect升级版 |
+|request |经过Express封装的req对象 |
+|response |经过Express封装的res对象 |
+|application|app上面的各种默认设置 |
+
+简要介绍一下每个模块
+
+##Router
+
+在Connect中间件特性的基础上,加入了如下特性,是Connect的升级版
+
+1. 正则匹配route;
+2. 进行将http的方法在route中分解开;
+
+##Request
+
+在Request中集成了http.IncomingMessage(可读流+事件),并在其上增加了新的属性,方便使用,我们最常用的应该是
+req.param。
+
+##Response
+
+在Response中集成了http.ServerResponse(可写流+事件),并在其上增加了很多方便返回的函数,有我们熟悉的res.json、
+res.render、res.redirect、res.sendFile等等。
+
+我们可以拓展它写一个res.sendPersonInfoById。
+
+>关于流的题外话:req.pipe(res)的形式可以“完成发什么就返回什么”,而req.pipe(mylogic).pipe(res)可以添加自己的逻辑,
+我们的业务逻辑是把流读为String/Object再进行逻辑处理,处理完再推送给另一个stream,有没有可能在流的层面进行逻辑解
+耦提供服务呢?求大神解答了…至少这种写法在大流量、逻辑简单的情况下是有用的。
+
+##Application
+
+除了上面的三个模块以外,还需要有个地方存储整个app的属性、设置等。比较常用的是app.engine函数设置模板引擎。
+
+##Express小结
+
+Express是一个中间件机制的httpServer框架,它本身实现了中间件机制,它也包含了中间件。比如3.x版本的Express
+本身自带bodyParser、cookieSession等中间件,而在4.x中去掉了。包括TJ也写了很多中间件,比如node-querystring、
+connect-redis等。
+
+实现业务逻辑解耦时,中间件是从纵向的方面进行的逻辑分解,前面的中间件处理的结果可以给后面用,比如bodyParser把解析
+body的结果放在req.body中,后面的逻辑都可以从req.body中取值。由于中间件是顺序执行的,errHandler一般都放在最后,而log类的中间件则放在比较前面。
+
+#总结
+
+Connect用流程控制库的回调函数及中间件的思想来解耦回调逻辑;
+[Koa](https://github.com/koajs/koa)用Generator方法解决回调问题;
+
+我们应该也可以用事件、Promise的方式实现;
+
+PS: 用事件来实现的话还挺期待的,能形成网状的相互调用。