<返回更多

Egg服务器基础功能

2020-11-06    
加入收藏

Egg服务器基础功能
1. 框架约定目录规则

1.1 App/router.js:用于配置URL路由规则;

1.2 app/controller/** :用于解析用户的输入,处理后返回相应的结果;

1.3 app/service/**: 用于编写业务逻辑层;

1.4 app/public/**: 用于放置静态资源;

1.5 config/config.{env}.js: 用于编写配置文件;

1.6 config/plugin.js 用于配置需要加载的插件;

2.内置对象

1. Application:全局应用对象,在一个应用中,只会实例化一个对象;

在继承于 Controller, Service 基类的实例中,可以通过 this.app 访问到 Application 对象。

2. Request & Response:可以在 Context 的实例上获取到当前请求的 Request(ctx.request) 和 Response(ctx.response) 实例;

3. Controller:推荐所有的 Controller 都继承于该基类实现。该基类属性有:

ctx - 当前请求的 Context 实例。

app - 应用的 Application 实例。

service - 应用所有的 service。

4. Service:推荐所有的Service都继承该基类。

Service基类属性和 Controller 基类属性一致。

3.路由Router

路由是描述请求URL和具体承担执行动作的Controller的对应。说的直白点,就是用户访问不同的路径时应该有不同的Controller去响应不同的内容。

Egg服务器基础功能

 

4.控制器Controller

1. 控制器的定义以及和路由的关联

Controller负责解析用户的输入,处理后返回响应的结果。所有的Controller 文件都必须放在 app/controller目录下,支持多级目录,访问时可以通过目录名级联访问。如将Controller代码放到 app/controller/sub/post.js 中,则可以在 router 中这样使用:

// app/router.js
module.exports = app => {
app.router.post('createPost', '/api/posts', app.controller.sub.post.create);
}

同时,我们也可以自定义基类给控制器继承,官方案例如下:

// app/core/base_controller.js
const { Controller } = require('egg');
class BaseController extends Controller {
get user() {
return this.ctx.session.user;
}
success(data) {
this.ctx.body = {
success: true,
data,
};
}
notFound(msg) {
msg = msg || 'not found';
this.ctx.throw(404, msg);
}
}
module.exports = BaseController;

定义控制器继承他:

//app/controller/post.js
const Controller = require('../core/base_controller');
class PostController extends Controller {
async list() {
const posts = await this.service.listByUser(this.user);
this.success(posts);
}
}

5.获取提交的数据

接收GET请求的数据:ctx.request.query 和 ctx.query.id;

接收POST请求的数据:ctx.request.body,而不是 ctx.body;post请求时,会有安全验证问题,简单的处理方式是关闭安全验证:

// config/config.default.js

// 配置安全验证

config.security = {

csrf: {

enable: false,

ignoreJSON: true,

}

}

Post数据默认大小是100kb,如需调整可在 config/config.default.js 中覆盖框架的默认值:

 module.exports = {

                  bodyParser: {

                          jsonLimit: '1mb',

                          formLimit: '1mb',

                  },

};

接收路由参数:

// app.get('/projects/:projectId/app/:appId', 'app.listApp');

// GET /projects/1/app/2

class AppController extends Controller {

  async listApp() {

    assert.equal(this.ctx.params.projectId, '1');

    assert.equal(this.ctx.params.appId, '2');

  }

}

6.获取上传的文件

记住了,你要先在 config 文件中启用 file 模式:

// config/config.default.js
exports.multipart = {
mode: 'file',
};

然后,你就可以参考下面的代码了:

<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" id="avatar" multiple>
<input type="file" name="avatar1" id="avatar">
<input type="file" name="avatar2" id="avatar" multiple>
<input type="submit" value="上传">
</form>
这里的参考代码只处理一张图片,多张图片循环处理就可以了:

class UploadController extends Controller {

async file() {

const { ctx } = this;

const dest = '/public/upload/';

const file = ctx.request.files[0];

console.log(ctx.request.files);

let to = path.dirname(__dirname) + dest + path.basename(file.filepath);

// 处理文件,比如上传到云端 或 放到指定的目录

await fs.copyFileSync(file.filepath, to);

fs.unlinkSync(file.filepath);

console.log(dest);

// 返回图片路径

let cluster = this.app.config.cluster.listen;

ctx.body = `http://${cluster.hostname}:${cluster.port}${dest}${path.basename(file.filepath)}`;

}

}

7.Cookie

通过 ctx.cookies可以在 Controller 中便捷、安全的设置和读取 Cookie。

class CookieController extends Controller {
async add() {
const ctx = this.ctx;
let count = ctx.cookies.get('count');
count = count ? Number(count) : 0;
ctx.cookies.set('count', ++count);
ctx.body = count;
}
async remove() {
const ctx = this.ctx;
const count = ctx.cookies.set('count', null);
ctx.status = 204;
}
}

需要注意的是,cookie默认不支持中文,可以尝试转码,如encodeURI('中文egg'),然后再转回来decodeURI(ctx.cookies.get('username'));也可以通过加密的方式处理。

清除cookie把值设置为null即可。

在设置cookie时有个对象类型的可选参数,可以对cookie进行相关设置:

maxAge: 设置cookie的有效期,单位毫秒,默认浏览器关闭消失;

httpOnly:设置cookie是否允许js访问,默认true,不允许;

overwrite:如果设置为true,相同的键值对会被覆盖,否则发送两个;

signed:如果为true表示对cookie进行签名,不是加密,只是防止被篡改,注意在获取的时候也要提供该设置进行匹配;

encrypt:是否加密,true加密后客户端看不到明文,只能在服务器端获取,注意在获取的时候也要提供该设置进行匹配;

8.Session

Session 的使用方法非常直观,直接读取或者修改就可以,如果要删除它,直接将它赋值为 null:

class SessionController extends Controller {
async deleteSession() {
this.ctx.session = null;
}
};

注意:设置 session 属性时不要以 _ 开头,不能为 isNew

Session默认配置如下:

 exports.session = {

         key: 'EGG_SESS',

         maxAge: 24 * 3600 * 1000, // 1 天

         httpOnly: true,

         encrypt: true,

};

也可以针对性设置有效期:

 // 如果用户勾选了 `记住我`,设置 30 天的过期时间

if (rememberMe) ctx.session.maxAge = ms('30d');

重置session的有效期:当用户 Session 的有效期仅剩下最大有效期一半的时候

 // config/config.default.js

module.exports = {

  session: {

         renew: true,

  },

};

9.调用service

在 Controller 中可以调用任何一个 Service 上的任何方法,同时 Service 是懒加载的,只有当访问到它的时候框架才会去实例化它。

 // 调用 service 进行业务处理

const res = await ctx.service.post.create(req);

10.发送HTTP响应

i. 设置status

// 设置状态码为 201

this.ctx.status = 201;

ii. 设置body

ctx.body 是 ctx.response.body 的简写,不要和 ctx.request.body 混淆了;

// 响应内容

this.ctx.body = '<html><h1>Hello</h1></html>';

iii. JSONP

app.jsonp() 提供的中间件来让一个 controller 支持响应 JSONP 格式的数据。在路由中,我们给需要支持 jsonp 的路由加上这个中间件:

// app/router.js

module.exports = app => {

  const jsonp = app.jsonp();

  app.router.get('/api/posts/:id', jsonp, app.controller.posts.show);

  app.router.get('/api/posts', jsonp, app.controller.posts.list);

};

在 Controller 中,只需要正常编写即可。用户请求对应的 URL 访问到这个 controller 的时候,如果 query 中有 _callback=fn 参数,将会返回 JSONP 格式的数据,否则返回JSON格式的数据。

可配置:

// config/config.default.js

exports.jsonp = {

  callback: 'callback', // 识别 query 中的 `callback` 参数

  limit: 100, // 函数名最长为 100 个字符

};

 

iv. 重定向

Ø ctx.redirect(url) 如果不在配置的白名单域名内,则禁止跳转。

Ø ctx.unsafeRedirect(url) 不判断域名,直接跳转,一般不建议使用,明确了解可能带来的风险后使用。

用户如果使用ctx.redirect方法,需要在应用的配置文件中做如下配置:

// config/config.default.js

exports.security = {

  domainWhiteList:['.domain.com'],  // 安全白名单,以 . 开头

};

若用户没有配置 domainWhiteList 或者 domainWhiteList数组内为空,则默认会对所有跳转请求放行,即等同于ctx.unsafeRedirect(url)

 

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>