当前位置:网站首页 > Node.js开发 > 正文

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 中,有很多优秀的模板引擎,它们大抵相同,但都各有特点

  • marko
  • nunjucks
  • handlebars.js
  • EJS
  • Pug
  • art-template

基本使用

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 服务框架

  • Express
  • Koa
  • ThinkJS
  • Egg
  • AdonisJs

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

第5章 构建 HTTPS 服务

占位

到此这篇Node.js网络通信(三)——构建http服务之创建http服务、根据url处理响应、响应html内容、处理页面中的静态资源、使用模版引擎& 构建https服务之原理、CA证书、搭建https服务器的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • nodejs事件循环与多进程(一)——事件循环允许Node.js执行非阻塞IO操作 & js是操作DOM,决定了单线程 & 事件循环之宏任务setTimeout在后、微任务promise在前2024-12-02 15:18:05
  • nodejs事件循环与多进程(二)——fs和setTimeout、setImmediate关系&事件循环是异步操作&process.nextTick阻塞IO操作&app.on订阅、app.emit触发2024-12-02 15:18:05
  • nodejs事件循环与多进程(四)——Process进程-Node全局对象&child_process子进程-exec、execSync、execFile、spawn、fork & Cluster集群2024-12-02 15:18:05
  • nodejs事件循环与多进程(五)——cluster多进程模型 & worker进程使用fork()函数,实现与master进程间通信 & 惊群之发生多线程多进程等待同一个socket事件2024-12-02 15:18:05
  • nodejs事件循环与多进程(六)——Nginx是HTTP和反向代理服务器& 正向代理-不知客户端需代理、反向代理-不知服务器需代理& cluster中的优雅退出和进程守护& IPC通信是进程间的通信2024-12-02 15:18:05
  • Node.js 网络通信(二)02-构建UDP服务——UDP简介 & UDP三种传播方式-单播、广播、组播 & UDP一对多通信场景 & dgram模块用于构建UDP服务之Socket方法和事件2024-12-02 15:18:05
  • Node.js 网络通信(二)01-构建TCP服务——TCP全名为传输控制协议,属于传输层协议,如http协议 & 显著特征是在传输之前需要三次握手形成会话 & Socket通信模型2024-12-02 15:18:05
  • Node.js 网络通信(一)——网络通信相关概念、网络七层模型、mac 地址之ip地址、Port 端口号、域名 & TCP-传输控制协议、UDP-用户数据报协议、Socket套接字2024-12-02 15:18:05
  • Node学习(九)07-使用验证码——必须登录才能访问页面 & 模糊搜索的时候重置分页页码2024-12-02 15:18:05
  • Node学习(九)065-会话技术简介之cookie和session的优缺点——cookie-优点是节省服务器空间,缺点不安全 & session-优点是安全,缺点需要服务器空间 & 语法之设置和获取2024-12-02 15:18:05
  • 全屏图片