從零開始學習Koa(二)
一、Koa 路由
路由(Routing)是由一個 URI(或者叫路徑)和一個特定的 HTTP 方法(GET、POST 等) 組成的,涉及到應用如何響應客戶端對某個網站節點的訪問。
通俗的講:路由就是根據不同的 URL 地址,載入不同的頁面實現不同的功能。
Koa 中的路由和
Express
有所不同,在Express
中直接引入Express
就可以配置路由,但是在 Koa 中我們需要安裝對應的koa-router
路由模組來實現。
npm install --save koa-router
/** https://www.npmjs.com/package/koa-router 1.安裝模組 2.看文件使用 */ //引入 koa模組 var Koa=require('koa'); var router = require('koa-router')(); /*引入是例項化路由** 推薦*/ //例項化 var app=new Koa(); router.get('/',async (ctx)=>{ ctx.body="首頁"; }) router.get('/news',async (ctx)=>{ ctx.body="新聞列表頁面"; }) router.get('/newscontent',async (ctx)=>{ ctx.body="新聞詳情"; }) app.use(router.routes()); /*啟動路由*/ app.use(router.allowedMethods()); /* * router.allowedMethods()作用: 這是官方文件的推薦用法,我們可以 看到 router.allowedMethods()用在了路由匹配 router.routes()之後,所以在當所有 路由中介軟體最後呼叫.此時根據 ctx.status 設定 response 響應頭*/ app.listen(3002);
二、GET請求資料獲取
如果依靠ctx.request.url去手動處理路由,將會寫很多處理程式碼,這時候就需要對應的路由的中介軟體對路由進行控制,這裡介紹一個比較好用的路由中介軟體koa-router
安裝koa-router中介軟體
# koa2 對應的版本是 7.x
npm install --save [email protected]
快速使用koa-router
在 koa2 中 GET 傳值通過 request 接收,但是接收的方法有兩種:query 和 querystring。
- query:返回的是格式化好的引數物件。
- querystring:返回的是請求字串。
在koa中,獲取GET請求資料來源頭是koa中request物件中的query方法或querystring方法,query返回是格式化好的引數物件,querystring返回的是請求字串,由於ctx對request的API有直接引用的方式,所以獲取GET請求資料有兩個途徑。
-
一種是從上下文中直接獲取 請求物件ctx.query,返回如 { a:1, b:2 } 請求字串 ctx.querystring,返回如 a=1&b=2
-
一種是從上下文的request物件中獲取 請求物件ctx.request.query,返回如 { a:1, b:2 } 請求字串 ctx.request.querystring,返回如 a=1&b=2
/**
https://www.npmjs.com/package/koa-router
1.安裝模組
2.看文件使用
*/
//引入 koa模組
var Koa=require('koa');
var router = require('koa-router')(); /*引入是例項化路由** 推薦*/
//例項化
var app=new Koa();
router.get('/',async (ctx)=>{
ctx.body="首頁";
})
router.get('/news',async (ctx)=>{
ctx.body="新聞列表頁面";
})
//獲取get傳值
//http://localhost:3002/newscontent?aid=123
router.get('/newscontent',async (ctx)=>{
/*在 koa2 中 GET 傳值通過 request 接收,但是接收的方法有兩種:query 和 querystring。
query:返回的是格式化好的引數物件。
querystring:返回的是請求字串。*/
//從ctx中讀取get傳值
console.log(ctx.query); //{ aid: '123' } 獲取的是物件 用的最多的方式 ******推薦
console.log(ctx.querystring); //aid=123&name=zhangsan 獲取的是一個字串
console.log(ctx.url); //獲取url地址
//ctx裡面的request裡面獲取get傳值
console.log(ctx.request.url);
console.log(ctx.request.query); //{ aid: '123', name: 'zhangsan' } 物件
console.log(ctx.request.querystring); //aid=123&name=zhangsan
onst router = new Router(); router.get('/', function (ctx, next) {
ctx.body="Hello koa";
})
//從 request 中獲取 GET 請求
let request =ctx.request;
let req_query = request.query;
let req_querystring = request.querystring; //從上下文中直接獲取
let ctx_query = ctx.query;
let ctx_querystring =ctx.querystring;
ctx.body={
url,
req_query,
req_querystring,
ctx_query,
ctx_querystring
}
//ctx.body="新聞詳情";
})
app.use(router.routes()); /*啟動路由*/
app.use(router.allowedMethods());
/*
* router.allowedMethods()作用: 這是官方文件的推薦用法,我們可以
看到 router.allowedMethods()用在了路由匹配 router.routes()之後,所以在當所有
路由中介軟體最後呼叫.此時根據 ctx.status 設定 response 響應頭*/
app.listen(3002);
執行程式
node get.js
執行後程序後,用chrome訪問 http://localhost:3000/page/user?a=1&b=2 會出現以下情況
三、POST請求引數獲取
原理
對於POST請求的處理,koa2沒有封裝獲取引數的方法,需要通過解析上下文context中的原生node.js請求物件req,將POST表單資料解析成query string(例如:a=1&b=2&c=3
),再將query string 解析成JSON格式(例如:{"a":"1", "b":"2", "c":"3"}
)
注意:ctx.request是context經過封裝的請求物件,ctx.req是context提供的node.js原生HTTP請求物件,同理ctx.response是context經過封裝的響應物件,ctx.res是context提供的node.js原生HTTP請求物件。
具體koa2 API文件可見 https://github.com/koajs/koa/blob/master/docs/api/context.md#ctxreq
解析出POST請求上下文中的表單資料
demo原始碼
https://github.com/ChenShenhai/koa2-note/blob/master/demo/request/post.js
// 解析上下文裡node原生請求的POST引數
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)
}
})
}
// 將POST請求引數字串解析成JSON
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
}
舉個例子
原始碼在 /demos/request/post.js中
例子程式碼
const Koa = require('koa')
const app = new Koa()
app.use( async ( ctx ) => {
if ( ctx.url === '/' && ctx.method === 'GET' ) {
// 當GET請求時候返回表單頁面
let html = `
<h1>koa2 request post demo</h1>
<form method="POST" action="/">
<p>userName</p>
<input name="userName" /><br/>
<p>nickName</p>
<input name="nickName" /><br/>
<p>email</p>
<input name="email" /><br/>
<button type="submit">submit</button>
</form>
`
ctx.body = html
} else if ( ctx.url === '/' && ctx.method === 'POST' ) {
// 當POST請求的時候,解析POST表單裡的資料,並顯示出來
let postData = await parsePostData( ctx )
ctx.body = postData
} else {
// 其他請求顯示404
ctx.body = '<h1>404!!! o(╯□╰)o</h1>'
}
})
// 解析上下文裡node原生請求的POST引數
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)
}
})
}
// 將POST請求引數字串解析成JSON
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('[demo] request post is starting at port 3000')
})
啟動例子
node post.js
訪問頁面
提交表單發起POST請求結果顯示
四、koa-bodyparser中介軟體
原理
對於POST請求的處理,koa-bodyparser中介軟體可以把koa2上下文的formData資料解析到ctx.request.body中
安裝koa2版本的[email protected]中介軟體
npm install --save [email protected]
舉個例子
例子程式碼
demo原始碼
https://github.com/ChenShenhai/koa2-note/blob/master/demo/request/post-middleware.js
const Koa = require('koa')
const app = new Koa()
const bodyParser = require('koa-bodyparser')
// 使用ctx.body解析中介軟體
app.use(bodyParser())
app.use( async ( ctx ) => {
if ( ctx.url === '/' && ctx.method === 'GET' ) {
// 當GET請求時候返回表單頁面
let html = `
<h1>koa2 request post demo</h1>
<form method="POST" action="/">
<p>userName</p>
<input name="userName" /><br/>
<p>nickName</p>
<input name="nickName" /><br/>
<p>email</p>
<input name="email" /><br/>
<button type="submit">submit</button>
</form>
`
ctx.body = html
} else if ( ctx.url === '/' && ctx.method === 'POST' ) {
// 當POST請求的時候,中介軟體koa-bodyparser解析POST表單裡的資料,並顯示出來
let postData = ctx.request.body
ctx.body = postData
} else {
// 其他請求顯示404
ctx.body = '<h1>404!!! o(╯□╰)o</h1>'
}
})
app.listen(3000, () => {
console.log('[demo] request post is starting at port 3000')
})
啟動例子
node post-middleware.js