Node.js 核心模块http

下面我们将学习 Node.js 的 http 模块,通过它来实现以下功能:

  1. 创建一个 HTTP 服务器
  2. 服务器接收请求并进行处理
  3. 响应并返回处理结果

get请求

新建 server.js 文件:

// 1.导入模块
const http = require('http')

// 2.创建服务器 获取服务器的实例对象
let server = http.createServer()
server.listen(3000, () => {
    console.log('http://127.0.0.1:3000')
})

// 3.接收响应
server.on('request', (req, res) => {
    // 4.处理响应
    res.write('888')
    //5.断开连接
    res.end()
})

然后在终端运行:

node server.js

控制台将输出 http://127.0.0.1:3000

在浏览器中访问,会得到我们写入的 888

在 Node.js 开发中,每次修改代码后都需要重启服务才能看到新的输出。为了解决这个问题,我们可以使用 nodemon 工具,它可以自动检测文件的变化并更新服务。安装步骤如下:

sudo npm i -g nodemon

安装完成后,通过下面命令启动项目:

nodemon server.js

当我们尝试输出中文时,可能会发现浏览器内显示的是乱码。这是因为我们没有告诉浏览器如何解析这段文本,因此我们需要设置一下响应头:

server.on('request', (req, res) => {
    res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); // 设置响应头
    res.write('你好')
    res.end()
})

通过修改响应头,我们就可以输出对应的内容。

常见请求方式

以下是 Node.js 中常见的请求方法及其说明:

方法 说明
GET 用于向指定的资源请求数据。
POST 用于向指定的资源提交要被处理的数据。
PUT 用于向指定的资源位置上传其最新内容。
DELETE 删除指定的资源。
HEAD 类似于 GET 请求,但只返回 HTTP 报头,不返回实体主体。
OPTIONS 用于获取目标资源所支持的通信选项。
PATCH 对资源进行部分修改。

这些方法在 HTTP 协议中定义,Node.js 提供了对这些方法的支持,可以通过构建 HTTP 请求来使用它们。例如,可以使用 httphttps 模块创建一个服务器,然后根据接收到的请求的方法来执行相应的处理。

接下来,我们将发起一个带有参数的 GET 请求:

server.js 中:

const http = require('http')
const url = require('url') // 解析携带的参数

let server = http.createServer()
server.listen(3000, () => {
    console.log('http://127.0.0.1:3000')
})

// 接收响应
server.on('request', (req, res) => {
    if (req.method === 'GET') {
        let { query } = url.parse(req.url, true)
        res.write('GET 请求,参数为:' + query.id)
        res.end()
    }
})

在浏览器中访问:

http://127.0.0.1:3000/user?id=123

将会返回:

GET 请求,参数为:123

这个例子演示了如何使用 Node.js 发起带参数的 GET 请求。

处理 POST 请求

server.js 中:

const http = require('http')
const url = require('url')

let server = http.createServer()
server.listen(3000, () => {
    console.log('http:127.0.0.1:3000')
})

server.on('request', (req, res) => {
    res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); // 设置响应头
    if (req.method === 'GET') {
        let { query } = url.parse(req.url, true)
        res.write('get请求,参数为:' + query.id)
        res.end()
    } else if (req.method === 'POST') {
        let postData = ''
        req.on('data', chunk => {
            postData += chunk
        })
        req.on('end', () => {
            res.write('POST 请求, 参数为: ' + postData)
            res.end();
        })
    }
})

在处理 POST 请求时,我们通过监听 data 事件和 end 事件来获取请求的数据。在 data 事件中,我们将每个数据块(chunk)累加到 postData 中,最终在 end 事件中处理完整的请求数据。

代码拆分

以上示例演示了如何处理不同请求方法的逻辑,但在实际开发中,我们会进一步将代码拆分以保持结构清晰。

我们可以创建一个 router.js 文件来处理路由,以及一个 controller.js 文件来处理具体的业务逻辑。

  • router.js
const fs = require('fs')
const controller = require('./controller')

module.exports = (req, res) => {
    res.setHeader('Content-Type', 'text/plain;charset=UTF-8'); // 设置响应头
    if (req.method === 'GET') {
        if (req.url == '/') {
            controller.index(res)
        }

    } else if (req.method === 'POST') {
        let postData = ''
        req.on('data', chunk => {
            postData += chunk
        })
        req.on('end', () => {
            controller.user(require('querystring').parse(postData), res)
        })
    }
} 
  • controller.js
const url = require('url')

module.exports = {
    index(req, res) {
        let { query } = url.parse(req.url, true)
        res.write('get请求')
        res.end()
    },

    user(data, res) {
        console.log(data)
        res.end()
    }
}

通过将不同的逻辑模块拆分到 controller.js 中,我们可以更清晰地组织代码。这样在实际的开发中,也能更方便地维护和扩展应用程序。