处理post请求

简介: 处理post请求

处理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就是用来干这个活的。


我们在package.json中添加依赖项:


"koa-bodyparser": "3.2.0"


然后使用npm install安装。


下面,修改app.js,引入koa-bodyparser:


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


在合适的位置加上:


app.use(bodyParser());


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


现在我们就可以处理post请求了。写一个简单的登录表单:


router.get('/', 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>`;
});
router.post('/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>`;
    }
});


重构


现在,我们已经可以处理不同的URL了,但是看看app.js,总觉得还是有点不对劲。


image.png

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


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


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


于是我们把url-koa复制一份,重命名为url2-koa,准备重构这个项目。


我们先在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}`);
        }
    }
}

如果上面的大段代码看起来还是有点费劲,那就把它拆成更小单元的函数:


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) {
    var files = fs.readdirSync(__dirname + '/controllers');
    var js_files = files.filter((f) => {
        return f.endsWith('.js');
    });
    
    for (var f of js_files) {
        console.log(`process controller: ${f}...`);
        let mapping = require(__dirname + '/controllers/' + f);
        addMapping(router, mapping);
    }
}

addControllers(router);


确保每个函数功能非常简单,一眼能看明白,是代码可维护的关键。



Controller Middleware



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


const fs = require('fs');

function addMapping(router, mapping) {
    ...
}

function addControllers(router, dir) {
    ...
}

module.exports = function (dir) {
    let
        controllers_dir = dir || 'controllers', // 如果不传参数,扫描目录默认为'controllers'
        router = require('koa-router')();
    addControllers(router, controllers_dir);
    return router.routes();
};


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


...

// 导入controller middleware:
const controller = require('./controller');

...

// 使用middleware:
app.use(controller());

...
相关文章
|
4月前
|
JSON 数据格式
使用axios发送get和post请求
使用axios发送get和post请求
72 0
|
4月前
|
缓存
GET和POST请求
GET和POST请求
31 0
|
4月前
|
缓存 安全 API
Post请求和get请求的区别是什么?
Post请求和get请求的区别是什么?
|
4月前
|
容器
PostMan发送携带参数Get请求、Post请求及SpringMVC解决Post请求中文乱码问题
PostMan发送携带参数Get请求、Post请求及SpringMVC解决Post请求中文乱码问题
151 0
|
网络协议 Python
三、get请求和post请求
三、get请求和post请求
|
安全 前端开发 JavaScript
【GET请求和POST请求区别。】
GET请求和POST请求是HTTP协议中最常见的两种请求方法,它们在客户端向服务器发送请求时有着不同的特点和用途。
106 0
|
JSON JavaScript 数据格式
axios发送get和post请求详解
使用axios发送get和post请求详解
219 0
|
Web App开发 缓存 安全
get请求和post请求的区别
get请求和post请求的区别
get请求和post请求的区别