搭建 http server

下面是一个 http server 的示例:

const http = require('http')
process.env.PORT = 3000
const port = process.env.PORT

const server = http.createServer((req, res) => {
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/html')
    res.end('<h1>hello world</h1>')
})
server.listen(port, () => console.log(`server running at port ${port}`))

访问 http://localhost:3000 就会看到页面显示 hello world

下面我们简单解释下以上示例的执行过程:

  • 首先引入 http module
  • 设置环境变量 PORT 为 3000,然后赋值给 port 变量
  • 创建一个 server,其中含有一个 callback function,用户访问 server 时会被调用
  • 设置监听端口并启动 server,当 server 启动成功后,会执行 server.listen 内定义的 callback function

当 server 收到用户的请求时,会触发 request event 并提供了两个数据:一个 request(http.IncomingMessage object) 和一个 response(http.ServerResponse object)。

  • request 提供了 request 的详细信息,可以用来获取请求 hreaders 和请求数据。
  • response 用来操作将要发送给客户端的数据。

在上面的示例中,我们修改了 response 相关信息:

  • 设置 statusCode 为 200
  • 设置一个 header
  • 结束 response 并将响应内容作为数据传入 end()

发起 GET 请求

下面示例发起一个 GET 请求:

const https = require('https')
const options = {
    hostname: 'niekun.net',
    port: 443,
    path: '/',
    method: 'GET'
}

const req = https.request(options, res => {
    console.log(`statusCode is:${res.statusCode}`);
    res.on('data', d => {
        process.stdout.write(d)
    })
})

req.on('error', err => console.log(err))
req.end()

以上示例执行过程为:

  • 首先引入 https 模块。
  • 创建一个 options object 存储请求的信息。
  • 创建一个 https request,使用 options 作为请求信息,当请求成功后会执行后面定义的 callback function。
  • 定义一个 event handler 事件管理器来处理当 error 被触发时的响应。
  • 最后结束这个 request

发起 POST 请求

下面是一个 POST 请求示例:

const https = require('https')

const data = JSON.stringify({
    todo: 'go to sleep'
})

const options = {
    hostname: 'niekun.net',
    port: 443,
    path: '/',
    method: 'POST',
    Headers: {
        'Content-Type': 'application/json',
        'Content-Length': data.length
    }
}

const req = https.request(options, res => {
    console.log(`statusCode is:${res.statusCode}`);
    res.on('data', d => {
        process.stdout.write(d)
    })
})
req.on('error', err => console.log(err))

req.write(data)
req.end()

POST 请求相比 GET 请求多了 request.write(data) 部分,因为 POST 是把数据消息放在 body 中的。

PUT 和 DELETE 请求和 POST 格式相同,只需要修改 request.method 即可。

使用 Axios 库发起 POST 请求

上面介绍了是应用 https 模块来发起 POST 请求,我们也可以使用第三方库使代码更加简洁,这里介绍 axios 库实现(需要通过 npm 安装):

const axios = require('axios')

axios
.post('http://localhost:3000', {
    todo: 'go to sleep'
})
.then(res => {
    console.log(`statusCode is: ${res.status}`)
    process.stdout.write(res.data)
})
.catch(err => console.log(err))

获取 http request body 数据

下面介绍 server 端如何提取在 http request body 中的 json 数据。

如果你使用 Express 模块创建 http server,那么只需要使用它的 body-parser 内容拆分模块即可实现提取 json 数据,Express 模块在第一章做过示例,如果客户端使用上面的 axios 示例发起请求,服务端代码如下:

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

process.env.PORT = 3000
const port = process.env.PORT

app.use(
    express.urlencoded({
        extended: true
    })
)
app.use(express.json())

app.get('/', (req, res) => {
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/html')
    res.end('<h1>hello world</h1>')
})

app.post('/', (req, res) => {
  console.log(req.body.todo)
  res.statusCode = 200
  res.setHeader('Content-Type', 'text/html')
  res.end('hello world\n')
});

const server = app.listen(port, () => console.log('Server ready'));

我们使用 express 模块创建了一个 server,并同时监听 GET 和 POST 请求并定义了 callback 响应,通过 app.use 设置了对请求 body 数据的 json 支持。

当启动上面实例中使用 axios 开启的服务端的程序后,server 端收到 POST 请求后就会提取请求 body 中的 todo 对应内容并输出到终端。客户端成功收到 response 后会输出 200 状态码和响应内容。

我们通过浏览器直接访问 localhost:3000 会发起一个 GET 请求,浏览器会显示 hello world。

如果你不想使用 express 模块创建 server,那么 server 端要提取 POST request body 中的 json 数据就稍微麻烦一些。

首先需要理解的是当我们通过 http.createServer() 创建了一个 http 服务后,callback function 会在所有的 request headers 内容都接收到后被调用,而不是 request body。

connection callback 中传递的完整的 request object 数据是在 stream 流中。所以我们必须监听传输的 request body 的内容,它们是在一些 chunks 数据块中的。

首先我们通过监听 data event 获取 body 数据,data event 在传输过程中会被多次触发,当 request 数据传输完毕后 end event 会被触发。

通过下面的代码可以获取到完整的 body 数据:

const server = http.createServer((req, res) => {
    let data = '';
    req.on('data', chunk => {
        data += chunk;
    })
    req.on('end', () => {
        console.log(JSON.parse(data).todo)
    })
})

以上代码中,data 最终存储了 request body 的数据,然后通过 JSON.parse method 可以解析 json 内容。

server 端完整的代码如下:

const http = require('http')
process.env.PORT = 3000
const port = process.env.PORT

const server = http.createServer((req, res) => {
    let data = '';
    req.on('data', chunk => {
        data += chunk;
    })
    req.on('end', () => {
        console.log(JSON.parse(data).todo)
    })

    res.statusCode = 200
    res.setHeader('Content-Type', 'text/html')
    res.end('<h1>hello world</h1>')
})
server.listen(port, () => console.log(`server running at port ${port}`))

以上就是 http request 和 response 部分的简单介绍。

标签: none

添加新评论