-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] 有egg基于ServerLess部署的指导方案吗? #3352
Labels
Comments
我看见函数计算(ServerLess)中需要编写函数入口,如果在egg中实现,是不是也需要提供入口文件~😜 |
This was referenced Dec 29, 2018
之前基于 入口// index.js
'use strict';
const App = require('./app');
module.exports.handler = async (request, response, _ctx) => {
const app = new App();
app.use(async (ctx, next) => {
await next();
console.log('it\'s fucking beautiful!');
});
// router handler
// 传入函数计算默认参数;
return app.run(request, response, _ctx);
}; 应用// app.js
const delegate = require('delegates');
const compose = require('koa-compose');
const config = require('./conf');
const onerror = require('./lib/onerror');
const respond = require('./lib/respond');
const middleware = require('./middleware');
const urllib = require('urllib');
const nunjucks = require('nunjucks');
module.exports = class App {
constructor(options) {
this.curl = urllib;
this.config = Object.assign(config, options);
this.renderString = nunjucks.renderString.bind(nunjucks);
this.middleware = Object.values(middleware).map(fn => fn(this));
}
createContext(request, response, _ctx) {
this.env = _ctx;
const context = {};
context.app = request.app = response.app = this;
context.req = context.request = request.req = response.req = request;
context.res = context.response = request.res = response.res = response;
delegate(context, 'app')
.access('env')
.access('curl')
.access('config')
.method('renderString');
delegate(context, 'request')
.access('url')
.access('path')
.access('method')
.access('queries')
.access('headers')
.access('clientIP');
delegate(context, 'response')
.method('send')
.method('setHeader')
.method('deleteHeader')
.method('setStatusCode');
return context;
}
use(fn) {
this.middleware.push(fn);
}
run(request, response, _ctx) {
const ctx = this.createContext(request, response, _ctx);
const handleError = err => onerror(err, ctx);
const handleResponse = () => respond(ctx);
const fn = compose(this.middleware);
return fn(ctx)
.then(handleResponse)
.catch(handleError);
}
}; 响应处理// lib/respond.js
const url = require('url');
const path = require('path');
const mime = require('mime-types');
const status = require('statuses');
const patchMatch = require('../utils/pathMatch');
module.exports = async ctx => {
const { pack } = ctx;
console.log('pack', pack);
const { packName, pathName } = pack;
// not match pack
if (!packName) {
console.log('not match pack');
ctx.setHeader('Content-Type', mime.contentType('index.html'));
ctx.setStatusCode(403);
ctx.send(status[403]);
return;
}
const prefix = `${ctx.config.oss.prefix}/${packName}`;
const assetsMap = await ctx.getObject(`${prefix}/config.json`);
const matched = patchMatch(pathName, assetsMap.pages);
console.log('matched', matched);
if (!matched) {
console.log('not found.');
ctx.setHeader('Content-Type', mime.contentType('index.html'));
ctx.setStatusCode(404);
ctx.send(status[404]);
return;
}
const page = assetsMap.pages[matched.route];
const { template, data, proxy } = page;
console.log('page', template, data, proxy);
// html
if (template) {
let tpl, locals;
const templatePath = url.parse(template).pathname;
const templateName = path.basename(templatePath);
tpl = await ctx.getObject(templatePath);
// locals
const env = {
params: matched.params || {},
queries: ctx.queries,
};
console.log('env', env);
if (data) {
const dataPath = url.parse(data).pathname;
locals = await ctx.getObject(dataPath);
console.log('locals', locals);
}
const body = ctx.renderString(tpl, Object.assign({}, env, locals || {}));
// console.log(body);
ctx.setHeader('Content-Type', mime.contentType(templateName));
ctx.setHeader('Cache-Control', 'max-age=0, s-maxage=120, must-revalidate');
ctx.send(body);
return;
}
// assets
if (proxy) {
const proxyName = path.basename(proxy);
const { data: asset } = await ctx.curl.request(proxy);
ctx.setHeader('Content-Type', mime.contentType(proxyName));
ctx.setHeader('Cache-Control', 'max-age=0, s-maxage=120, must-revalidate');
ctx.send(asset.toString());
return;
}
}; 错误处理// lib/onerror.js
'use strict';
module.exports = (err, ctx) => {
const msg = err.stack || err.toString();
console.error();
console.error(msg.replace(/^/gm, ' '));
console.error();
ctx.setStatusCode(500);
ctx.send(msg);
}; 中间件// middleware/oss.js
const mime = require('mime-types');
const oss = require('ali-oss');
module.exports = () => {
return async function storage(ctx, next) {
const { region, bucket, internal } = ctx.config.oss;
const { accessKeyId, accessKeySecret, securityToken } = ctx.env.credentials;
// init oss
const client = oss({
region,
internal,
accessKeyId,
accessKeySecret,
stsToken: securityToken,
});
client.useBucket(bucket);
ctx.client = client;
// make curl
ctx.getObject = async url => {
const mimetype = mime.lookup(url);
if (!mimetype) {
return;
}
const raw = await client.get(url);
if (mimetype === 'application/json') {
return JSON.parse(raw.content.toString());
}
return raw.content.toString();
};
await next();
};
}; |
fc 最好是能自己写 Runtime,这样的话把 egg 集成到 runtime 里面,用户代码不需要感知,现在也正在实践没有直接能用的产出。 |
这个需求还有人在跟进吗? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Background
可以用egg做阿里云的函数计算(ServerLess)开发吗?
看到函数计算文档,python使用Django框架开发的示例
使用egg可以实现ServerLess开发吗??
Proposal
可以参照Django案例的项目目录结构来写egg函数程序吗?求实现方案~
Additional context
The text was updated successfully, but these errors were encountered: