nodejs做为一个优秀的异步IO框架,其自己就是用来做为http web服务器使用的,nodejs中的http模块,提供了不少很是有用的http相关的功能。css
虽然nodejs已经带有http的处理模块,可是对于现代web应用程序来讲,这或许还不太够,因而咱们有了express框架,来对nodejs的内容进行扩展。html
今天咱们将会介绍一下使用nodejs和express来开发web应用程序的区别。node
nodejs提供了http模块,咱们能够很方便的使用http模块来建立一个web服务:ios
const http = require('http') const hostname = '127.0.0.1' const port = 3000 const server = http.createServer((req, res) => { res.statusCode = 200 res.setHeader('Content-Type', 'text/plain') res.end('welcome to www.flydean.com\n') }) server.listen(port, hostname, () => { console.log(`please visit http://${hostname}:${port}/`) })
上面建立的http服务监听在3000端口。咱们经过使用createServer方法来建立这个http服务。web
该方法接受一个callback函数,函数的两个参数分别是 req (http.IncomingMessage 对象)和一个res(http.ServerResponse 对像)。express
在上面的例子中,咱们在response中设置了header和body值,而且以一个end方法来结束response。json
咱们建立好http web服务以后,通常状况下是从web浏览器端进行访问和调用。可是咱们有时候也须要从nodejs后端服务中调用第三方应用的http接口,下面的例子将会展现如何使用nodejs来调用http服务。axios
先看一个最简单的get请求:后端
const http = require('http') const options = { hostname: 'www.flydean.com', port: 80, path: '/', method: 'GET' } const req = http.request(options, res => { console.log(`status code: ${res.statusCode}`) res.on('data', d => { console.log(d); }) }) req.on('error', error => { console.error(error) }) req.end()
上面代码咱们使用了http.request来建立一个request,而且传入了咱们自带的options参数。数组
咱们经过res的回调事件来进行相应的处理。
再看一个简单的post请求:
const http = require('http') const data = JSON.stringify({ name: 'flydean' }) const options = { hostname: 'www.flydean.com', port: 80, path: '/', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': data.length } } const req = http.request(options, res => { console.log(`status code: ${res.statusCode}`) res.on('data', d => { console.log(d); }) }) req.on('error', error => { console.error(error) }) req.write(data) req.end()
post和get类似,不一样的是options中的method不同,同时put能够有多种请求类型,因此咱们须要在headers中指定。
一样的,PUT 和 DELETE 也可使用一样的方式来调用。
直接使用nodejs底层的http.request有点复杂,咱们须要本身构建options,若是使用第三方库,好比axios可让post请求变得更加简单:
const axios = require('axios') axios .post('http://www.flydean.com', { name: 'flydean' }) .then(res => { console.log(`status code: ${res.statusCode}`) console.log(res) }) .catch(error => { console.error(error) })
上面的例子中,咱们直接使用axios的post请求,并将请求结果封存成了promise,而后经过then和catch来进行相应数据的处理。很是的方便。
在上面的例子中,咱们经过监听req的data事件来输出http请求的正文:
res.on('data', d => { console.log(d); }) })
这样作实际上是有问题的,并不必定可以得到完整的http请求的正文。
由于res的on data事件是在服务器得到http请求头的时候触发的,这个时候请求的正文可能尚未传输完成,换句话说,请求回调中的request是一个流对象。
咱们须要这样处理:
const server = http.createServer((req, res) => { let data = [] req.on('data', chunk => { data.push(chunk) }) req.on('end', () => { console.log(JSON.parse(data)); }) })
当每次触发data事件的时候,咱们将接受到的值push到一个数组里面,等全部的值都接收完毕,触发end事件的时候,再统一进行输出。
这样处理显然有点麻烦。
咱们介绍一个在express框架中的简单方法,使用 body-parser 模块:
const bodyParser = require('body-parser') app.use( bodyParser.urlencoded({ extended: true }) ) app.use(bodyParser.json()) app.post('/', (req, res) => { console.log(req.body) })
上面的例子中,body-parser对req进行了封装,咱们只用关注与最后的结果便可。
express是什么呢?
express是基于 Node.js 平台,快速、开放、极简的 web 开发框架。它提供一系列强大的特性,帮助你建立各类 Web 和移动设备应用。
丰富的 HTTP 快捷方法和任意排列组合的 Connect 中间件,让你建立健壮、友好的 API 变得既快速又简单。
Express 不对 Node.js 已有的特性进行二次抽象,咱们只是在它之上扩展了 Web 应用所需的基本功能。
咱们看一下怎么使用Express来搭建一个helloworld:
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!'); }); var server = app.listen(3000, function () { var host = server.address().address; var port = server.address().port; console.log('Example app listening at http://%s:%s', host, port); });
简单的使用app.listen便可搭建好一个http web服务。
有了web服务,咱们须要对不一样的请求路径和请求方式进行不一样的处理,这时候就须要使用到了express路由功能:
// 对网站首页的访问返回 "Hello World!" 字样 app.get('/', function (req, res) { res.send('Hello World!');}); // 网站首页接受 POST 请求 app.post('/', function (req, res) { res.send('Got a POST request');}); // /user 节点接受 PUT 请求 app.put('/user', function (req, res) { res.send('Got a PUT request at /user');}); // /user 节点接受 DELETE 请求 app.delete('/user', function (req, res) { res.send('Got a DELETE request at /user');});
更高级一点的,咱们还能够在请求路径中作路由匹配:
// 匹配 acd 和 abcd app.get('/ab?cd', function(req, res) { res.send('ab?cd');}); // 匹配 abcd、abbcd、abbbcd等 app.get('/ab+cd', function(req, res) { res.send('ab+cd'); }); // 匹配 abcd、abxcd、abRABDOMcd、ab123cd等 app.get('/ab*cd', function(req, res) { res.send('ab*cd'); }); // 匹配 /abe 和 /abcde app.get('/ab(cd)?e', function(req, res) { res.send('ab(cd)?e');}); // 匹配任何路径中含有 a 的路径: app.get(/a/, function(req, res) { res.send('/a/'); }); // 匹配 butterfly、dragonfly,不匹配 butterflyman、dragonfly man等 app.get(/.*fly$/, function(req, res) { res.send('/.*fly$/'); });
有时候,一个请求可能有多个处理器,express提供了路由句柄(中间件)的功能,咱们可自由组合处理程序。
注意,在路由句柄中,咱们须要调用next方法,来触发下一个路由方法。
var cb0 = function (req, res, next) { console.log('CB0'); next();} var cb1 = function (req, res, next) { console.log('CB1'); next();} app.get('/example/d', [cb0, cb1], function (req, res, next) { console.log('response will be sent by the next function ...'); next(); }, function (req, res) { res.send('Hello from D!'); });
上面的请求会通过cb0,cb1和自定义的两个function,最终结束。
express提供了不少响应方法API,能够方便咱们的代码编写:
方法 | 描述 |
---|---|
res.download() | 提示下载文件。 |
res.end() | 终结响应处理流程。 |
res.json() | 发送一个 JSON 格式的响应。 |
res.jsonp() | 发送一个支持 JSONP 的 JSON 格式的响应。 |
res.redirect() | 重定向请求。 |
res.render() | 渲染视图模板。 |
res.send() | 发送各类类型的响应。 |
res.sendFile | 以八位字节流的形式发送文件。 |
res.sendStatus() | 设置响应状态代码,并将其以字符串形式做为响应体的一部分发送。 |
一般来讲,静态资源是不须要服务端进行处理的,在express中,可使用express.static来指定静态资源的路径:
app.use(express.static('public')); 如今,public 目录下面的文件就能够访问了。 http://localhost:3000/images/kitten.jpg http://localhost:3000/css/style.css http://localhost:3000/js/app.js http://localhost:3000/images/bg.png http://localhost:3000/hello.html //多个静态资源目录 app.use(express.static('public')); app.use(express.static('files')); //静态前缀 app.use('/static', express.static('public')); http://localhost:3000/static/images/kitten.jpg http://localhost:3000/static/css/style.css
web应用固然须要html文件,express中可使用多种模板语言,让编写html页面更加容易。若是想要使用模板引擎。咱们可使用下面的步骤:
views, 放模板文件的目录,好比: app.set('views', './views')
view engine, 模板引擎,好比: app.set('view engine', 'jade')
在 views 目录下生成名为 index.jade 的 Jade 模板文件,内容以下:
html head title!= title body h1!= message
//配置route 规则 app.get('/', function (req, res) { res.render('index', { title: 'Hey', message: 'Hello there!'}); });
nodejs和express是很是方便的http web服务框架,但愿你们可以喜欢。
本文做者:flydean程序那些事
本文连接:http://www.flydean.com/nodejs-http-express/
本文来源:flydean的博客
欢迎关注个人公众号:「程序那些事」最通俗的解读,最深入的干货,最简洁的教程,众多你不知道的小技巧等你来发现!