HTTP开发之Connect工具集——中间件

继学习node.js的TCP API和HTTP API之后,node.js web开发进入了正轨,但这就好像Java的servlet一样,我们不可能使用最基础得Servlet对象去写网站,我们也不能使用最基本的node http API去写一个完整得网站,我们需要更加强大得工具集,web套件,甚至是web开发框架(诸如Java下的Spring MVC),来提供开发者更人性化得web开发环境。

创建网站的基本任务——为何要有中间件

  1. 独立托管静态文件,诸如:html,css,js,images
  2. 处理错误和不存在的地址
  3. 处理不同类型的请求

如果我们上来就直接用上一章的http模块来做的话,我们需要先实现一个“框架”才能做到一个网站最基本的任务,如果是运用生产环境的话,我们希望有这样的一个“框架”——connect工具集,最好称它为工具集,他离所谓的“框架”依旧有点差距。

Connect是基于http API之上的,也就是基于node http模块写出来的,方便web开发者使用,他提供了一些工具方法能够上一些重复性的工作便于实现,让开发者更加专注于应用的功能业务。

Connect已经是十分基础的node web开发工具集,在实际开发中很少看到,以后回介绍稍微高级点的express(对于实际开发来说依然很基础)

特别注意:《了不起的node.js》一书中的代码和connect版本过时了,如果使用最新版的connect需要参照如下方法使用!

导入Connect等中间件模块

Connect模块并非node.js的原生模块,需要引入外部模块

同时还要导入“serve-static”,“content-disposition”提供静态文件访问支持

最终完整package.json:

{
"name":"node-connect",
"version":"0.0.1",
"description":"Use connect to create a website",
"dependencies":{
"connect":"latest",
"serve-static":"latest",
"content-disposition":"latest"
}
}

node npm包搜索管理网站:https://www.npmjs.com/

注:除了connect外,还导入了serve-static,这个包原本属于connect集合,后官方独立出来了,《了不起的node.js》使用的是1.8.x版本的connect(太老了)还包含着static中间件,这里使用了3.0.0+的版本,则需要额外导入这个静态中间件模块。

这些是官网独立的中间件(Connect/Express负责管理)

将不同功能的中间件从connect独立出来是一件好事,方便管理维护!(对于开发者需要注意查看更新)

npm install

引用connect模块

//引入connect模块
var connect = require("connect");
//依然需要引入http模块
var http = require("http")
//依然使用http模块创建服务器
http.createServer().listen(3000);

connect现在是http中间件,如果使用本文最新的connect版本就不能出现《了不起的node.js》一书中的connect.createServer(),因为connect已经移除了这个方法!!!

createServer交给了http模块去做,充分体现了connect是中间件的特性,而不是代替http!

依然使用http.createServer()创建http服务器!!!

使用serve-static中间件托管静态文件

node本身不像nginx,apache,他不是一个完整的http服务器,而是一个语言解析器。

通过对node.js API的开发,可以构建类似nginx一样的功能,负责提供用户静态页面,这就需要用到serve-static中间件

首先serve-static中间件原本属于connect中间件,现在已经独立出来了,也就说其实和connect关系已经不大了,但我依然将两者放在一回中解说。

静态文件指的是:html,css,图片,js等等

在项目目录下新建一个views目录,存放静态html文件

新建index.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>hello world</h1>
</body>
</html>

index.js返回静态页面代码:

//引入http模块
var http = require("http");
//引入serveStatic模块
var serveStatic = require('serve-static')
var finalhandler = require('finalhandler'); var serve = serveStatic(__dirname+'/views',{'index':['index.html','index.htm']}); http.createServer(function(req,res){
serve(req,res,finalhandler(req,res));
}).listen(3000);

finalhandler是什么?

作用是友好处理找不到页面访问不到URL的异常和错误,如果删除,用户访问非法地址将会导致node抛出异常停止工作。

访问首页之外的页面?

views下创建一个hello.html,直接在浏览器地址后面+“/hello.html”即可访问这个页面。

访问图片文件?

如何提示下载文件?

