Koa处理url

一、koa-router

  为了处理URL,我们需要引入koa-router这个middleware,让它负责处理URL映射。

  我们修改app.js,使用koa-router来处理URL:

const Koa = require(‘koa‘);

// 注意require(‘koa-router‘)返回的是函数:
const router = require(‘koa-router‘)();

const app = new Koa();

// log request URL:
app.use(async (ctx, next) => {
    console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
    await next();
});

// add url-route:
router.get(‘/hello/:name‘, async (ctx, next) => {
    var name = ctx.params.name;
    ctx.response.body = `<h1>Hello, ${name}!</h1>`;
});

router.get(‘/‘, async (ctx, next) => {
    ctx.response.body = ‘<h1>Index</h1>‘;
});

// add router middleware:
app.use(router.routes());

app.listen(3000);
console.log(‘app started at port 3000...‘);

  注意导入koa-router的语句最后的()是函数调用

const router = require(‘koa-router‘)();

// 相当于:
const fn_router = require(‘koa-router‘);
const router = fn_router();

二、处理post请求

  用router.get(‘/path‘, async fn)处理的是get请求。如果要处理post请求,可以用router.post(‘/path‘, async fn)

  用post请求处理URL时,我们会遇到一个问题:post请求通常会发送一个表单,或者JSON,它作为request的body发送,但无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!

  所以,我们又需要引入另一个middleware来解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中。

  koa-bodyparser就是用来干这个活的。使用npm install安装。

  接下来,修改app.js,引入koa-bodyparser

const bodyParser = require(‘koa-bodyparser‘);

  在合适的位置加上

app.use(bodyParser());

  由于middleware的顺序很重要,这个koa-bodyparser必须在router之前被注册到app对象上

三、重构

  所有的URL处理函数都放到app.js里显得很乱,而且,每加一个URL,就需要修改app.js。随着URL越来越多,app.js就会越来越长。

  如果能把URL处理函数集中到某个js文件,或者某几个js文件中就好了,然后让app.js自动导入所有处理URL的函数。这样,代码一分离,逻辑就显得清楚了。最好是这样:

url2-koa/
+- controllers/
|  |
|  +- login.js <-- 处理login相关URL
|  |
|  +- users.js <-- 处理用户管理相关URL
|
+- app.js <-- 使用koa的js
|
+- package.json <-- 项目描述文件
|
+- node_modules/ <-- npm安装的所有依赖包

  我们先在controllers目录下编写index.js

var fn_index = async (ctx, next) => {
    ctx.response.body = `<h1>Index</h1>
        <form action="/signin" method="post">
            <p>Name: <input name="name" value="koa"></p>
            <p>Password: <input name="password" type="password"></p>
            <p><input type="submit" value="Submit"></p>
        </form>`;
};

var fn_signin = async (ctx, next) => {
    var
        name = ctx.request.body.name || ‘‘,
        password = ctx.request.body.password || ‘‘;
    console.log(`signin with name: ${name}, password: ${password}`);
    if (name === ‘koa‘ && password === ‘12345‘) {
        ctx.response.body = `<h1>Welcome, ${name}!</h1>`;
    } else {
        ctx.response.body = `<h1>Login failed!</h1>
        <p><a href="/">Try again</a></p>`;
    }
};

module.exports = {
    ‘GET /‘: fn_index,
    ‘POST /signin‘: fn_signin
};

  这个index.js通过module.exports把两个URL处理函数暴露出来。类似的,hello.js把一个URL处理函数暴露出来:

var fn_hello = async (ctx, next) => {
    var name = ctx.params.name;
    ctx.response.body = `<h1>Hello, ${name}!</h1>`;
}

module.exports = {
    ‘GET /hello/:name‘: fn_hello
}

  现在,我们修改app.js,让它自动扫描controllers目录,找到所有js文件,导入,然后注册每个URL:

// 先导入fs模块,然后用readdirSync列出文件
// 这里可以用sync是因为启动时只运行一次,不存在性能问题:
var files = fs.readdirSync(__dirname + ‘/controllers‘);

// 过滤出.js文件:
var js_files = files.filter((f)=>{
    return f.endsWith(‘.js‘);
});

// 处理每个js文件:
for (var f of js_files) {
    console.log(`process controller: ${f}...`);
    // 导入js文件:
    let mapping = require(__dirname + ‘/controllers/‘ + f);
    for (var url in mapping) {
        if (url.startsWith(‘GET ‘)) {
            // 如果url类似"GET xxx":
            var path = url.substring(4);
            router.get(path, mapping[url]);
            console.log(`register URL mapping: GET ${path}`);
        } else if (url.startsWith(‘POST ‘)) {
            // 如果url类似"POST xxx":
            var path = url.substring(5);
            router.post(path, mapping[url]);
            console.log(`register URL mapping: POST ${path}`);
        } else {
            // 无效的URL:
            console.log(`invalid URL: ${url}`);
        }
    }
}

四、Controller Middleware

  最后,我们把扫描controllers目录和创建router的代码从app.js中提取出来,作为一个简单的middleware使用,命名为controller.js

const fs = require("fs")

function addMapping(router, mapping) {
    for (var url in mapping) {
        if (url.startsWith(‘GET ‘)) {
            var path = url.substring(4);
            router.get(path, mapping[url]);
            console.log(`register URL mapping: GET ${path}`);
        } else if (url.startsWith(‘POST ‘)) {
            var path = url.substring(5);
            router.post(path, mapping[url]);
            console.log(`register URL mapping: POST ${path}`);
        } else {
            console.log(`invalid URL: ${url}`);
        }
    }
}

