写点什么

使用 nodejs 和 express 搭建 http web 服务

发布于: 2021 年 01 月 15 日

简介

nodejs 作为一个优秀的异步 IO 框架,其本身就是用来作为 http web 服务器使用的,nodejs 中的 http 模块,提供了很多非常有用的 http 相关的功能。


虽然 nodejs 已经带有 http 的处理模块,但是对于现代 web 应用程序来说,这或许还不太够,于是我们有了 express 框架,来对 nodejs 的内容进行扩展。


今天我们将会介绍一下使用 nodejs 和 express 来开发 web 应用程序的区别。


使用 nodejs 搭建 HTTP web 服务

nodejs 提供了 http 模块,我们可以很方便的使用 http 模块来创建一个 web 服务:


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 服务。


该方法接受一个 callback 函数,函数的两个参数分别是 req (http.IncomingMessage 对象)和一个 res(http.ServerResponse 对像)。


在上面的例子中,我们在 response 中设置了 header 和 body 值,并且以一个 end 方法来结束 response。


请求 nodejs 服务

我们创建好 http web 服务之后,一般情况下是从 web 浏览器端进行访问和调用。但是我们有时候也需要从 nodejs 后端服务中调用第三方应用的 http 接口,下面的例子将会展示如何使用 nodejs 来调用 http 服务。


先看一个最简单的 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 也可以使用同样的方式来调用。


第三方 lib 请求 post

直接使用 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 来进行相应数据的处理。非常的方便。


获取 http 请求的正文

在上面的例子中,我们通过监听 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 搭建 http web 服务

express 是什么呢?


express 是基于 Node.js 平台,快速、开放、极简的 web 开发框架。它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。


丰富的 HTTP 快捷方法和任意排列组合的 Connect 中间件,让你创建健壮、友好的 API 变得既快速又简单。


Express 不对 Node.js 已有的特性进行二次抽象,我们只是在它之上扩展了 Web 应用所需的基本功能。


express helloworld

我们看一下怎么使用 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 服务。


express 路由

有了 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 和 abcdapp.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 和 /abcdeapp.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 路由句柄中间件

有时候,一个请求可能有多个处理器,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 响应方法

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 中,可以使用 express.static 来指定静态资源的路径:


app.use(express.static('public'));现在,public 目录下面的文件就可以访问了。http://localhost:3000/images/kitten.jpghttp://localhost:3000/css/style.csshttp://localhost:3000/js/app.jshttp://localhost:3000/images/bg.pnghttp://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.jpghttp://localhost:3000/static/css/style.css
复制代码

Express 使用模板引擎

web 应用当然需要 html 文件,express 中可以使用多种模板语言,让编写 html 页面更加容易。如果想要使用模板引擎。我们可以使用下面的步骤:


  1. views, 放模板文件的目录,比如: app.set(‘views’, ‘./views’)

  2. view engine, 模板引擎,比如: app.set(‘view engine’, ‘jade’)

  3. 在 views 目录下生成名为 index.jade 的 Jade 模板文件,内容如下:

html  head    title!= title  body    h1!= message
复制代码
  1. 在 nodejs 服务端配置 route 规则

//配置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 的博客

欢迎关注我的公众号:「程序那些事」最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!


发布于: 2021 年 01 月 15 日阅读数: 33
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
使用nodejs和express搭建http web服务