var contentDisposition = require('content-disposition')
var finalhandler = require('finalhandler')
var http = require('http')
var serveStatic = require('serve-static') var serve = serveStatic(__dirname+'/files', {
'index': false,
'setHeaders': setHeaders
}) //强制下载
function setHeaders (res, path) {
res.setHeader('Content-Disposition', contentDisposition(path))
} http.createServer(function onRequest (req, res) {
serve(req, res, finalhandler(req, res))
}).listen(3000);

新建一个files目录,下载的文件放在里面即可。

到此,serve-static中间件简化了开发者托管静态文件的代码,我们不必向上一章那样使用fs+http方式去自己实现输出流文件给浏览器客户端。

使用connect中间件处理不同的请求

在上一回中,如果要对用户不同访问给出对应的返回,我们需要在同一个createServer中不停的写if...else if....else if...else....if.........来判断,这样显得代码十分冗余,而且根本无法把所有情况写清楚,也无法扩展,且根本无法维护。

上一回的部分代码:

	//请求为图片
if(req.method == 'GET' && req.url.substr(-4)==".jpg"){
fs.stat(__dirname+req.url,function(err,stat){
if(err || !stat.isFile()){
res.writeHead(404);
res.end("找不到图片");
return;
}
serve(__dirname+req.url,'application/x-jpg');
});
}else if(req.method=="GET" && req.url=='/'){
//请求为html文件
serve(__dirname+'/form.html','text/html');
}else{
res.writeHead(404);
res.end("网址丢了");
return;
}

接下来使用connect重写这些代码:(代码是基于static-serve那块修改过来的)

//下载文件模块
var contentDisposition = require('content-disposition')
//不需要finalhandler
//var finalhandler = require('finalhandler')
//http模块创建http服务器必须
var http = require('http')
//静态文件托管中间件
var serveStatic = require('serve-static')
//connect工具集
var connect = require("connect");
var app = connect(); app.use(function(req,res,next){
//任何请求都会打印!是必然执行的一步
console.error('%s %s',req.method,req.url)
next();
}); //图片显示
app.use("/images",function(req,res,next){
serveStatic(__dirname+"/images")(req,res,next);
});
//下载文件
app.use("/files",function(req,res,next){
serveStatic(__dirname+"/files",{'index':false,'setHeaders':setHeaders})(req,res,next);
}); //最终处理,所有next都执行不通后到达此处
app.use(function(req,res,next){
res.writeHead(404);
res.end('404 Not Found')
//没有next了,这是最终方法,返回404 not found就行了
}); //强制下载函数
function setHeaders (res, path) {
res.setHeader('Content-Disposition', contentDisposition(path))
}
//建立http服务器
http.createServer(app).listen(3000);

注意到我们依然需要http模块来建立http服务器,然后引入了connect模块,以及之前的serve-static和content-disposition。

这一段代码实际上是把上一回分类请求处理和这一回静态文件托管强强联手了

如果说serve-static这个中间件解决的是静态文件托管的话,那么connect中间件其实是解决了路由,请求定向的控制。这样我们不再需要通过手写的if...else来判断用户请求了什么类型的文件。

next()函数

这个函数在connect中扮演了十分重要的角色,作用:将不同种类的请求线性的串联在一行,每一个app.use()其实类似于原来我们写的if...else语句,next就是在处理不了的情况下,执行另一个app.use(),这样只要回掉函数做不了就抛给下一个做,这样不停的“甩锅”,最终谁都做不了就有一个最终函数,开发者需要建立这样的最终函数,里面没有next()了,说明到最后一步了,必须返回错误给用户看了。我们这里最终函数是一个404错误反馈。

use()函数

第一个参数可以给定一个请求的目录,相对于node执行的项目目录,相当于浏览器网址后面第一个“/”后面的参数。