function addControllers(router, dir) {
    // 先导入fs模块,然后用readdirSync列出文件
    // 这里可以用sync是因为启动时只运行一次,不存在性能问题:
    var files = fs.readdirSync(__dirname + dir);
    // 过滤出.js文件:
    var js_files = files.filter(f => {
        return f.endsWith(‘.js‘);
    });
    // 处理每个js文件:
    for (var f of js_files) {
        console.log(`process controller: ${f}...`);
        // 导入js文件:
        let mapping = require(__dirname + ‘/controllers/‘ + f);
        addMapping(router, mapping);
    }
}

module.exports = function (dir) {
    let controllers_dir = dir || ‘/controllers‘,
        router = require("koa-router")()
    addControllers(router, controllers_dir)
    return router.routes()
}

  这样一来,我们在app.js的代码又简化了:

const Koa = require("koa")
const bodyParser = require("koa-bodyparser")
const controller = require("./controller")
const app = new Koa()
app.use(bodyParser())

// add router middleware:
app.use(controller());

app.listen(8080)
console.log("app started at port 8080")

  经过重新整理后的工程url2-koa目前具备非常好的模块化,所有处理URL的函数按功能组存放在controllers目录,今后我们也只需要不断往这个目录下加东西就可以了,app.js保持不变。

原文地址:https://www.cnblogs.com/goloving/p/12121944.html

时间: 2024-08-30 16:09:08

Koa处理url的相关文章

KoaHub.js -- 基于 Koa.js 平台的 Node.js web 快速开发框架之koahub-handlebars

koahub-handlebars koahub-handlebars koahub handlebars templates Installation $ npm install koahub-handlebars Use with koa var koa = require('koa'); var hbs = require('koahub-handlebars'); var app = koa(); // koahub-handlebars is middleware. `use` it 

基于 Koa平台Node.js开发的KoaHub.js的模板引擎代码

koahub-handlebars koahub-handlebars koahub handlebars templates Installation $ npm install koahub-handlebars Use with koa var koa = require('koa'); var hbs = require('koahub-handlebars'); var app = koa(); // koahub-handlebars is middleware. `use` it 

KoaHub.js:使用ES6/7特性开发Node.js框架(2)

    }       isLogin() {         console.log('base isLogin');     } }   //index controller, admin/controller/index.controller.js import base from "./base.controller"; export default class extends base{       constructor() {         super();      

koa+orm2

koa+orm2 koa是由 Express 原班人马打造的新的web框架.套用其官方的说法:Koa 应用是一个包含一系列中间件 generator 函数的对象. 这些中间件函数基于 request 请求以一个类似于栈的结构组成并依次执行. koa的中间件系统原理: Koa的精妙之处就在于其基于promise的中间件系统的实现,避免了免除重复繁琐的回调函数嵌套.Koa的中间件是一系列generator函数的对象,执行起来有点类似于栈的结构,依次执行.从网上找到一张图可以比较形象的说明koa的中间

Koa 请求日志打点工具

前一段时间开始搞优化后端 API 性能的事,发现根本无从下手,Kibana 中虽然有记一些简陋且零散的日志,但也瞅不出啥眉目来.总结了下是日志太少了,所以决定先搞搞日志的事,目标是记录 API 请求相关的日志,找出哪个接口慢,最好具体到哪个函数慢. 记日志必然要涉及日志打点,怎么做日志打点是个问题.如果直接在代码中插入日志打点代码不仅侵入性强而且工作量大,也不够灵活,于是考虑如何做智能的自动打点.我们石墨后端使用的 bay 框架(基于 [email protected] 二次开发,基本上你可以认

Koa框架实践与中间件原理剖析

Koa框架实践与中间件原理剖析 最近尝试用了一下Koa,并在此记录一下使用心得. 注意:本文是以读者已经了解Generator和Promise为前提在写的,因为单单Generator和Promise都能够写一篇博文来讲解介绍了,所以就不在这里赘述.网上资料很多,可以自行查阅. Koa是Express原班人马打造的一个更小,基于nodejs平台的下一代web开发框架.Koa的精妙之处就在于其使用generator和promise,实现了一种更为有趣的中间件系统,Koa的中间件是一系列generat

koa中间件分析

转载请注明: TheViper http://www.cnblogs.com/TheViper  另外可以参考http://purplebamboo.github.io/2014/05/24/koa-source-analytics-3/,作者用简单的方式造了一个山寨koa. koa是什么? koa是从2013年11月开始发布,更新的.和express相比,koa太年轻了.但它(用文档上的话说)通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升常用错误处理效率.Ko

nodejs 中koa框架下的微信公众号开发初始篇

最近在搞微信公众号开发,后端采用的是nodejs下的koa框架,初识后端的菜鸟,自己搞难度太大了,网上找了很多文章,采用的中间件大都是express框架下的,不过好在爬了许多坑之后总算看见点曙光了,遂把探索出来的一点东西拿出来分享,毕竟能力有限,拿出来也是希望大神看到了给点建议, 主要用 koa-wechat 处理验证和消息解析 ,用wechat-api来进行按钮组等api操作,刚开始没什么内容,大家随意看看就好, 废话不多说,直接上代码(这是一个route的代码): var koa = req

koa中使用的模块

今天开始学习目前呼声很高的koa模块,不过目前使用koa还是要用--harmony-generator标识,即便在刚出的nodejs 12上也是如此~,io.js倒是不需要,去年的nodejs和iojs分派不知道会不会带来什么大的变革,不过既然koa目前呼声这么高,肯定有他值得学习的地方,所以先搞着吧,多学点总比不学好. 这篇文章把koa依赖的模块列举一下,以后再自己学习koa的过程中减少一点查询的过程,也算是nodejs打基础的第一步吧~ accepts Higher level conten