Node.js网络通信(三)——构建http服务之创建http服务、根据url处理响应、响应html内容、处理页面中的静态资源、使用模版引擎& 构建https服务之原理、CA证书、搭建https服务器

Node.js网络通信(三)——构建http服务之创建http服务、根据url处理响应、响应html内容、处理页面中的静态资源、使用模版引擎& 构建https服务之原理、CA证书、搭建https服务器

第4章 构建 HTTP 服务

在这里插入图片描述

内容安排:

  • Node 中的 http 模块
  • 使用 Node 构建 http 服务
  • 实现一个静态文件服务器
  • 使用模板引擎处理动态网页
  • 结合数据库渲染动态页面
  • 实现一个留言本案例
  • 第三方 HTTP 服务框架

Node 中的 http 模块

TCP 和 UDP 都属于网络传输层协议,如果要构建高效的网络应用,就应该从传输层进行着手。但是对于经典的浏览器网页和服务端通信场景,如果单纯的使用更底层的传输层协议则会变得麻烦。

所以对于经典的B(Browser)S(Server)通信,基于传输层之上专门制定了更上一层的通信协议:HTTP,用于浏览器和服务端进行通信。由于 HTTP 协议本身并不考虑数据如何传输及其他细节问题,所以属于应用层协议。

Node 提供了基本的 http 和 https 模块用于 HTTP 和 HTTPS 的封装。

const http = require('http')
const server = http.createServer()

Server 实例

API 说明
Event:‘close’ 服务关闭时触发
Event:‘request’ 收到请求消息时触发
server.close() 关闭服务
server.listening 获取服务状态

请求对象

API 说明
request.method 请求方法
request.url 请求路径
request.headers 请求头
request.httpVersion 请求HTTP协议版本

响应对象

API 说明
response.end() 结束响应
response.setHeader(name, value) 设置响应头
response.removeHeader(name, value) 删除响应头
response.statusCode 设置响应状态码
response.statusMessage 设置响应状态短语
response.write() 写入响应数据
response.writeHead() 写入响应头

使用 Node 构建 http 服务

Hello World

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('Hello World\n')
})