将js进行到底:node学习5的更多相关文章

  1. 【特别推荐】Node.js 入门教程和学习资源汇总

    这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...

  2. Node.js 入门教程和学习资源汇总

    这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...

  3. Node.js环境搭建和学习(windwos环境)

    Node.js环境搭建和学习 一.环境搭建 1.下载安装文件 下载地址http://nodejs-org.qiniudn.com/下载Node.js环境安装包,根据操作系统下载对应的安装包 下载地址 ...

  4. node 学习笔记 - Modules 模块加载系统 (1)

    本文同步自我的个人博客:http://www.52cik.com/2015/12/11/learn-node-modules-path.html 用了这么久的 require,但却没有系统的学习过 n ...

  5. [学姿势]实验室搬砖+node学习

    这周开始进行收尾工作,我当然没有进行核心技术的开发,主要负责的是对web端进行展示上的修修补补,主要包括添加VLC播放器.rtsp视频流以及一些js细节. 1.VLC 全称为Video Lan Cli ...

  6. 2015第40周二Node学习

    node历史 今天看cnode开源项目用了io.js,在查这个项目时发现这篇文章node历史,node.js和io.js关系谈到Node.js的由来,不可避免要聊到它的创始人Ryan Dahl.在20 ...

  7. 2015第40周一Node学习

    node学习尝试 早上看了张丹大牛博客文章nodeJS学习路线图和node从零入门系列,感觉获益匪浅,尝试了里面几项内容,对node有了更深入的认识. npm npm是一个node包管理和分发工具,已 ...

  8. Node学习——开篇

    前言:自从下决心转学前端以来,我的专业课java基本荒废了,所以对于后台开发的逻辑也已基本忘干净了.但是作为一名准前端程序猿,我认为还是有必要了解后端开发的,虽不必深入学习,但是能够了解项目从前端到后 ...

  9. node 学习资料

    Node 学习资料: 资料名称 网址 Node.js 中文API文档 http://nodejs.cn/api/ Node 菜鸟教程 http://www.runoob.com/nodejs/node ...

  10. Node学习HTTP模块(HTTP 服务器与客户端)

    Node学习HTTP模块(HTTP 服务器与客户端) Node.js 标准库提供了 http 模块,其中封装了一个高效的 HTTP 服务器和一个简易的HTTP 客户端.http.Server 是一个基 ...

随机推荐

  1. git submodule update --init 和 --remote的区别

    git 的submodule 工具方便第三方库的管理,比如gitlab 上的各种开源工具,spdlog等 在项目目录下创建.gitmodule 里可以添加第三方库,然后在更新第三方库时,有两个选项 g ...

  2. Mysql 环境部署

    1.Window 1.1 下载软件: https://dev.mysql.com/downloads/mysql/ 依次点击上图 红色框中按钮 1.2 安装软件 1.2.1 解压软件 正常解压即可  ...

  3. MySQL——事务(transaction)简单总结

    简介: MySQL事务操作主要用于处理操作量大,复杂度高的数据,比如说,在人员管理系统中要删除一个人员,你既要删除他的基本资料,也要删除该人员的相关信息,如文章.信箱等.这些数据库操作语句就构成了一个 ...

  4. 整理平时常用git命令

    git常用命令 git创建分支 #创建本地分支并切换到新创建的分支 $ git checkout -b newbranch #将新创建的分支信息推送到github $ git push origin ...

  5. grub.cfg文件编辑

    grub2启动项里面找不到Windows的情况,这时候就需要自己去配置grub.cfg 在grub.cfg中加入如下代码: menuentry 'Windows Boot Manager (on /d ...

  6. python爬虫破解带有CryptoJS的aes加密的反爬机制

    发现问题 在一次偶然中,在爬取某个公开网站(非商业型网站)时,老方法,打开调试工具查看请求方式,请求拦截,是否是异步加载,不亦乐乎,当我以为这个网站非常简单的时候,发现二级网页的地址和源码不对应 Aj ...

  7. 蓝桥杯 Car的旅行路线 (预处理+最短路径)

    https://www.luogu.org/problem/P1027 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有4个飞机场,分别位于一个矩形的4个顶点上,同 ...

  8. 微信小程序裁剪图片后上传

    上传图片的时候调起裁剪页面,裁剪后再回调完成上传; 图片裁剪直接用we-cropper   https://github.com/we-plugin/we-cropper we-cropper使用详细 ...

  9. shell的集合运算

    用cat,sort,uniq命令实现文件行的交集 .并集.补集 交集 $F_1 \cap F_2 $ cat f1 f2 | sort | uniq -d 并集 $F_1 \cup F_2 $ cat ...

  10. C++ malloc()函数的注意点及使用示例

    1.malloc()函数的头文件是stdlib.h,其函数声明如下: void* malloc(size_t size); 其中参数size_t size表示动态内存分配空间的大小,以字节为单位. s ...