阅读 231

前端进阶 - node基本操作 - Koa快速搭建本地服务

使用node搭建本地http服务,Koa只是选择之一。上半年看了个新闻,express的占有率又处于上升。

安装

npm install koa
复制代码

快速上手

创建一个文件koa.js,贴入以下代码:

const Koa = require('koa')

const app = new Koa()

app.use((ctx) => {
    ctx.body = '<h1>Hello Koa</h1>'
    ctx.type = 'text/html'
})

const port = 3001

app.listen(port, () => {
    console.log(`Koa start at http://127.0.0.1:${port}`)
})
复制代码

然后运行该脚本

% node koa.js
Koa start at http://127.0.0.1:3001
复制代码

打开http://127.0.0.1:3001,即可看到Hello Koa的大黑字。

搭建本地 GET POST 测试服务器

基于上面的代码,做一下改造。出于简单和触及基础的考虑,这里我们不使用koa-router等其他中间件。

PS:后面课程对本篇有依赖

识别 GET | POST

const { url, method } = ctx.request
复制代码

这里的method,即http请求方法,url则是请求的绝对路径。

用method驱动响应逻辑

app.use((ctx) => {
    const { url, method } = ctx.request
    if(method === 'POST') {
        // 这里配置POST响应
    } else {
        ctx.body = `Hello Koa`
    }
    ctx.type = 'text/plain'
})
复制代码

读取ctx.req流

app.use使用中间件,会传入ctx上下文对象作为第一个参数;其中的ctx.req就是客户端写入的流。

按HTTP规范,GET并不会写请求流,POST会,也就是我们post的表单、上传文件等数据。

流的读取是异步,不过可以统一处理。我们先写一个流读取的方法,封装为Promise

const readStream = (stream) => new Promise((resolve, reject) => {
    const chunks = []
    stream.on('data', chunk => {
        chunks.push(chunk)
    })
    stream.on('end', () => {
        const buff = Buffer.concat(chunks)
        const data = buff.toString('utf-8')
        resolve(data)
    })
    stream.on('error', err => {
        reject(err)
    })
})
复制代码

一般来讲,使用data end error 这3个生命周期基本够用。

由于读取是按block来读取,所以一个大文件或者数据,会有多次data生命周期触发。由此可以发散联想:http基于ip/tcp协议,是按序发送数据包,所以chunks缓存区使用数组结构,有序推入、合成即可。

合成服务

最终代码

const Koa = require('koa')

const port = 3001

const app = new Koa()
const readStream = (stream) => new Promise((resolve, reject) => {
    const chunks = []
    stream.on('data', chunk => {
        chunks.push(chunk)
    })
    stream.on('end', () => {
        const buff = Buffer.concat(chunks)
        const data = buff.toString('utf-8')
        resolve(data)
    })
    stream.on('error', err => {
        reject(err)
    })
})
app.use(async (ctx) => {
    const { url, method } = ctx.request
    if(method === 'POST') {
        try {
            const data = await readStream(ctx.req)
            console.log(`[${method}]`, data)
            ctx.body = data
        } catch(err) {
            ctx.status = 500
            ctx.body = err
        }

    } else {
        ctx.body = `${decodeURIComponent(url)}`
        console.log(`[${method}]`, url)
    }
    ctx.type = 'text/plain'
})

app.listen(port, () => {
    console.log(`Koa start at http://127.0.0.1:${port}`)
})
复制代码

单元测试

安装jestaxios

npm i -D jest axios
复制代码

创建koa.test.js文件

const axios = require('axios')

describe('Koa service get', () => {
    it(`get /123`, done => {
        axios.get(`http://127.0.0.1:3001/123`).then(({ data }) => {
            expect(data).toEqual('/123')
            done()
        })
    })
})

describe('Koa service get', () => {
    it(`get /?123`, done => {
        axios.get(`http://127.0.0.1:3001/?123`).then(({ data }) => {
            expect(data).toEqual('/?123')
            done()
        })
    })
})

describe('Koa service get', () => {
    it(`get /中文`, done => {
        axios.get(`http://127.0.0.1:3001/${encodeURIComponent('中文')}`).then(({ data }) => {
            expect(data).toEqual('/中文')
            done()
        })
    })
})

describe('Koa service get', () => {
    it(`get /?中文`, done => {
        axios.get(`http://127.0.0.1:3001/?${encodeURIComponent('中文')}`).then(({ data }) => {
            expect(data).toEqual('/?中文')
            done()
        })
    })
})


describe('Koa service post', () => {
    it(`post '中文'`, done => {
        axios.post(`http://127.0.0.1:3001/`, '中文').then(({ data }) => {
            expect(data).toEqual('中文')
            done()
        })
    })
})

describe('Koa service post', () => {
    it(`post 'AbC'`, done => {
        axios.post(`http://127.0.0.1:3001/`, 'AbC').then(({ data }) => {
            expect(data).toEqual('AbC')
            done()
        })
    })
})
复制代码

更改package.json

{
    "scripts": {
        "test": "jest"
    }
}
复制代码

运行单元测试

% npm test

> testnpm@1.0.0 test
> jest

 PASS  ./koa.test.js
  Koa service get
    ✓ get /123 (26 ms)
    ✓ get /?123 (2 ms)
    ✓ get /中文 (2 ms)
    ✓ get /?中文 (2 ms)
  Koa service post
    ✓ post '中文' (2 ms)
    ✓ post 'AbC' (2 ms)

Test Suites: 1 passed, 1 total
Tests:       6 passed, 6 total
Snapshots:   0 total
Time:        0.266 s, estimated 1 s
Ran all test suites.

复制代码

以上

文章分类
前端
文章标签