Quick start

  • Create a new koA2-Demo folder
  • Open this folder through WebStorm
  • Installation of koa
npm i koa
Copy the code
  • Create an app.js file
const Koa = require('koa')
const app = new Koa()

app.use( async ( ctx ) => {
    ctx.body = 'hello koa2'
})

app.listen(3000)
console.log('Started successfully')
Copy the code
  • Create another package.json
{
  "name": "koa2-demo"."version": "1.0.0"."description": "koa2 demo"."main": "app.js"."scripts": {
    "start": "node app.js"
  },
  "keywords": [
    "koa"."async"]."author": "zxq"."license": "MIT"."repository": {
    "type": "git"
   },
  "dependencies": {
    "koa": Tokens "2.13.1"}}Copy the code

run

node app.js
Copy the code
  • HTTP :localhost:3000 Click the page to view

routing

Native KOA implements routing

//app.js

const Koa = require('koa')
const fs = require('fs')
const app = new Koa()

// Promise encapsulates asynchronous file-reading methods
function render(page){
    return new Promise((resolve,reject) = >{
        let viewUrl = `./view/${page}`
        // Read the file
        fs.readFile(viewUrl,"binary".(err,data) = >{
            if(err){
                reject(err)
            }else{
                resolve(data)
            }
        })
    })
}

async function route(url){
    let view = '404.html'
    switch (url){
        case '/':
            view = "index.html"
            break
        case '/index':
            view = 'index.html'
            break
        case '/todo':
            view = 'todo.html'
            break
        case '/ 404':
            view = '404.html'
            break
        default:
            break
    }
    let html = await render(view)
    return html
}
//app.use() adds the given middleware method to the application, and app.use() returns this
app.use(async(ctx)=>{
    / / CTX is Context
    // ctx.request is a Node request
    
    // Obtain the routing information of the user
    let url = ctx.request.url
    // Write the fs file through the routing information
    let html = await route(url)
    ctx.body = html
    //ctx.body is the ctx.response.body
})
app.listen(3000.() = >{
    console.log('Started successfully')})// the app.listen() method is a syntactic sugar, the syntactic sugar of the following methods
const http = require('http')
http.createServer(app.callback()).listen(3000)
Copy the code
//index.html

<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>index</title>
</head>
<body>
<h1>koa2 demo index page</h1>
<p>this is a index page</p>
<ul>
    <li><a href="/">/</a></li>
    <li><a href="/index">/index</a></li>
    <li><a href="/todo">/todo</a></li>
    <li><a href="/ 404">/ 404</a></li>
    <li><a href="/nofund">/nofund</a></li>
</ul>
</body>
</html>
Copy the code
//404.html

<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>404</title>
</head>
<body>
<h1>koa2 demo 404 page</h1>
<p>this is a 404 page</p>
</body>
</html>
Copy the code
//todo.html

<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>todo</title>
</head>
<body>
<h1>koa2 demo todo page</h1>
<p>this is a todo page</p>
</body>
</html>
Copy the code

run

node -harmony app.js
Copy the code

http://localhost:3000/index click page views

Koa-router Specifies the routing middleware

The installation

npm install --save koa-router@7
Copy the code
//app.js

const Koa = require('koa')
const fs = require('fs')
const app = new Koa()

// Child route 1
const Router = require('koa-router')
let home = new Router()
home.get('/'.async(ctx)=>{
    let html = ` 
       `
    ctx.body = html
    // You can add additional attributes to CTX by editing app.context
})


// Child route 2
let page = new Router()
page.get('/ 404'.async(ctx)=>{
    ctx.body = '404 page! '
}).get('/helloworld'.async(ctx)=>{
    ctx.body = "helloworld page"
})

// Load all child routes
let router = new Router()
router.use('/',home.routes(),home.allowedMethods())
router.use('/page',page.routes(),page.allowedMethods())

// Load the routing middleware
app.use(router.routes()).use(router.allowedMethods())

app.listen(3000.() = >{
    console.log('Successful startup')})Copy the code

Data request

Get Data request

  • Request from context
  • Request from request in context

run

node app.js
Copy the code

http://localhost:3000/page/user?a=1&b=2Click to viewFormatted JSON data

A POST request

//app.js
const Koa = require('koa')
const app = new Koa()
app.use(async(ctx)=>{
    if(ctx.url === '/' && ctx.method === 'GET') {let html = ` 

koa2 request post demo

userName



nickName



email



`
ctx.body = html }else if(ctx.url === '/'&& ctx.method === 'POST') {let postData = await parsePostData(ctx) ctx.body = postData }else { ctx.body = '

404!!!

'
}})function parsePostData(ctx){ return new Promise((resolve,reject) = >{ try { let postdata = ""; ctx.req.addListener('data'.(data) = >{ postdata += data }) ctx.req.addListener("end".function(){ let parseData = parseQueryStr(postdata) resolve(parseData) }) } catch (err){ reject(err) } }) } function parseQueryStr(queryStr){ let queryData = {} let queryStrList = queryStr.split('&') console.log(queryStrList); for(let [index,queryStr] of queryStrList.entries()){ let itemList = queryStr.split('=') queryData[itemList[0]] = decodeURIComponent(itemList[1])}return queryData } app.listen(3000.() = >{ console.log('success')})Copy the code

