第I部分 入门
第1章 hapi简介 ··································3
1.1 hapi是什么 ··································4
1.1.1 hapi的特色 ································6
1.1.2 hapi是哪类框架 ························8
1.2 hapi的组成部分 ························11
1.2.1 服务器 ·····································13
1.2.2 连接 ·········································13
1.2.3 路由 ·········································13
1.2.4 handler ·····································13
1.2.5 插件 ·········································13
1.3 何时应该(不该)使用hapi ······14
1.3.1 何时应该使用hapi ··················14
1.3.2 何时不应该使用hapi ··············15
1.4 hapi的运作方式 ························15
1.4.1 安装hapi ··································15
1.4.2 创建服务器 ·····························16
1.4.3 添加路由 ·································16
1.4.4 注册插件 ·································17
1.4.5 运行hapi ··································18
1.5 获得帮助 ····································18
1.5.1 hapi.js网站 ······························19
1.5.2 Make Me hapi ··························19
1.5.3 GitHub ·····································19
1.5.4 IRC ···········································19
1.5.5 Stack Overflow ························20
目 录
1.5.6 阅读代码 ·································20
1.6 小结 ············································20
第2章 构建API ·································21
2.1 设计API ·····································21
2.1.1 你应该接受这个任务 ·············21
2.1.2 收集需求 ·································22
2.1.3 设计API接口 ·························22
2.2 准备工作 ····································23
2.2.1 工作目录 ·································23
2.2.2 准备数据库和样本数据 ·········23
2.2.3 sqlite3 node模块 ·····················24
2.3 获取和搜索食谱 ························25
2.3.1 server.route()介绍 ···················25
2.3.2 路由handler ····························26
2.3.3 接口A:获取所有食谱 ··········28
2.3.4 接口A:搜索食谱 ··················30
2.3.5 接口B:获取单一食谱 ··········31
2.4 编写可维护的代码 ····················32
2.4.1 模块化路由 ·····························32
2.4.2 用好server.bind():设置
handler中的上下文 ················33
2.4.3 模块化handler ························35
2.5 身份验证 ····································37
2.5.1 模式和策略 ·····························37
2.5.2 实现不记名token身份验证 ···38
2.5.3 使用用户凭据 ·························40
XVI hapi.js 实战
2.6 食谱创建和标星 ························40
2.6.1 测试接口 ·································40
2.6.2 接口C:创建食谱 ··················41
2.7 小结 ············································44
第3 章 构建网站 ·································45
3.1 DinDin 网站 ·······························45
3.1.1 网站的样子 ·····························45
3.1.2 网站是如何运作的 ·················47
3.1.3 设置 ·········································47
3.2 网页和静态内容服务 ················49
3.2.1 静态文件服务 ·························49
3.2.2 整个目录服务 ·························51
3.2.3 server.views():使用Handlebars
动态渲染视图 ·························53
3.2.4 DRY 视图:布局和片段 ········57
3.3 使用外部API ·····························60
3.3.1 使用Wreck:调用API···········60
3.3.2 动态主页 ·································62
3.3.3 食谱详情页 ·····························62
3.3.4 视图helper ······························65
3.4 管理登录和用户会话 ················67
3.4.1 hapi-auth-cookie 插件 ·············67
3.4.2 表单 ·········································69
3.4.3 实现登录 ·································71
3.4.4 创建食谱 ·································75
3.4.5 实现注销 ·································78
3.5 小结 ············································79
第II 部分 扩展工具箱
第4 章 深入理解路由和handler ·········83
4.1 深入理解路由 ····························83
4.1.1 hapi 的路由:路由的排序和
冲突处理 ·································83
4.1.2 路由方法 ·································84
4.1.3 参数化路径 ·····························85
4.1.4 hapi 如何选取路由 ··················88
4.2 构建自定义handler ···················90
4.2.1 国际化例子 ·····························91
4.2.2 解析Accept-Language
header ·······································92
4.2.3 第一个实现 ·····························93
4.2.4 再次简化 ·································94
4.3 服务器方法 ································96
4.4 路由先决条件 ····························99
4.4.1 异步JavaScript 的并发问题 ···99
4.4.2 指定路由先决条件 ·············· 101
4.4.3 使用带有先决条件的服务器
方法 ······································ 102
4.4.4 多重串行先决条件 ·············· 103
4.4.5 并发先决条件:并行地运行
任务 ······································ 105
4.5 管理文件上传 ··························107
4.5.1 使用数据输出:把文件内容
读入内存 ······························ 108
4.5.2 使用流输出:以流的方式获取
文件 ······································ 109
4.5.3 使用文件输出:把文件存储到
磁盘 ······································ 110
4.5.4 额外的payload 设置 ·············111
4.4 小结 ·········································· 111
第5 章 理解请求和响应 ····················113
5.1 request 对象和生命周期 ·········· 113
5.1.1 什么是request 对象 ············· 113
5.1.2 请求的生命周期 ·················· 115
5.1.3 扩展点 ·································· 118
5.1.4 应该使用哪个扩展点? ······ 121
5.2 reply 接口和response 对象 ·····121
5.2.1 什么是reply 接口? ············ 121
5.2.2 reply() 的有效参数 ··············· 123
XVII
目 录
5.2.3 response对象 ·······················124
5.2.4 使用流来响应 ······················126
5.3 处理错误 ··································128
5.3.1 程序员错误和操作错误 ······129
5.3.2 HTTP状态码 ·······················129
5.3.3 介绍Boom:创建HTTP
友好的错误 ··························131
5.3.4 网站友好的HTML错误
页面 ······································132
5.4 小结 ··········································136
第6章 使用Joi验证 ························139
6.1 介绍Joi·····································140
6.1.1 Joi的工作方式 ·····················140
6.1.2 一个简单例子:验证标量
类型 ······································141
6.1.3 一个更复杂的例子:验证一个
复合类型 ······························142
6.2 掌握Joi·····································144
6.2.1 了解API ·······························145
6.2.2 Joi.assert()和Joi.validate() ··146
6.2.3 Joi中的类型转换 ·················146
6.2.4 abortEarly选项 ·····················147
6.2.5 探索Joi错误 ························148
6.3 hapi中的验证 ··························150
6.3.1 使用Joi进行输入验证 ········150
6.3.2 验证payload ·························152
6.3.3 验证响应 ······························155
6.3.4 使用failAction自定义验证
响应 ······································156
6.4 整合:使用hapi和Joi进行Web
表单验证 ··································157
6.4.1 如何工作 ······························158
6.4.2 创建骨架 ······························159
6.4.3 创建路由和视图 ··················160
6.4.4 添加验证 ······························163
6.4.5 在表单中渲染错误 ··············165
6.4.6 表单提交成功后的重定向 ···167
6.5 小结 ··········································168
第7章 使用插件构建模块化应用 ·····169
7.1 插件思想 ··································169
7.1.1 插件的定义 ··························171
7.1.2 插件的作用 ··························172
7.1.3 把所有东西放进插件 ··········174
7.1.4 Pingoo应用 ··························174
7.2 创建和加载插件 ······················176
7.2.1 创建插件 ······························176
7.2.2 使用server.register()加载
插件 ······································179
7.2.3 插件依赖 ······························180
7.2.4 使用选项配置插件 ··············182
7.3 使用Glue组合插件 ················186
7.3.1 什么是Glue? ·····················186
7.3.2 创建一个清单 ······················187
7.3.3 使用Confidence工具实现智
能配置 ··································190
7.4 插件通信 ··································193
7.4.1 全局的服务器配置 ··············193
7.4.2 通过server.expose()在插件中
对外公开属性 ······················195
7.4.3 使用事件系统 ······················196
7.5 小结 ··········································200
第8章 充分利用缓存 ·······················201
8.1 客户端缓存 ······························202
8.1.1 手动设置header ···················203
8.1.2 在配置中设置缓存策略 ······203
8.1.3 重新验证和ETag ·················204
8.2 介绍Catbox:一个多策略的对象
缓存库 ······································207
8.2.1 什么是Catbox ······················208
XVIII hapi.js 实战
8.2.2 Catbox 客户端和策略 ·········· 211
8.2.3 Staleness ································ 213
8.2.4 应该用哪个缓存策略? ······ 215
8.3 hapi 应用中的服务器端缓存 ··216
8.3.1 配置客户端 ·························· 216
8.3.2 使用server.cache() 创建并使用
Catbox 策略 ·························· 217
8.3.3 缓存服务器方法 ·················· 219
8.3.4 使用键、分区和段来组织缓存
数据 ······································ 220
8.4 小结 ··········································222
第Ⅲ部分 创建健壮的应用
第9 章 身份验证和安全 ····················225
9.1 关于身份验证的深度探讨 ······225
9.1.1 hapi 身份验证概述 ··············· 226
9.1.2 应该选择哪种身份验证
模式 ·································228
9.1.3 身份验证的scope ················ 228
9.1.4 身份验证模式 ······················ 229
9.2 通过Bell 实现第三方身份
验证 ··········································231
9.2.1 什么是第三方身份验证 ······ 231
9.2.2 Bell 简介 ······························· 232
9.2.3 将Bell 整合进hapi 应用 ····· 233
9.3 通过CORS 管理跨域请求 ······240
9.3.1 允许来自任何地方的跨域
请求 ······································ 241
9.3.2 只接受指定源的访问 ·········· 243
9.3.3 处理自定义的header ··········· 244
9.3.4 CORS 和凭据(Cookie) ········ 246
9.3.5 CORS 设置的粒度 ··············· 247
9.4 使用Crumb 保护应用免受CSRF
攻击 ··········································248
9.4.1 通过CSRF 令牌对抗CSRF
攻击 ······································ 249
9.4.2 通过创建自己的漏洞来理解
CSRF ····································· 250
9.4.3 通过Crumb 保护HTML ····· 253
9.4.4 使用Crumb 保护restful
API ········································ 254
9.5 安全相关的header···················255
9.6 小结 ··········································257
第10 章 使用Lab、Code 和server.inject()
进行测试 ·····························259
10.1 Lab 简介 ·································259
10.1.1 第一个测试 ························ 260
10.1.2 Lab 作为本地依赖 ············· 261
10.1.3 通过experiments 组织
测试 ·······························262
10.1.4 默认异步执行 ···················· 263
10.1.5 Lab 的语法糖 ····················· 264
10.2 用Code 断言库制作断言 ······265
10.2.1 什么是Code 断言库 ·········· 265
10.2.2 Code 的语法:断言语句的
结构 ···································· 267
10.3 使用server.inject() 测试hapi
服务 ········································269
10.3.1 为测试准备server ·············· 270
10.3.2 server.inject() 的响应
参数 ···································· 272
10.3.3 使用request payload 进行
测试 ···································· 272
10.3.4 测试需要验证的路由 ········ 274
10.4 Lab 进阶 ·································276
10.4.1 reporter ································ 276
10.4.2 代码覆盖率 ························ 278
10.4.3 linting ·································· 278
10.4.4 全局变量泄露 ···················· 279
目 录 XIX
10.4.5 并行执行测试 ····················279
10.5 使用stub、spies和monkey-patching
测试难以测试的代码 ············281
10.5.1 monkey-patching介绍 ·······281
10.5.2 使用Sinon的Spy和stub ····284
10.5.3 使用proxyquire ··················286
10.6 小结 ········································288
第11章 投入生产环境及更多相关
内容 ····································291
11.1 hapi的日志记录和Good ·······291
11.1.1 hapi中的服务器事件 ·········291
11.1.2 通过request.log()和
server.log()记录日志 ·········293
11.1.3 通过Good记录线上日志和
处理监控 ····························296
11.1.4 使用多种reporter实例 ······297
11.2 为路由生成文档 ····················298
11.2.1 路由的tags、notes和
descriptions ·························299
11.2.2 通过Lout自动生成的
文档 ····································299
11.3 监控 ········································302
11.3.1 Graphite和StatsD ··············302
11.3.2 通过StatsD度量任何指标 ···303
11.3.3 使用Oppsy获取hapi的操作
数据 ····································304
11.4 调试 ········································307
11.4.1 不要认为使用console.log()
不好 ····································307
11.4.2 Node debug ·························307
11.4.3 Node Inspector ····················309
11.4.4 通过Poop进行Core
dumps ··································310
11.4.5 使用hapi TV调试实时
请求 ····································312
11.5 部署支持SSL/TLS的应用 ···314
11.5.1 TLS的配置项 ·····················314
11.5.2 在hapi中配置TLS连接 ···315
11.5.3 使用self-signed凭据测试
SSL ······································315
11.5.4 强制HTTPS ·······················317
11.6 小结 ········································319
附录A Node.js和npm入门 ·············321
附录B 本书用到的npm包 ···············327
· · · · · · (
收起)