koa简单使用

一. RESTful(Representational State Transfer)风格API:

1. 客服服务端(Client-Server)

关注点分离,服务端专注数据存储,提升了简单性,前端专注用户界面,提升了可移植性

2. 无状态(Stateless)

每次请求必须包括所有信息,不能依赖上下文信息,客户端保留所有会话信息,服务端不再保留会话信息

3. 缓存(Cache)

所有信息必须标记为可缓存或不可缓存

4. 统一接口(Uniform Interface)

接口设计尽可能统一,接口与实现解耦

5. 分层系统(Layered System)

每一层只知道相邻的一层,每一层负责不同的功能安全,负载均衡

6. 按需代码

RESTful风格最佳例子:https://developer.github.com/v3/

二.koa基础使用

1.自定义路由

koa所需工具:nodemon自动重启
记得取package.json里写脚本:"start":"nodemon index.js",
断点调试和查看官网的api:ctx.url ctx.status ctx.method ctx.body

const Koa = require("koa")
const app = new Koa()

app.use(async (ctx) => {
    if (ctx.url === '/') {
        //处理不同的url
        ctx.body = "这是主页 "
    } else if (ctx.url === "/user") {
        //处理不同的方法
        if (ctx.method === "GET") {
            ctx.body = "这是用户列表页"
        } else if (ctx.method === "POST") {
            ctx.body = "创建用户"
        } else {
            //方法不允许
            ctx.status = 405
        }

    } else if (ctx.url.match(/\/user\/\w+/)) {
        // 解析请求参数
        const userId = ctx.url.match(/\/user\/(\w+)/)[1]
        ctx.body = `这是用户${userId}`
    } else {
        ctx.status = 404
    }
})
app.listen(3000)
2.使用koa-router,不用自定义路由

koa-router实现路由

获取HTTP请求参数:

  1. 获取query(ctx.query). ?q=keyword
  2. 获取body(koa-bodyparser||koa-body)
  3. 获取header(ctx.header). Accept,Cookie
  4. 获取router params(ctx.params). /users/:id

发送HTTP响应:

  1. 发送status(ctx.status)
  2. 发送body(ctx.body)
  3. 发送header(ctx.set("Allow","get","post"))Allow Content-type
  4. 实现用户的增删改查(get获取用户,post新建返回新建用户,put全部更新,patch局部更新,delete删除返回204,options显示支持什么访问方法)
    常用状态码:
    204:删除用户后返回,表示成功状态响应代码指示请求已成功,但没有内容返回
    200:响应成功,内容返回
    500:运行时错误
    404:找不到
    412:先决条件失败
    422:无法处理的实体,参数格式不对
const Koa = require("koa")
const Router = require("koa-router")
const app = new Koa()
const router = new Router()
//前缀
const userRouter = new Router({ prefix: "/user" })
const koaBody = require("koa-body")
const parser = require("koa-bodyparser")
//多中间件  
const auth = async (ctx, next) => {
    // if(ctx.url !== "/user"){
    //     //没有权限  
    //     ctx.throw(401)
    // }
    await next( )
}

router.get("/", (ctx) => {
    ctx.body = "这是主页"
})
//处理不同的url
userRouter.get('/', auth, (ctx) => {
    ctx.body = "这是用户列表"
})
//处理不同的方法 post新建用户 返回新建的用户
userRouter.post("/", auth, (ctx) => {
    ctx.body = "创建用户"
})
//解析请求参数 get查列表 返回列表
userRouter.get("/:id", auth, (ctx) => {
    //设置header响应头
    ctx.set("Allow","GET,POST")
    ctx.body = `这是用户${ctx.params.id}列表 `
})
//put修改 返回修改的用户
userRouter.put("/:id", (ctx) => {
    ctx.body = `这是用户${ctx.params.id}`
})
//delete删除 返回实体,但是成功
userRouter.delete("/:id", (ctx) => {
    ctx.status = 204
})

//注册中间件
app.use(parser( ))
app.use(router.routes())
app.use(userRouter.routes())
//响应options方法请求,告诉他所支持的请求方法
//405方法不允许,支持但没写。501方法无法实现,不存在 
app.use(userRouter.allowedMethods())

app.listen(3000)
//http请求参数:
//Query String  如?q=keyword(可选)
//Router Params 如/user/:id(必传)
//Body,如json,form等conten-type里面会写到
//Header,如accept,cookie,jwt等
  
//发送http响应:
//发送status。如200/400等
//发送body,如json等
//发送header,如allow,content-type等 
//1.每个资源的控制器尽量发在不同的文件里
//2.尽量使用类+类的形式编写控制器
//3.严谨的错误处理
3.错误处理和更加合理的目录结构

错误处理:
ctx.throw(422,'文本信息')
koa-json-error:记得隐藏堆栈信息,在生产环境的时候
koa-parameter:校验参数ctx.verifyParams({name:{type:"string",required:true}})

const Koa = require("koa")
const bodyParser = require("koa-bodyparser")
const app = new Koa()
const routing = require("./routes")
const error = require("koa-json-error")
const parameter = require('koa-parameter')//校验参数

//自定义的错误处理,无法捕获404信息
// app.use(async (ctx, next) => {
//     try {
//         await next()
//     } catch (error) {
//         //断点
//         ctx.status = error.status || error.statusCode || 500
//         //返回json格式
//         ctx.body = {
//             message: error.message
//         }
//     }
// })
app.use(error({
    //定制返回格式
    postFormat: (e, { stack, ...rest }) => {//原生的error,应该返回的格式
        // "start": "export NODE_ENV='production'&& nodemon app",
        return process.env.NODE_ENV === "production" ? rest : { stack, ...rest }
    }
}))//koa-json-error中间价处理错误,404,412,500
app.use(bodyParser())//解析请求体
app.use(parameter(app))//校验参数,传入app,进行全局的使用,全局方法,比如在create方法中
routing(app)
app.listen(3000, () => { console.log("程序在3000端口启动了") })
//异常状况有哪些
//1.运行是错误,服务器内部的错误500
//2.逻辑错误,找不到404,先决条件失败412,无法处理的实体(参数格式不对422)
// 为什么要使用错误处理
//1.防止程序挂掉
//2.告诉用户信息
//3.便于开发者调试
目录结构
4.链接数据库的操作

到这里为止的仓库地址:https://github.com/ranzhouhang/2020-9-12practice

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容