server.listen(port, hostname, () => {
    
    
  console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

根据不同 url 处理不同请求

const http = require('http')

const hostname = '127.0.0.1'
const port = 3000

const server = http.createServer((req, res) => {
    
    
  const url = req.url
  if (url === '/') {
    
    
    res.end('Hello World!')
  } else if (url === '/a') {
    
    
    res.end('Hello a!')
  } else if (url === '/b') {
    
    
    res.end('Hello b!')
  } else {
    
    
    res.statusCode = 404
    res.end('404 Not Found.')
  }
})

server.listen(port, hostname, () => {
    
    
  console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

响应 HTML 内容

const http = require('http')
const fs = require('fs')

const hostname = '127.0.0.1'
const port = 3000

const server = http.createServer((req, res) => {
    
    
  fs.readFile('./index.html', (err, data) => {
    
    
    if (err) {
    
    
      throw err
    }
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/html; charset=utf-8')
    res.end(data)
  })

//   res.end(`
// <h1>Hello World!</h1>
// <p>你好,世界!</p>
//   `)
})

server.listen(port, hostname, () => {
    
    
  console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

处理页面中的静态资源

const http = require('http')
const fs = require('fs')

const hostname = '127.0.0.1'
const port = 3000

const server = http.createServer((req, res) => {
    
    
  const url = req.url
  if (url === '/') {
    
    
    fs.readFile('./index.html', (err, data) => {
    
    
      if (err) {
    
    
        throw err
      }
      res.statusCode = 200
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      res.end(data)
    })
  } else if (url === '/assets/css/main.css') {
    
    
    fs.readFile('./assets/css/main.css', (err, data) => {
    
    
      if (err) {
    
    
        throw err
      }
      res.statusCode = 200
      res.setHeader('Content-Type', 'text/css; charset=utf-8')
      res.end(data)
    })
  } else if (url === '/assets/js/main.js') {
    
    
    fs.readFile('./assets/js/main.js', (err, data) => {
    
    
      if (err) {
    
    
        throw err
      }
      res.statusCode = 200
      res.setHeader('Content-Type', 'text/javascript; charset=utf-8')
      res.end(data)
    })
  } else {
    
    
    res.statusCode = 404
    res.setHeader('Content-Type', 'text/plain; charset=utf-8')
    res.end('404 Not Found.')
  }
})

server.listen(port, hostname, () => {
    
    
  console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

统一处理页面中的静态资源

const http = require('http')
const fs = require('fs')
const mime = require('mime')
const path = require('path')

const hostname = '127.0.0.1'
const port = 3000

const server = http.createServer((req, res) => {
    
    
  const url = req.url
  if (url === '/') {
    
    
    fs.readFile('./index.html', (err, data) => {
    
    
      if (err) {
    
    
        throw err
      }
      res.statusCode = 200
      res.setHeader('Content-Type', 'text/html; charset=utf-8')
      res.end(data)
    })
  } else if (url.startsWith('/assets/')) {
    
    
    // /assets/js/main.js
    fs.readFile(`.${
      
      url}`, (err, data) => {
    
    
      if (err) {
    
    
        res.statusCode = 404
        res.setHeader('Content-Type', 'text/plain; charset=utf-8')
        res.end('404 Not Found.')
      }
      const contentType = mime.getType(path.extname(url))
      res.statusCode = 200
      res.setHeader('Content-Type', contentType)
      res.end(data)
    })
  } else {
    
    
    res.statusCode = 404
    res.setHeader('Content-Type', 'text/plain; charset=utf-8')
    res.end('404 Not Found.')
  }
})

server.listen(port, hostname, () => {
    
    
  console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

使用模板引擎处理动态页面

假如我们有一份数据 todos 需要展示到页面中

const todos = [
  {
    
     title: '吃饭', completed: false },
  {
    
     title: '睡觉', completed: true },
  {
    
     title: '打豆豆', completed: false }  
]

如何将一组数据列表展示到一个页面中,最简单的方式就是字符串替换,但是如果有不止一份数据需要展示到页面中的时候就会变得非常麻烦,所以前人将此种方式整合规则之后开发了我们常见的模板引擎。

例如我们经常在网页源码中看到下面这样一段代码

<ul>
  <% todos.forEach(function (item) { %>
  <li><%= item.title %></li>
  <% }) %>
</ul>

或者是

<ul>
  {
   
   { each todos }}
  <li>{
   
   { $value.title }}</li>
  {
   
   { /each }}
</ul>

无论如何,我们看到的这些语法都在模板引擎所指定的一些规则,目的就是让我们可以非常方便的在网页中进行字符串替换以达到动态网页的效果。

在 Node 中,有很多优秀的模板引擎,它们大抵相同,但都各有特点

基本使用

const template = require('art-template')

// const ret = template.render('Hello {
    
    { message }}', {
    
    
//   message: 'World'
// })

const ret = template.render(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
  <h1>Hello {
     
     { message }}</h1>
  <ul>
    {
     
     { each todos }}
    <li>{
     
     { $value.title }} <input type="checkbox" {
     
     { $value.completed ? 'checked' : '' }} /></li>
    {
     
     { /each }}
  </ul>
</body>
</html>
`, {
    
    
  message: 'World',
  todos: [
    {
    
     title: '吃饭', completed: false },
    {
    
     title: '睡觉', completed: true },
    {
    
     title: '打豆豆', completed: false }
  ]
})

console.log(ret)

结合 http 服务渲染页面

const http = require('http')
const template = require('art-template')
const fs = require('fs')

const hostname = '127.0.0.1'
const port = 3000

const server = http.createServer((req, res) => {
    
    
  const url = req.url
  if (url === '/') {
    
    
    fs.readFile('./index2.html', (err, data) => {
    
    
      if (err) {
    
    
        throw err
      }
      const htmlStr = template.render(data.toString(), {
    
    
        message: '黑马程序员',
        todos: [
          {
    
     title: '吃饭', completed: true },
          {
    
     title: '睡觉', completed: true },
          {
    
     title: '打豆豆', completed: false }
        ]
      })
      res.statusCode = 200
      res.setHeader('Content-Type', 'text/html')
      res.end(htmlStr)
    })
  }
})

server.listen(port, hostname, () => {
    
    
  console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

实现一个静态文件服务器

使用数据库中的数据

实现一个留言本案例

第三方 HTTP 服务框架

更多优秀的第三方资源 awesome node.js

第5章 构建 HTTPS 服务

占位

猜你喜欢

转载自blog.csdn.net/weixin_44867717/article/details/131255575