Koa – bodyparser middleware

//app.js

const Koa = require('koa')
const app = new Koa()
const bodyParser = require('koa-bodyparser')

app.use(bodyParser())

app.use(async (ctx)=>{
    if(ctx.url === '/' && ctx.method === 'GET') {let html = ` 

koa2 request post demo

userName



nickName



email

`
ctx.body = html }else if(ctx.url === '/' && ctx.method === 'POST') {let postData = ctx.request.body ctx.body = postData }else { ctx.body = '

404!!!

'
} }) app.listen(3000.() = >{ console.log('success')})Copy the code

Static resource loading

Native Koa implements static resource servers

//index.js

const Koa = require('koa')
const path = require('path')
const content = require('./util/content')
const mimes = require('./util/mimes')

const app = new Koa()
// Static resource directory path
const staticPath = './static'

// Parse the resource type
function parseMime(url){
    //path.extname returns the extension of path
    let extName = path.extname(url)
    extName = extName ? extName.slice(1) :'unknown'
    return mimes[extName]
}
app.use(async(ctx)=>{
    // __dirname Directory name of the current module
    let fullStaticPath = path.join(__dirname,staticPath)

    // Get static resource content
    let _content = await content(ctx,fullStaticPath)
    // Parse the type of content
    let _mime = parseMime(ctx.url)
    // If there is a corresponding file type, configure the context type
    if(_mime){
        ctx.type = _mime
    }
    // If the output static resource is a picture,
    if(_mime && _mime.indexOf('image/') > =0) {// Set the response header
        ctx.res.writeHead(200)
        // Output the static resource content as binary data
        ctx.res.write(_content,'binary')
        // End the response
        ctx.res.end()
    }else {
        // If it is not a picture, output other text
        ctx.body = _content
    }
})

app.listen(3000)
console.log('Successful startup')
Copy the code
//content.js

const path = require('path')
const fs = require('fs')
const dir = require('./dir')
const file = require('./file')


async function content(ctx,fullStaticPath){
    // CTX KOA context
    // The absolute local path of the static resource directory

    // Connect the static resource to the fetch request path
    let reqPath = path.join(fullStaticPath,ctx.url)
    // Check whether the path exists in a directory or file
    let exist = fs.existsSync(reqPath)
    let content = ' '
    // If the path does not exist, 404
    if(! exist){ content ='404 Not Found! '
    }else {
        // If so, asynchronously return information about the given file path to determine whether it is a file or a directory
        let stat = fs.statSync(reqPath)
        // If it is a directory
        if(stat.isDirectory()){
            content = dir(ctx.url,reqPath)
        }else {
            // If it is a file, the file content is read
            content = await file(reqPath)
        }
    }
    return content
}
module.exports = content
Copy the code
//dir.js

const url = require('url')
const fs = require('fs')
const path = require('path')

const walk = require('./walk')

function dir(url,reqPath){
    let contentList = walk(reqPath)
    let html = `<ul>`
    for(let [index,item] of contentList.entries()){
        html = `${html}<li><a href="${url === '/' ? ' ' : url}/${item} ">${item}</a></li>`
    }
    html = `${html}</ul>`
    return html
}
module.exports = dir
Copy the code
//file.js

const fs = require('fs')

function file (filePath) {
    let content = fs.readFileSync(filePath,'binary')
    return content
}
module.exports = file
Copy the code
// mimes.js

let mimes = {
    'css': 'text/css'.'less': 'text/css'.'gif': 'image/gif'.'html': 'text/html'.'ico': 'image/x-ico'.'jpeg': 'image/jpeg'.'jpg' : 'image/jpg'.'js': 'text/javascript'.'json': 'application/json'.'pdf': 'application/pdf'.'png': 'image/png'.'svg': 'image/svg+xml'.'swf': 'application/x-shockwave-flash'.'tiff': 'image/tiff'.'txt': 'text/plain'.'wav': 'audio/x-wav'.'wma': 'audio/x-ms-wma'.'wmv': 'video/x-ms-wmv'.'xml': 'text/xml'
}
module.exports = mimes
Copy the code
//walk.js

const fs = require('fs')
const mimes = require('./mimes')

function walk(reqPath){
    let files = fs.readdirSync(reqPath)
    let dirList = [],fileList = []
    for(let i = 0,len = files.length; i<len; i++){let item = files[i]
        let itemArr = item.split("\.")
        let itemMime = (itemArr.length > 1 )? itemArr[itemArr.length-1] :"undefined"
            if(typeof mimes[itemMime] === "undefined"){
                dirList.push(files[i])
            }else {
                fileList.push(files[i])
            }
    }
    let result = dirList.concat(fileList)
    return result
}
module.exports = walk
Copy the code

run

node index.js
Copy the code

Koa -static middleware

// index.js

const Koa = require('koa')
const path = require('path')
const static = require('koa-static')

const app = new Koa()

const staticPath = './static'
app.use(static(path.join(__dirname,staticPath)))

