网络埋伏纪事

Node Hero - 4. 第一个 Node.js HTTP 服务器

网络埋伏纪事 · 2016-11-21翻译 · 1570阅读 原文链接

本章我会指导你启动一个简单的 Node.js HTTP 服务器,并开始为请求服务。

Node.js 服务器的 http 模块

当开始在 Node.js 中构建基于 HTTP 的应用程序时,内置的 http/https 模块就是你要与之交互的模块。

现在,我们开始创建第一个 Node.js HTTP 服务器!我们将 require http 模块,并将服务器绑定到 3000 端口来监听。

// index.js 的内容
const http = require('http')  
const port = 3000

const requestHandler = (request, response) => {  
  console.log(request.url)
  response.end('Hello Node.js Server!')
}

const server = http.createServer(requestHandler)

server.listen(port, (err) => {  
  if (err) {
    return console.log('something bad happened', err)
  }

  console.log(`server is listening on ${port}`)
})

可以用如下命令启动:

$ node index.js

这里要注意:

  • requestHandler: 每次请求到达服务器时,该函数都会被调用。如果从浏览器访问 localhost:3000,就会出现两条日志信息:一条是 /,一条是 favicon.ico
  • if (err): 错误处理 - 如果端口已被占用,或者服务器因为其它原因不能启动,就会在这里得到通知

http 模块是很低层的 - 用上面的代码片段创建复杂的 Web 应用程序是很耗时间的。这就是为什么我们经常会为项目选用一个框架的原因。有很多框架可以选,但是最重要的是这些:

本章和下一章我们打算用 Express,因为在 NPM 上可以找到的 Express 模块最多。

Express

> 快速、开放、极简的 Node.js Web 框架 - http://expressjs.com/

将 Express 添加到项目中的唯一方法是 NPM 安装:

$ npm install express --save

安装完 Express 后,我们来看看如何创建一个像以前那样的应用程序:

const express = require('express')  
const app = express()  
const port = 3000

app.get('/', (request, response) => {  
  response.send('Hello from Express!')
})

app.listen(port, (err) => {  
  if (err) {
    return console.log('something bad happened', err)
  }

  console.log('server is listening on ${port}')
})

这里你必须注意到的最大区别是,Express 默认给了一个路由器。不需要手动检测 URL 来判断要做什么,而是用 app.getapp.postapp.put 等定义应用程序的路由。它们会被翻译为对应的 HTTP 动词。

Express 实现的最强大概念之一是中间件模式。

中间件

可以把中间件当作是 Unix 管道,但是是对 HTTP 请求的管道。

Express middlewares for building a Node.js HTTP server

在图中你可以看到一个请求是如何通过 Express 应用程序的。它经历了三个中间件。每个中间件都可以修改它,然后基于业务逻辑,要么第三个中间件送回一个响应,要么将它送到一个路由处理器。

在实践中,可以按这种方式做:

const express = require('express')  
const app = express()

app.use((request, response, next) => {  
  console.log(request.headers)
  next()
})

app.use((request, response, next) => {  
  request.chance = Math.random()
  next()
})

app.get('/', (request, response) => {  
  response.json({
    chance: request.chance
  })
})

app.listen(3000)

这里要注意:

  • app.use: 在这里定义中间件 - 它带有三个参数的函数,第一个是请求,第二个是响应,第三个是 next 回调。调用 next 就是通知 Express 可以跳到下一个中间件,或者路由处理器。
  • 第一个中间件只是记录请求头,然后立即调用下一个。
  • 第二个中间件给请求添加一个特殊属性 - 这是中间件模式最强大的功能之一。你的中间件可以向 request 对象添加额外的数据,这个数据可以被下游中间件读取或修改。

错误处理

在所有框架中,正确的错误处理是至关重要的。在 Express 中,必须创建特殊的中间件函数来实现 - 一个带有四个参数的中间件:

const express = require('express')  
const app = express()

app.get('/', (request, response) => {  
  throw new Error('oops')
})

app.use((err, request, response, next) => {  
  // log the error, for now just console.log
  console.log(err)
  response.status(500).send('Something broke!')
})

这里要注意:

  • 错误处理函数应该是用 app.use 添加的最后一个函数。
  • 错误处理器有一个 next 回调 - 它可以用来将多个错误处理器链在一起。

渲染 HTML

至此,我们已经了解了如何发送 JSON 响应 - 是时候学习如何用简单方法渲染 HTML 了。为此,我们要使用 express-handlebars 中的 handlebars 包。

首先,创建如下的目录结构:

├── index.js
└── views
    ├── home.hbs
    └── layouts
        └── main.hbs

之后,用如下代码片段填充 index.js

// index.js
const path = require('path')  
const express = require('express')  
const exphbs = require('express-handlebars')

const app = express()

app.engine('.hbs', exphbs({  
  defaultLayout: 'main',
  extname: '.hbs',
  layoutsDir: path.join(__dirname, 'views/layouts')
}))
app.set('view engine', '.hbs')  
app.set('views', path.join(__dirname, 'views'))

上述代码初始化 handlebars 引擎,将布局目录设置为 views/layouts。布局将会存在这个目录中。

设置好后,可以把初始 html 放进 main.hbs 中 - 为保持简单,我们就用这个:

<html>  
  <head>
    <title>Express handlebars</title>
  </head>
  <body>
    {{{body}}}
  </body>
</html>

这里的 {{{body}}} 占位符,就是放内容的地方 - 下面我们创建 home.hbs

<h2>Hello {{name}}<h2>

要让它起作用,我们得做最后一件事情:给 Express 应用程序添加一个路由处理器:

app.get('/', (request, response) =&gt; {  
  response.render('home', {
    name: 'John'
  })
})

render 方法带有两个参数:

  • 第一个是视图的名称;
  • 第二个是要渲染的数据。

一旦调用这个端点,会得到如下的 HTML:

&lt;html&gt;  
  &lt;head&gt;
    &lt;title&gt;Express handlebars&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    <h2>Hello John<h2>
  &lt;/body&gt;
&lt;/html&gt;

这只是冰山一角 - 要学习如何添加更多布局甚至局部模板,请参考官方 express-handlebars 文档。

调试 Express

在某些情况下,你可能需要看到应用程序正在运行时 Express 发生了什么。为此,可以传递如下环境变量给 Express:DEBUG=express*

必须用如下方式启动 Node.js HTTP 服务器:

$ DEBUG=express* node index.js

总结

本章学习了如何从头开始创建第一个 Node.js HTTP 服务器。我推荐用 Express 开始,然后随意去尝试。

下章会学习如何从数据库获取信息

相关文章