koa基础

作者: noyanse | 来源:发表于2020-07-28 16:15 被阅读0次

    错误处理

    koa 对于找不到的会自动返回404错误
    可以用ctx.throw(412) 跑出错误码

    编写错误处理中间件

    把错误处理的中间件放在中间件链条的最前面

    app.use(async (ctx, next) => {
        try {
            await next()
        } catch (err) {
            // 运行时错误,都返回500
            ctx.status = err.status || status.statusCode || 500
            // ctx.body = err.message // 最好返回json形式
            ctx.body = {
                message: err.message
            }
        }
    })
    

    koa-json-error

    返回json信息的错误处理中间件

    跨平台 变量中间件 cross-env
    在package.json中设置 模拟生产环境
    "start": "cross-env NODE_ENV=production node app"

    koa -parameter 校验参数中间件

    const parameter = require('koa-parameter')
    
    app.use(parameter(app)) // ctx加一个全局的方法帮助我们校验参数
    
    ctx.verifyParams({
        name: { type: 'string', required: true } // required 默认为true 可不写
    })
    

    博客地址

    https://www.jianshu.com/u/84e78d51ad4e

    git clone https://github.com/r0oth3x49/udemy-dl.git

    cd udemy-dl

    pip install -r requirements.txt

    python udemy-dl.py 课程地址 -o "存放目录" -q 720 -c 章节编号 -l 章节中课程编号

    python udemy-dl.py https://www.udemy.com/ios11-app-development-bootcamp/learn/v4/t/lecture/7626360 -o /Users/chang/Desktop/sketch -q 720 -c 35 -l 8

    下载 https://www.udemy.com/ios11-app-development-bootcamp/learn/v4/t/lecture/7626360 课程的第 35 章节的第 8 课到本地目录 /Users/chang/Desktop/sketch 下。视频清晰度为 720。
    如果想下载 1080 视频,把 720 改成 1080 即可

    python udemy-dl.py https://www.udemy.com/complete-python-bootcamp/learn/lecture/3421822 -o F:\udemy\learn-python -q 720 -c 1 -l 1

    =======

    云数据库---mongodb Atlas

    1. 注册用户
    2. 创建集群
    3. 添加数据库用户
    4. 设置IP地址白名单
    5. 获取连接地址

    实操步骤

    • www.mongodb.com -- products -- cloud -- mongodb Atlas (https://www.mongodb.com/cloud/atlas)
    • 按照get stated 做就好 aws - 选新加坡地址 - 默认存储 - 按照mongodb4.0 - 集群名称要自定义一下,一旦创建就不能修改
    • 创建第一个集群是免费的,如果再创建第二个集群就要收费了
    • 创建数据库
    • 创建用户
    • 添加IP地址,选择可以从任何地方访问

    连接数据库

    const mongoose = require('mongoose')
    mongoose.connect(dbUrl, { useNewUrlParser: true }, () => {
        console.log('数据库连接成功')
    })
    mongoose.connection.on('error', () => {
        console.log('数据库连接失败')
    })
    

    设计用户模块的 Schema (json的数据结构)

    1. 分析用户模块的属性
    2. 编写用户模块的 Schema
    3. 使用Schema 生成用户 Model (MVC中的 Model,通常用于一些数据库的操作)
    Schema 应该放在 models文件夹下
    + models
    const mongoose = require('mongoose')
    const { Schema, model } = mongoose // 可以用这个生成文档 Schema
    // 可以设计出非常复杂的嵌套结构
    const userSchema = new Schema({
        name: {type: String, required: true},
        age: {type: Number, default: 0}
    })
    
    module.exports = model('User', userSchema) // model 可以来操作数据
    

    用Mongoose类库实现增删改查接口

    • User.find()
    • User.findById(id)
    • new User(ctx.request.body).save()
    • User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
    • User.findByIdAndRemove(ctx.params.id)
    • User.findOne(ctx.params.id)
    const User = require('../models/users')
    async find(ctx) {
        ctx.body = await User.find()
    }
    

    认证与授权

    session

    1. 客户端发起请求,携带用户名和密码,服务端接到请求后,生成session数据,保存在内存或者数据库(如redis)中,并把sessionId 返回给前端。

    2. 前端拿到sessinId后存在cookie中,set-cookie 不止有sessionId还有domain

    3. 客户端在发起请求,验证session

    前端想重新登录,清除缓存即可,后端想重新登录清楚session即可

    优点:
    1. 相比JWT可主动清除cookie
    2. session 保存在服务端,相对安全
    3. 结合cookie使用,灵活,兼容性好
    缺点:
    1. cookie + session 跨域场景表现不好
    2. 如果分布式部署,要做多机共享机制
    3. 查询session信息可能有数据库操作

    JWT

    1. JSON Web Token 是一个开放的标准(RFC 7519)
    1. 紧密且独立,作为JSON对象传输
    2. 该信息可验证和信任,经过数字签名
    JWT构成
    1. 头部(Header)
      • typ: token类型,定义为 JWT
      • alg: 使用hash算法,如 HMAC SHA256 RSA
      • 最后用 base64Url 编码了一下
    2. 有效载荷(Payload)
      • 存储要传递的信息,如用户id, 用户名等
      • 还包含元数据,如过期时间, 发布人等
      • 与header不同,可加密
    3. 签名(Signature)
      • Header 和 Payload 部分进行签名
      • 保证token在传输过程中没有被篡改或损坏
    JWT特点
    1. 通过令牌校验 无状态
    2. RESTful API
    3. JWT 性能不好,包含HTTP中完整的信息
    4. 时效性, JWT只能在过期后清除,不能主动销毁, 不如 session
    const jwt = require('jsonwebtoken')
    const token = jwt.sign({ name: 'lulu', secret }) // 生成签名
    jwt.verify(token) // 经过校验的解码
    

    JWT最主要就是解决跨域问题,存储在客户端,服务端无状态的

    上传图片

    • 用户头像
    • 封面图片
    • 问题和回答中的图片(支持富文本,图片可以通过按钮或者复制粘贴来上传)
    • 话题图片

    上传图片的功能点

    • 基础功能: 上传图片,生成图片链接
    • 附加功能:限制上传图片的大小和类型(加快图片加载)---通常在前端做
      生成图片高中低3中分辨率的图片链接、生成CDN(更好的传输速度)

    上传图片的技术方案

    • 阿里云 OSS 等云服务,推荐在生产环境使用
    • 直接上传到自己的服务器,不推荐在生产环境下使用(不稳定,不支持分布式环境,适合学习)

    使用 koa-body 中间件获取上传的文件

    • 安装 koa-body 替换 koa-bodyparser(koa-bodyparser只支持json和form两种格式的请求体,不支持文件的格式)
    • 设置图片上传目录(在注册koa-body中间件时注册的)
    • 使用Postman模拟上传文件
    npm install koa-body --save
    npm uninstall koa-bodyparser --save // 卸载koa-bodyparser
    
    const kodBody = require('koa-body')
    
    app.use(kodBody({
        multipart: true, // 启用文件,支持文件的格式
        formidable: {
            uploadDir: path.join(__dirname, '/public/uploads'),
            // 保留拓展名, 默认是 false
            keepExtensions: true
        }
    }))
    
    + controllers:
    class HomeCtl {
        index(ctx) {
            ctx.body = '这是主页'
        }
        upload(ctx) {
            // 获取上传文件
            const file = ctx.request.files.myfile
            ctx.body = { path: file.path }
        }
    }
    + routes
        + home.js:
    const { index, upload } = require('../controllers/home')
    
    const router = new Router()
    
    router.post('/upload', upload)
    
    
    • postman 里面新建一个 request, 路径为设置的路由,body中选择form-data格式
      key 选择file 格式

    PS:有点心累,本来这么写的,运行 ctx.request.files就是 undefined
    后来可能改了下中间件的位置,就Ok了,我再改回来,还是ok,简直是迷

    使用 koa-static 中间件 生成图片链接

    可以帮我们生成静态服务,指定了一个文件夹,文件夹下所有的文件都可以通过http服务来访问
    public 作为静态服务器

    1. 安装 koa-static
    2. 设置静态文件目录(通常设置在public文件夹下)
    3. 生成图片链接, 想办法让这个链接在上传接口中返回给客户端
    app.use(koaStatic(path.join(__dirname, 'public')))
    

    // 图片链接
    http://localhost:3000/uploads/upload_05fda00006b536a730d45455dee4d505.png

    const basename = path.basename(file.path) // basename 接收一个绝对路径,并返回basename
    // ctx.origin 就是 localhost:3000
    ctx.body = { path: `${ctx.origin}/uploads/${basename}` }
    

    public下的所有文件都可以通过http来访问,比如如果想放一个Html前端静态页面,放public下也可以通过http访问

    编写前端页面上传文件

    • 核心就是表单
    • 联调测试
    <form action="/upload" enctype="multipart/form-data" method="POST">
        <input type="file" name='file'>
        <button type="submit">上传</button>
    </form>
    

    限制上传格式

    <input type="file" name='file' accept='image/png, image/jpeg'> 或者
    accept='.png, .jpg, .jpeg'
    支持所有图片类型文件
    accept='image/*'
    

    个人资料需求分析

    • 不同类型的属性
    • 字段过滤

    个人资料的 Schema 设计 (这里指的是json的数据结构)

    • 分析个人资料的数据结构
      头像存的是url, 在上传图片的时候,存在服务器上,生成url
    avatar_url: { type: String }
    // 性别:男或女,可枚举字符串 enum 可根据性别给你推荐适合你的产品
    gender: { type: String, enum: ['male', 'female'], defaule: 'male', required: true }
    headline: { type: String },
    locations: { type: [{ type: String }] }, // 字符串数组
    business: { type: String }, // 行业
    employments: { // 职业经历
        type: [{
            company: { type: String },
            job: { type: String }
        }]
    },
    educations: {
        type: [{
            school: { type: String },
            major: { type: String },
            diploma: { type: Number }, // 用数字表示学历       
            entrance_year: { type: Number },
            graduation_year: { type: Number }
        }]
    }
    

    个人资料的参数校验

    • 请求体的校验
    • 分析个人资料的数据结构
    • 编写代码校验个人资料参数
      通常注册的时候,只填写用户名密码就好,
      校验参数的代码写在更新个人资料的接口中

    字段过滤

    • 设置 Schema 默认隐藏字段, 用户列表里面,不能显示太多字段
    • 通过查询字符串显示隐藏字段
      select: false // 设置 Schema 时隐藏字段
    const { fields } = ctx.query
    console.log('find by id', fields)
    // 把 f 不存在的字段过滤掉
    const selectFields = fields.split(';').filter(f => f).map(item => ' +' + item).join('')
    // 把隐藏的字段通过query查询显示出来
    const user = await User.findById(ctx.params.id).select(selectFields) // +employments +educations
    

    相关文章

      网友评论

          本文标题:koa基础

          本文链接:https://www.haomeiwen.com/subject/oxofrktx.html