app.use(async (ctx) => {
    ctx.body = "hello world"
})
app.listen(3000.() = >{
    console.log('Successful startup')})Copy the code
// static/index.html

<! doctypehtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>index</title>
    <style>
        h1 {
            color: lightblue;
        }
    </style>
</head>
<body>
<h1>hello world</h1>
<img src="image/koa2.jpg" alt="">
</body>
</html>
Copy the code
  • run
node index.js
Copy the code

cookie/session

Koa2 using cookies

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

app.use(async(ctx)=>{
    if(ctx.url === '/index') {// Write cookies in the context
        ctx.cookies.set(
            'cid'.'hello world',
            {
                domain: 'localhost'.// Write the domain name of the cookie
                path: '/index'.// Write the path to the cookie
                maxAge: 10 * 60 * 1000.// Cookie validity period
                expires: new Date('2021-05-15'),// Cookie expiration duration
                httpOnly: false.// Whether to be used for HTTP requests
                overwrite: false // Whether to override
            }
        )
        ctx.body = 'cookie is ok' 
    }else {
        ctx.body = 'hello world' 
    }
})

app.listen(3000.() = >{
    console.log('Successful startup')})Copy the code
  • run
node index.js
Copy the code

Koa2 session

I need mysql to stop working for a while

Copy the code

Koa loads the template engine

Ejs is a templating engine that generates HTML from javaScript code

  • view
    • index.ejs
  • index.js
  • package.json
// index.js

const Koa = require('koa')
const views = require('koa-views')
const path = require('path')
const app = new Koa()

// Load the template engine
app.use(views(path.join(__dirname,'./view'), {extension: 'ejs'
}))

app.use(async(ctx)=>{
    let title = 'hello koa2'
    await ctx.render('index',{
        title,
    })
})

app.listen(3000.() = >{
    console.log('Successful startup')})Copy the code
// view/index.ejs
<! doctypehtml>
<html lang="en">
<head>
    <title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<p>EJS Welcome to <%= title %></p>
</body>
</html>
Copy the code

run

node index.js
Copy the code

File upload

The busboy module

  • index.js
  • package.json
  • util
    • upload.js
// index.js

const Koa = require('koa')
const path = require('path')
const app = new Koa()
const { uploadFile } = require('./util/upload')

app.use(async (ctx)=>{
    if(ctx.url === '/' && ctx.method === 'GET') {let html = ` 

koa2 upload demo

file upload

picName:





`
ctx.body = html }else if(ctx.url === '/upload.json' && ctx.method === 'POST') {let result = {success: false} let serverFilePath = path.join(__dirname,'upload-files') result = await uploadFile(ctx,{ fileType: 'album'.path: serverFilePath }) ctx.body = result }else { ctx.body = '

404!!!

'
} }) app.listen(3000.() = >{ console.log('Started successfully')})Copy the code
//upload.js

const inspect = require('util').inspect
const path = require('path')
const os = require('os')
const fs = require('fs')
const Busboy = require('busboy')

// Create a file directory
function mkdirsSync(dirname) {
    // Return true if the path exists
    if(fs.existsSync(dirname)){
        return true
    }else {
        //path.dirname() Gets the directory name in the path
        if(mkdirsSync(path.dirname(dirname))){
            // Create directory
            fs.mkdirSync(dirname)
            return true}}}// Get the suffix of the uploaded file
function getSuffixName(fileName){
    let nameList = fileName.split('. ')
    return nameList[nameList.length - 1]}// Upload the file
function uploadFile(ctx,options){
    let req = ctx.req
    let res = ctx.res
    let busboy = new Busboy({headers:req.headers})

    // Get the type
    let fileType = options.fileType || 'common'
    let filePath = path.join(options.path, fileType)
    let mkdirResult = mkdirsSync(filePath)

    return new Promise((resolve, reject) = > {
        console.log('File uploaded... ')
        let result = {
            success: false.formData: {}}// Parse the request file event
        busboy.on('file'.function(fieldname,file,filename,encoding,mimetype){
            let fileName = Math.random().toString(16).substr(2) + '. ' + getSuffixName(filename)
            let _uploadFilePath = path.join(filePath,fileName)
            let saveTo = path.join(_uploadFilePath)

            // Save the file to the specified path
            file.pipe(fs.createWriteStream(saveTo))

            // The file write event ends
            file.on('end'.function(){
                result.success = true
                result.message = 'File uploaded successfully'
                console.log('File uploaded successfully! ')
                resolve
            })
        })
        // Parse other field information in the form
        busboy.on('field'.function(fieldname,val,fieldnameTruncated,valTruncates,encoding,mimety){
            console.log('Form field data [' + fieldname + ']:valueL' + inspect(val));
            result.formData[fieldname] = inspect(val)
        })

        // Parse the end event
        busboy.on('finish'.function(){
            console.log('End on file');
            resolve(result)
        })

        // Parse the error event
        busboy.on('error'.function(err){
            console.log('Error on file');
            reject(result)
        })
        req.pipe(busboy)
    })
}
module.exports = {
    uploadFile
}
Copy the code

Asynchronous upload picture implementation