require('babel-polyfill') import Koa from 'koa' import bodyParser from 'koa-bodyparser' import Router from 'koa-router' import config from './config' let server = new Koa() let api = new Router() server.use(bodyParser()) let createGetRoute = function (route) { console.log('Route GET [' + route + ']') api.get(route, function *() { this.status = 200 this.body = this.params || {} }) } let createPutRoute = function (route) { console.log('Route PUT [' + route + ']') api.put(route, function *() { this.status = 200 this.body = this.params || {} }) } let createPostRoute = function (route) { console.log('Route POST [' + route + ']') api.post(route, function *() {
import 'babel-polyfill'; import Koa from 'koa'; import koaConvert from 'koa-convert'; import koaStatic from 'koa-static'; import koaBodyParser from 'koa-bodyparser'; import routes from './server/routes'; const app = new Koa(); app.use(koaConvert(koaStatic('public'))); app.use(koaBodyParser()); app.use(routes); app.listen(3000, () => { console.log('Server started: http://localhost:3000/'); // eslint-disable-line no-console });
securedRoutes.use('/api', json(), function*(next) { if (this.isAuthenticated()) { yield next; } else { this.status = 401; this.body = {error: 'Not authorized'}; } }, api.routes(), api.allowedMethods()); export default [ serve(__dirname + '/../public'), function*(next) { this.app.keys = ['superSecretKey12345']; yield next; }, bodyParser(), session({ store: new SessionStore(), cookie: {httpOnly: false} }), passport.initialize(), passport.session(), publicRoutes.middleware(), securedRoutes.middleware(), function*(next) { let store = this.state.store; // Populate user in the store store.dispatch({ type: 'USER', user: this.req.user }); store.dispatch({ type: 'INCREMENT' }); yield next; }
export default config => { const { port=8888, preRouteServerMiddleware=[], postRouteServerMiddleware=[], reduxMiddleware=[], reducers={}, routes=[], getServerRouter=() => {}, template=() => {}, dispatchBeforeNavigation=async () => {}, } = config; const server = new Koa(); const bodyparser = KoaBodyParser(); const router = new KoaRouter(); const handleRoute = async (ctx) => { const nav = navigationMiddleware.create(routes); const well = PromiseWell.create(); const thunk = Thunker.create(); const r = combineReducers({ ...reducers, platform }); const store = createStore(r, {}, applyMiddleware( ...reduxMiddleware, nav, thunk, well.middleware, )); store.dispatch(async (dispatch, getState, utils) => { await dispatchBeforeNavigation(ctx, dispatch, getState, utils); }); store.dispatch(actions.navigateToUrl( ctx.request.method.toLowerCase(), ctx.path, { queryParams: ctx.request.query, bodyParams: ctx.request.body, referrer: ctx.headers.referer, } )); await well.onComplete(); const state = store.getState(); // check for redirects const currentUrl = state.platform.currentPage.url; const currentQuery = state.platform.currentPage.queryParams; if (!isEqual(currentUrl, ctx.path) || !isEqual(currentQuery, ctx.request.query)) { if (currentUrl) { let newUrl = currentUrl; if (!isEmpty(currentQuery)) { newUrl += createQuery(currentQuery); } ctx.redirect(newUrl); } else { ctx.redirect('/'); } } else { ctx.body = template(state, store); } }; for (let route of routes) { let [path, handler] = route; for (let method of values(METHODS)) { if (handler.prototype[method]) { router[method](path, handleRoute); } } } getServerRouter(router); preRouteServerMiddleware.forEach(m => server.use(m)); server.use(bodyparser); server.use(router.routes()); server.use(router.allowedMethods()); postRouteServerMiddleware.forEach(m => server.use(m)); return () => { server.listen(port, () => { console.log(`App launching on port ${port}`); }); }; };
module.exports = function(){ //引入模块 var app = require('koa')(), swig = require('swig'), render = require('koa-swig'), ksc = require('koa-static-cache'), bodyparser = require('koa-bodyparser'), session = require('koa-session'), //favicon中间件 fav = require('./parts/favicon'), webset = require('./parts/webset'), router = require('./router/'), mongoose = require('./mongoose'), //获取默认配置 conf = require('./config'); //cookie key app.keys = [conf.secret]; //debug conf.debug && app.use(require('koa-logger')()); //parse app.use(bodyparser({formLimit:'2mb'})); //session app.use(session({maxAge:7* 24 * 60 * 60 * 1000},app)); //static cache conf.enableStatic && app.use(ksc(conf.static, {maxAge:0, dynamic:true})); //加载favicon.ioc app.use(fav()); //webset app.use(webset(swig)); //connection db mongoose(conf.mongodb); //init methods app.context.render = render({ root: conf.views, autoescape: true, cache: 'memory', // disable, set to false ext: 'html' }); app.context.msg = function(url, val, title){ return render('msg',{url:url,msg:val,secondtitle:title,time:5}); }; //Error Handling //app.use(function* (next) { // try { // yield next; // } catch (err) { // console.log(err) // this.redirect('/404'); // } //}); //routers router(app); //监听 app.listen(conf.port,function(){ console.log('listening on port ' + conf.port); }); }
module.exports = app => bodyParser()
var path = require('path'); var router = require('koa-router')(); var routers = require('./routes'); var bodyParser = require('koa-bodyparser'); var render = require('koa-ejs'); //var session = require('koa-session'); var session_generic = require('koa-generic-session'); var MysqlStore = require('koa-mysql-session'); var Config = require('./config'); var Admin = require('./modal/admin'); // log requests app.use(logger());//日志 app.use(bodyParser()); //解析post请求数据 //app.use(serve(__dirname + '/public')); //加载静态资源文件夹 app.use(staticCache(__dirname + '/public')); //加载静态资源文件夹缓存 // app.use(function *(next){ this; // is the Context this.request; // is a koa Request this.response; // is a koa Response yield next; }); app.env = process.env.NODE_ENV || 'development'; app.keys = [Config.key]; //app.use(function*(next){ // if(this.status !=='404'){ // return yield next;
Deepstream = require('deepstream.io'), Router = require('koa-router'), BodyParser = require('koa-bodyparser'), Send = require('koa-send'), Static = require('koa-static'), staticDir = Static('../dst'), ds = new Deepstream(), router = new Router(), app = module.exports = KOA(); const REDDITUSERAGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2728.0 Safari/537.36:dum.demo:v0.0.1 (by /u/fossage)'; app.use(BodyParser({ detectJSON: function (ctx) { return /\.json$/i.test(ctx.path); } })); // ds.set( 'urlPath', '/io' ); // ds.set( 'httpServer', app ); router .get('/api/authorize_reddit', function *(next) { this.body = request({ url: 'https://www.reddit.com/api/v1/access_token', method: 'post', body: 'grant_type=client_credentials', contentType: 'application/json', userAgent: REDDITUSERAGENT, auth: {
app.use(rewrite('/favicon.ico', '/favicon.png')); app.use(staticCache); if (config.pagemock) { app.use(require('koa-mock')({ datadir: path.join(rootdir, 'test', 'mocks') })); } app.use(opensearch); app.keys = ['todokey', config.sessionSecret]; app.proxy = true; app.use(proxyToNpm({ isWeb: true })); app.use(bodyParser({ jsonLimit: config.jsonLimit, strict: false })); app.use(auth()); app.use(notFound); if (config.enableCompress) { app.use(middlewares.compress({threshold: 150})); } app.use(conditional()); app.use(etag()); var viewDir = config.viewDir || path.join(rootdir, 'view', 'web'); var docDir = path.join(rootdir, 'docs', 'web'); var layoutFile = path.join(viewDir, '_layout.html'); var footer = config.customFooter || fs.readFileSync(path.join(viewDir, 'footer.html'), 'utf8');
var fdbserver = { app:app, router:router, loadSysFile:loadSysFile, run:function() { this.app.run(); } } var filedir = process.cwd()+"/file/"; if (!fs.existsSync(filedir)) { fs.mkdir(filedir); } app.keys = [setting.key]; app.use(session(app)); app.use(bodyParser({formLimit:5*1000*1000, jsonLimit:5*1000*1000})); function response(res, code, msg) { res.status = code; res.set({'Content-Length':''+msg.length,'Content-Type':'text/plain'}); res.body = msg; if (code !== 200) console.log('response error : ', code, msg); } fdbserver.response = response; fdbserver.doAfterFilePost=function*(path, self) { yield Promise.resolve(false); } fdbserver.doAfterPostDb=function*(table, op, body) {
module.exports = function(root, kpath) { /** * ===================自定义部分===================== * C全局静态配置 * D全局数据模型 * G全局动态变量 * M全局外部模块调用 * R全局请求 */ global.C = {}; //global.M = {}; global.F = {}; global.G = {}; //global.R = {}; //C配置文件 M通用模块插件 F 内置函数 D 数据库类 //================主模块========================= var koa = require('koa'), staticCache = require('koa-static-cache'), //static = require('koa-static'), swig = require('swig'), app = koa(), path = require('path'), fs = require('fs'), // co = require('co'), //parse = require('co-body'), bodyParser = require('koa-bodyparser'), // views = require('co-views'), combo = require('koa-combo') global._ = require('lodash'); //===================获取配置内容 var systemConfig = require(kpath + '/config')(root); var clientConfig = require(root + '/config/config')(root); _.extend(systemConfig, clientConfig); C = systemConfig; //===================缓存配置 C.debug = {}; C.debug.common = false; //全局debug C.debug.logger = true; //请求debug C.debug.db = true; //数据库debug //===================debug module if (C.debug.common || C.debug.logger) { var logger = require('koa-logger'); app.use(logger()); } //===================定义模版类型以及路径 require('koa-swig')(app, { root: C.view, autoescape: true, //cache: 'memory', // disable, set to false ext: 'html', //locals: locals, //filters: filters, //tags: tags, //extensions: extensions }); //post 处理 this.request.body; app.use(bodyParser()); //路由 //定义静态模版以及路径 /*app.use(staticCache(path.join(root, 'static'), { maxAge: 365 * 24 * 60 * 60 }))*/ var static_root = path.join(root, 'static'); app.use(staticCache(static_root, { maxAge: 860000000, gzip:true })); //静态文件加载 app.use(combo([static_root])); //公共函数定义 合并 lodash var styleFn = require(kpath + '/function/init')(kpath); //F = _; _.extend(F, styleFn); //model 初始化 require(kpath+'model')(app,fs) //密钥 app.keys = [C.secret]; //favicon 特殊处理 app.use(function * (next) { //非favicon 直接跳过 if ('/favicon.ico' != this.path) return yield next; //头部定义防止 404 if ('GET' !== this.method && 'HEAD' !== this.method) { this.status = 'OPTIONS' == this.method ? 200 : 405; this.set('Allow', 'GET, HEAD, OPTIONS'); return; } }); require(kpath+'controller')(app,fs) //404页面 app.use(function * pageNotFound(next) { this.body = yield this.render('404'); }); /** * 监听端口 */ app.listen(C.port); console.log('listening on port ' + C.port); /** * 错误处理 */ app.on('error', function(err) { console.log('server error', err); }); }
const index = require('./routes/index') const users = require('./routes/users') // error handler onerror(app) app.keys = ['keys', 'keyskeys'] app.use(session({ key: 'mt', prefix: 'mtpr', store: new koaRedis() })) // middlewares app.use(bodyparser({ enableTypes: ['json', 'form', 'text'] })) app.use(json()) app.use(logger()) app.use(require('koa-static')(__dirname + '/public')) app.use(views(__dirname + '/views', { extension: 'ejs' })) // logger app.use(async (ctx, next) => { const start = new Date() await next() const ms = new Date() - start console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
let config = global.config; let config_vhost = global.config.vhost; let config_api = global.config.api; let config_path = global.config.path; let config_path_project = global.config.path.project; let config_site = global.config.site; let config_template = global.config.template; let config_mongo = global.config.mongo; let config_mock = global.config.mock; let app = koa(); // bodyparser app.use(bodyparser({ formLimit:'5mb' })); // gzip app.use(gzip()); // 配置静态文件路由 app.use(_static('/static', config_path_project, config_vhost)); let vhosts = []; for (let item in config_vhost) { vhosts.push(item); } vhosts = vhosts.map(function(item) { let vapp = koa();
var params = require('..'); var koa = require('koa'); var bodyparser = require('koa-bodyparser'); var qs = require('koa-qs') var app = koa(); qs(app); // required for nested query string objects app.use(bodyparser()); // required for params to include request body objects app.use(params()); app.use(function *() { this.body = this.params.all(); }); app.listen(3001);
config = require('config'), koa = require('koa'), route = require('koa-route'), parser = require('koa-bodyparser'), // Routes packageRoutes = require(__dirname + '/server/package'), authenticationRoutes = require(__dirname + '/server/authentication'), // Server variables port = 3000, // Default to 3000 app; app = koa(); app.use(parser()); if (config.has('debug') && config.get('debug') === true) { app.use(function *(next) { yield next; // Log both URL and body console.log(this.url); console.log(this.method); console.log(this.request.headers); console.log(this.request.body); }); } /* * Package section
const database = require('./config/database'); const appRouter = require('./routes/index'); /** * Set and create koa server */ var app = koa(); // trust proxy app.proxy = true // set keys app.keys = [config.secret]; app.use(logger()); app.use(bodyParser(config.bodyParser)); app.use(session(app)); app.use(passport.initialize()); app.use(passport.session()); app.use(appRouter.routes()); app.use(compress()); // MongoDB console.log('Connecting to MongoDB...'); mongoose.connect(database.url); app = module.exports = http.createServer(app.callback()); if (!module.parent) { const port = process.env.PORT || config.port || 8888;
maxage: 365 * 24 * 60 * 60 })) render(app, { root: path.join(__dirname, 'template'), layout: 'template', viewExt: 'html', cache: false, debug: true }); app.use(userAgent()); app.use(bodyParser({ extendTypes: { json: ['application/x-javascript'] } })); router.post("/mj_render", function *(next) { var data = this.request.body; var subject = data['subject'] || 'math'; var item_list = data['item_list']; var ua = this.state.userAgent; var browser = ua.browser; var version = ua.version; var format = data['format'] || (browser === 'IE' && Number(version) < 9 ? 'html' : 'svg'); var format_obj = {'svg': 'SVG', 'html': 'CommonHTML'}; var render_type = format_obj[format]; var promise_list = [];
co(function* coWrapper() { require("./auth"); const sessionStore = new RethinkSession({connection: r}); yield sessionStore.setup(); const app = new Koa(); exports.app = app; app.proxy = true; app.use(bodyParser()); app.keys = config.site.keys; app.use(session({ store: sessionStore })); app.use(passport.initialize()); app.use(passport.session()); // statically serve assets app.use(serve("./assets")); app.use(hbs.middleware({ viewPath: `${__dirname}/views`, layoutsPath: `${__dirname}/views/layouts`, partialsPath: `${__dirname}/views/partials`, defaultLayout: "main" })); app.use(function* appUse(next) { try { yield next; } catch (err) { if (this.state.api === true) { // if this was an API request, send the error back in a plain response this.app.emit("error", err, this); this.body = {error: true, message: String(err)}; } else { // this wasn"t an API request, show the error page this.app.emit("error", err, this); yield this.render("error", { dump: err }); } } }); require("./routes"); console.log(`${config.site.name} is now listening on port ${config.site.port}`); app.listen(config.site.port); if (process.env.NODE_ENV === "local") { // react stuff const webpack = require("webpack"); const webpackConfig = require("./webpack.config.js"); const WebpackDevServer = require("webpack-dev-server"); // WEBPACK DEV SERVER new WebpackDevServer(webpack(webpackConfig), { "hot": true, "historyApiFallback": true, proxy: { "*": `http://localhost:${config.site.port}` }, stats: "errors-only" }).listen(config.site.port + 1, "localhost", function webpackDevServer(err, result) { if (err) { console.error(err); } console.log(`Webpack Dev Server (Hot-Reload) listening on port ${config.site.port + 1}`); }); } process.on("SIGINT", function end() { process.exit(); }); });
import koa from 'koa'; import bodyparser from 'koa-bodyparser'; import route from 'koa-route'; import mount from 'koa-mount'; import serve from 'koa-static'; import views from 'koa-views'; import pg from 'koa-pg'; import Healthcheck from './api/healthcheck'; import Standings from './api/standings'; import Matches from './api/matches'; import Awards from './api/awards'; import Players from './api/players'; const app = koa(); app.use(bodyparser()); app.use(mount('/static', serve(__dirname + '/static'))); app.use(views(__dirname + '/views', { map: { html: 'mustache' } })); app.use(pg({ name: 'db', conStr: process.env.DATABASE_URL })); app.use(route.get('/api/healthcheck/', Healthcheck.list)); app.use(route.get('/api/standings/', Standings.list));
export default async function createServer() { const app = new Koa(); const serviceNames = getServiceNames(); const compiler = createClientCompiler(serviceNames); Schema.autoLoadTables(); const schema = new Schema(); app.use(bodyParser()); app.use(async (context, next) => { if (context.path === `/_api` && (context.method === `POST` || context.method === `GET`)) { try { const [ serviceName, methodName, ] = context.request.query.method.split(`.`); // TODO: If context.request.body is not an array, exit. // TODO: There should be some sort of check to see if executing this service method is // allowed. const Service = getService(serviceName); if (!Service) { console.log(`Could not find service with name ${serviceName}`); } else { await callServerService(Service, methodName, context, schema); } } catch (e) { console.log(`exception in server api`); console.log(e); context.type = `json`; context.body = JSON.stringify({ error: true }); context.status = e.status || 500; } } else { await next(); } }); app.use(webpackMiddleware({ compiler, dev: { noInfo: true, stats: false, quiet: true, log: false, }, hot: { noInfo: true, quiet: true, stats: false, log: false, }, })); app.use(async (context, next) => { await next(); // TODO: Server-render everything? Including the css! // TODO: We should use jsx and renderToString? context.type = `html`; context.body = `<!doctype html> <html> <head> <title></title> </head> <body> <div id="root"></div> </body> <script src="/client.js"></script> </html>`; }); app.listen(3000); }
stats: { colors: true } })); app.use(hotMiddleware(compile, { // log: console.log, // path: '/__webpack_hmr', // heartbeat: 10 * 1000 })); } /********************* * middlewares */ app.use(convert(bodyparser())); app.use(json()); app.use(logger()); app.use(convert(koaStatic(config.server.path + 'public'))); app.use(views(config.server.path + 'views', { extension: 'ejs' })); console.log('-----配置', config); /********* * 网站路由 */ // app.use(router.routes()).use(router.allowedMethods()); import index from './server/routes/index'; app.use(index.routes()).use(index.allowedMethods());
function Scaffold(configs) { var settings = _.extend(_.clone(defaults), configs || {}); var devMode = true; if (settings.env === 'production') devMode = false; // find `views` and `public` abs path var dirs = {}; dirs.views = finder(configs, 'views'); dirs.uploads = finder(configs, 'uploads'); var app = koa(); app.db = monk(settings.database.name); app.keys = ['feedr session']; app.use(bodyParser()); app.use(session(app)); app.use(passport.initialize()); app.use(passport.session()); app.use(views(settings.views, settings.view_options)); app.use(logger(devMode ? 'dev' : settings.logformat)); app.use(router(app)); if(Array.isArray(settings.publics)) { for(var i = 0; i < settings.publics.length; i++) { app.use(serve(settings.publics[i])); } } else { app.use(serve(settings.publics)); } locale(app); // expose locals to template engine locals(app, { sys: pkg, site: settings }); app.use(i18n(app, settings.i18n)); //app.use(errors()); app.use(function *(next) { try { yield next; } catch (err) { console.log(err); if(err.status === 401) { this.status = 401; this.set('WWW-Authenticate', 'Basic'); this.body = 'Unauthorized request'; } if(!err.status) { this.status = 500; yield this.render(settings.error['500']); } else { this.status = err.status; } } if(this.status === 200) { return; } if(!this.status) { this.status = 404; } if(this.status === 404) { yield this.render(settings.error['404']); } if(this.status === 500) { yield this.render(settings.error['500']); } }); //setting language-cookie if f.e. ?lang=de is added to the url app.use(function * (next) { this.i18n.setLocaleFromQuery(this.request); yield next; var currentLocale = this.i18n.getLocale(); this.cookies.set('lang', currentLocale, { signed: true }); }); // setup server settings var port = _.isNumber(settings.port) ? settings.port : defaults.port; this.app = app; this.port = port; return new Inner(app, port); }
const utils = require('./utils'); const WS = require('./ws'); const Rethink = require('./repos/rethink'); Rethink.openConnection().then((conn) => { Rethink.prepareTables().run(conn).then( () => { conn.close(); } ); }); var app = koa(); app.use(body()); for (var mdw of utils.middlewares) { app.use(mdw); } app.use(views.routes()); app.use(views.allowedMethods()); app.ws = new WS(app); const koaListen = app.listen; app.listen = (port, callback) => { app.server = koaListen.apply(app, [port, callback]); app.ws.listen(app.server);
var koa = require('koa') var jwt = require('koa-jwt'); var cors = require('koa-cors'); var routes = require('koa-route'); var bodyparser = require('koa-bodyparser'); var dotenv = require('dotenv'); dotenv.load(); // App configuration var app = koa(); app.use(cors()); // Enable cross-site data transfer app.use(bodyparser()); // Enable POST body parsing // Routes var ping = require('./routes/ping'); var register = require('./routes/register'); // Validate incoming id_tokens unless they are going through a public directory var privateKey = new Buffer(process.env.AUTH0_CLIENT_SECRET, 'base64'); app.use( jwt({ secret: privateKey, algorithm: 'HS256' }) .unless({path:[/^\/public/]}) ); app.use(routes.get('/public/ping', ping.publicPing)); app.use(routes.get('/ping', ping.privatePing)); app.use(routes.post('/register', register.create));
heartbeat: 10 * 1000 }))) app.use(serve(__dirname + '/../public')) app.use(convert(jwt({ secret: process.env.JWT_SECRET }).unless({ path: [ '/login', '/register', '/favicon.ico' ] }))) app.use(logger()) app.use(convert(bodyParser())) //app.keys = ['some secret hurr'] //app.use(convert(session(app))) app.use( indexRouter.routes(), indexRouter.allowedMethods() ) app.use( userRouter.routes(), userRouter.allowedMethods() ) app.use( loginRouter.routes(), loginRouter.allowedMethods() )
init: async (config) => { params = config; const app = new Koa(); const sessions = sessionManager.getSessions(); const sessionMaxAge = 1000 * 60 * 60 * 24 * 7; const sessionName = "apiio"; const staticPaths = [ path.join(__dirname, "..", "..", "node_modules", "semantic-ui-css"), path.join(__dirname, "..", "..", "www", "pages", "default", "static") ]; // Setup application app.use(compress()); app.use(bodyParser({ enableTypes: [ "json", "form", "text" ] })); app.use(conditional()); app.use(etag()); app.use(range); // Configure error handling app.use(async (ctx, next) => { try { await next(); } catch (error) { console.error(error); ctx.status = error.status || 500; ctx.type = "json"; ctx.body = JSON.stringify({ result: "fail", error: error.message || error, status: ctx.status }, null, 2); } }); // Configure sessions app.use(async (ctx, next) => { let sessionId = false; try { sessionId = ctx.cookies.get(sessionName); } catch (e) { } if (!sessionId || !sessions[sessionId]) { sessionId = uuid.v4(); sessions[sessionId] = { _id: sessionId }; } ctx.session = sessions[sessionId]; ctx.session._expires = ctx.session._expires || new Date(Date.now() + sessionMaxAge); ctx.cookies.set(sessionName, sessionId, { maxAge: sessionMaxAge }); await next(); }); for (const staticPath of staticPaths) { app.use(serve(staticPath)); } app.use(async (ctx, next) => { if (ctx.path !== "/") { return next(); } ctx.type = "text/html; charset=utf-8"; ctx.body = fs.createReadStream(path.join(__dirname, "..", "..", "www", "index.html")); }); const mediaRoutes = media.routes(); for (const mroute of mediaRoutes) { app.use(route[mroute.method.toLowerCase()](mroute.route, mroute.handler)); } log.info(`Webpack is running in ${config.production ? "production" : "development"} mode`); const webpackCfg = await buildWebpackCfg({ dev: !config.production, configuration: {} }); const webpackMiddlewareConf = webpackMiddleware(webpack(webpackCfg), { stats: { colors: true } }); app.use(webpackMiddlewareConf); app.use(route.get("*", async (ctx) => { ctx.type = "text/html; charset=utf-8"; ctx.body = fs.createReadStream(path.join(__dirname, "..", "..", "www", "index.html")); })); // app.use(route.get("*", async (ctx) => await send(ctx, "/index.html", { root: path.join(__dirname, "..", "..", "www") }))); server = app.listen(params.port); enableDestroy(server); // Socket.io if we have defined API await api.start(server, { sessionName: sessionName, sessionMaxAge: sessionMaxAge }, sessions); log.info(`Now listening for http request on port ${params.port}`); },
if (stats.isDirectory()) { this.body = yield * FileManager.list(p); } else { //this.body = yield fs.createReadStream(p); this.body = origFs.createReadStream(p); } }); router.del('/api/(.*)', Tools.loadRealPath, Tools.checkPathExists, function *() { var p = this.request.fPath; yield * FileManager.remove(p); this.body = 'Delete Succeed!'; }); router.put('/api/(.*)', Tools.loadRealPath, Tools.checkPathExists, bodyParser(), function* () { var type = this.query.type; var p = this.request.fPath; if (!type) { this.status = 400; this.body = 'Lack Arg Type' } else if (type === 'MOVE') { var src = this.request.body.src; if (!src || ! (src instanceof Array)) return this.status = 400; var src = src.map(function (relPath) { return FilePath(relPath); }); yield * FileManager.move(src, p); this.body = 'Move Succeed!'; }
async beforeStart(app) { app.use(convert(sessionMiddleware(app))); app.use(convert(bodyParserMiddleware())); }
var oauthserver = require('koa-oauth-server'); var oauthModel = require('./lib/oauth_model'); var render = require('koa-swig'); var path = require('path'); var app = koa(); var TaskEngine = require('./lib/task_engine'); app.oauth = oauthserver({ model: oauthModel, grants: ["password", "refresh_token"], accessTokenLifetime: 3600*24*365, refreshTokenLifetime: 3600*24*365, debug: true }); app.use(bodyParser()); router.all('/oauth/token', app.oauth.grant()); app.context.render = render({ root: path.join(__dirname, 'views'), autoescape: true, cache: false, // disable, set to false ext: 'html' // locals: locals, // filters: filters, // tags: tags, // extensions: extensions }); /** * 统一处理默认Error
// Sets up a Web Server instance (based on Koa) // // options: // // compress - enables tar/gz compression of Http response data // // extract_locale - extracts locale from Http Request headers // and places it into this.locale // // session - tracks user session (this.session) // // authentication - uses a JWT token as a means of user authentication // (should be a function transforming token payload into user info) // // parse_post_requests - parse Http Post requests body // // routing - enables Rest Http routing // (usage: web.get('/path', parameters => return 'Echo')) // // log - bunyan log instance // // csrf - enables protection against Cross Site Request Forgery attacks // (pending) // // secret - gives access to app.keys[0] when using routing feature // // returns an object with properties: // // shut_down() - gracefully shuts down the server (pending) // // connections() - returns currently open connections count (not tested) // // errors - a set of common Http errors // // Unauthorized // Access_denied // Not_found // Input_missing // // file_upload() - enables file upload functionality // // parameters: // // path - the URL path to mount this middleware at (defaults to /) // // output_folder - where to write the files // // root_folder - Http response will contain file_name (or file_names) // relative to this folder // // multiple_files - set this flag to true in case of multiple file upload // // serve_static_files() - enables serving static files // // parameters: // // url_path - the URL path to mount this middleware at // // filesystem_path - the corresponding filesystem path where the static files reside // // listen() - starts listening for requests // // parameters: // // port - the TCP port to listen on // host - the TCP host to listen on (defaults to 0.0.0.0) // // returns: a Promise // // mount() - mounts a middleware at a path // // parameters: // // path - the URL path to mount the middleware at // middleware - the middleware to mount // // use() - standard Koa .use() method // // proxy() - proxies all requests for this path to another web server // // parameters: // // path - the URL path to mount the requests for // destination - where to proxy these requests to // export default function web_server(options = {}) { // this object will be returned const result = {} // instantiate a Koa web application const web = koa() if (options.compress) { // хз, нужно ли сжатие в node.js: мб лучше поставить впереди nginx'ы, // и ими сжимать, чтобы не нагружать процесс node.js web.use(compress()) } // handle errors web.use(function*(next) { // generic errors for throwing // (for convenient access from the subsequent middlewares and Http request handlers) this.errors = result.errors try { // // measure Http request processing time // const key = `${this.host}${this.url}` // // started processing Http request // console.time(key) // try to respond to this Http request yield next // // finished processing Http request // console.timeEnd(key) } catch (error) { let http_status_code if (exists(error.http_status_code)) { http_status_code = error.http_status_code } // superagent errors // https://github.com/visionmedia/superagent/blob/29ca1fc938b974c6623d9040a044e39dfb272fed/lib/node/response.js#L106 else if (typeof error.status === 'number') { http_status_code = error.status } if (exists(http_status_code)) { // set Http Response status code according to the error's `code` this.status = http_status_code // set Http Response text according to the error message this.message = error.message || 'Internal error' } else { // log the error, if it's not a normal Api error // (prevents log pollution with things like // `404 User not found` or `401 Not authenticated`) log.error(error) this.status = 500 this.message = 'Internal error' } } }) if (options.log) { web.use(koa_logger(log, { // which level you want to use for logging. // default is info level: 'debug', // this is optional. Here you can provide request time in ms, // and all requests longer than specified time will have level 'warn' timeLimit: 100 })) } if (options.extract_locale) { // get locale from Http request // (the second parameter is the Http Get parameter name) koa_locale(web, 'locale') // usage: // // .use(function*() // { // const preferred_locale = this.getLocaleFromQuery() || this.getLocaleFromCookie() || this.getLocaleFromHeader() || 'en' // }) } // Set up session middleware web.keys = configuration.session_secret_keys if (options.authentication) { const validate_token_url = '/validate-token' function get_jwt_token(context) { let token = context.cookies.get('authentication') if (token) { return { token } } if (context.header.authorization) { const parts = context.header.authorization.split(' ') if (parts.length !== 2) { return { error: 'Bad Authorization header format. Format is "Authorization: Bearer <token>"' } } const scheme = parts[0] const credentials = parts[1] if (!/^Bearer$/i.test(scheme)) { return { error: 'Bad Authorization header format (scheme). Format is "Authorization: Bearer <token>"' } } return { token: credentials } } return { error: 'JWT token not found' } } function validate_token(jwt, bot) { return http_client.get ( `${address_book.authentication_service}${validate_token_url}`, { bot }, { headers: { Authorization: `Bearer ${jwt}` } } ) } // takes some milliseconds to finish // because it validates the token via an Http request // to the authentication service async function authenticate() { const { token, error } = get_jwt_token(this) this.authenticate = () => { throw new result.errors.Unauthenticated() } this.role = () => { throw new result.errors.Unauthenticated() } if (!token) { this.authentication_error = new result.errors.Unauthenticated(error) return } this.jwt = token let payload for (let secret of web.keys) { try { payload = jwt.verify(token, secret) break } catch (error) { // if authentication token expired if (error.name === 'TokenExpiredError') { this.authentication_error = new result.errors.Unauthenticated('Token expired') return } // try another `secret` if (error.name === 'JsonWebTokenError') { continue } // some other error throw error } } if (!payload) { this.authentication_error = new result.errors.Unauthenticated('Corrupt token') return } const jwt_id = payload.jti // subject const user_id = payload.sub // validate token // (for example, that it has not been revoked) if (this.path !== validate_token_url) { if (!this.validating_jwt_id) { this.validating_jwt_id = validate_token(token, this.query.bot) } // takes some milliseconds to finish // // validates the token via an Http request // to the authentication service const is_valid = (await this.validating_jwt_id).valid delete this.validating_jwt_id if (!is_valid) { this.authentication_error = new result.errors.Unauthenticated('Token revoked') return } } this.jwt_id = jwt_id this.user = options.authentication(payload) this.user.id = user_id // payload fields: // // 'iss' // Issuer // 'sub' // Subject // 'aud' // Audience // 'exp' // Expiration time // 'nbf' // Not before // 'iat' // Issued at // 'jti' // JWT ID this.token_data = payload this.authenticate = () => this.user this.role = (...roles) => { for (let role of roles) { if (this.user.role === role) { return true } } throw new result.errors.Unauthorized(`One of the following roles is required: ${roles}`) } } web.use(function*(next) { yield authenticate.bind(this)() yield next }) } if (options.session) { const ttl = 15 * 60 * 1000 // 15 minutes // session timeout, in seconds if (configuration.redis) { const redis_client = redis.createClient ({ host : configuration.redis.host, port : configuration.redis.port, auth_pass : configuration.redis.password // auth_pass }) const prefix = 'user:session:' function generate_id() { return uid.sync(24) // 24 is "byte length"; string length is 32 symbols } async function is_unique(id) { return !(await redis_client.existsAsync(prefix + id)) } async function generate_unique_id() { const id = generate_id() if (await is_unique(id)) { return id } return generate_unique_id() } web.use(session ({ key : 'session:id', prefix, cookie : { maxAge : ttl }, ttl, genSid : generate_unique_id, store : redis_store ({ client : redis_client }) })) } else { web.use(session ({ key: 'session:id', // ttl, cookie : { maxAge : ttl }, })) } } if (options.parse_post_requests) { // Set up http post request handling. // Usage: this.request.body web.use(body_parser({ formLimit: '100mb' })) } if (options.csrf) { // Cross Site Request Forgery protection // // также: в api client'е при любом запросе выставлять заголовок X-Csrf-Token = csrf token cookie. // // // Cross Site Request Forgery token check // web.use(function* (next) // { // // on login: // import crypto from 'crypto' // const hmac = crypto.createHmac('sha1', configuration.session_secret_keys.first()) // hmac.update(this.session) // this.cookies.set('csrf-token', hmac.digest('hex')) // // // else, if logged in // if (this.get('X-Csrf-Token') !== this.cookies.get('csrf-token')) // { // throw new Errors.Access_denied(`Cross Site Request Forgery token mismatch. Expected "csrf-token" cookie value ${this.cookies.get('csrf-token')} to equal "X-Csrf-Token" header value ${this.get('X-Csrf-Token')}`) // } // }) } if (options.routing) { const router = koa_router() // supports routing // // usage: web.get('/path', parameters => 'Echo') for (let method of ['get', 'put', 'patch', 'post', 'delete']) { // if (web[method]) // { // throw new Error(`Method web.${method}() already exists in this Koa application instance. Cannot override.`) // } result[method] = function(path, action) { // all errors thrown from this middleware will get caught // by the error-catching middleware above router[method](path, function*(next) { const session = this.session const session_id = this.sessionId const destroy_session = () => this.session = null const get_cookie = name => this.cookies.get(name) const set_cookie = (name, value, options) => this.cookies.set(name, value, options) const destroy_cookie = name => { this.cookies.set(name, null) this.cookies.set(name + '.sig', null) } // api call parameters const parameters = { ...this.request.body, ...this.query, ...this.params } // treat empty strings as `undefined`s for (let key of Object.keys(parameters)) { if (parameters[key] === '') { delete parameters[key] } } // add JWT header to http client requests let tokenized_http_client = http_client if (this.jwt) { tokenized_http_client = {} const jwt_header = `Bearer ${this.jwt}` for (let key of Object.keys(http_client)) { tokenized_http_client[key] = function(destination, data, options) { options = options || {} options.headers = options.headers || {} options.headers.Authorization = options.headers.Authorization || jwt_header return http_client[key](destination, data, options) } } } // call the api method action const result = action.bind(this)(parameters, { ip: this.ip, get_cookie, set_cookie, destroy_cookie, session, session_id, destroy_session, user : this.user, authentication_error : this.authentication_error, authentication_token_id : this.jwt_id, secret : options.secret ? web.keys[0] : undefined, http : tokenized_http_client }) // http://habrahabr.ru/company/yandex/blog/265569/ switch (method) { case 'delete': this.status = 204 // nothing to be returned } function postprocess(result) { if (!exists(result)) { return {} } if (!is_object(result) && !Array.isArray(result)) { return { result } } return result } function is_redirect(result) { return is_object(result) && result.redirect && Object.keys(result).length === 1 } const respond = result => { if (is_redirect(result)) { return this.redirect(result.redirect) } this.body = postprocess(result) } if (result instanceof Promise) { yield result.then ( respond, error => { throw error } ) } else { respond(result) } }) } } web.use(router.routes()).use(router.allowedMethods()) } // active Http proxy servers const proxies = [] // server shutting down flag let shut_down = false // in case of maintenance web.use(function*(next) { if (shut_down) { this.status = 503 this.message = 'The server is shutting down for maintenance' } else { yield next } }) result.shut_down = function() { shut_down = true // pending promises const pending = [] // shut down http proxy proxies.forEach(proxy => pending.push(proxy.closeAsync())) // Stops the server from accepting new connections and keeps existing connections. // // The optional callback will be called once the 'close' event occurs. // Unlike that event, it will be called with an Error as its only argument // if the server was not open when it was closed. // pending.push(Promise.promisify(web.close, { context : web })()) return Promise.all(pending) } result.connections = function() { // http_server.getConnections() return Promise.promisify(web.getConnections(), { context : web })() } // // log all errors // web.on('error', function(error, context) // { // log.error(error, context) // }) // if (web.file_upload) // { // throw new Error(`Method web.file_upload() already exists in this Koa application instance. Cannot override.`) // } // can handle file uploads result.file_upload = function({ path = '/', output_folder, root_folder, multiple_files = false }) { web.use(mount(path, file_upload_middleware(output_folder, root_folder, multiple_files, options.log))) } // if (web.errors) // { // throw new Error(`Variable web.errors already exists in this Koa application instance. Cannot override.`) // } // standard Http errors result.errors = { Unauthenticated : custom_error('Unauthenticated', { additional_properties: { http_status_code: 401 } }), Unauthorized : custom_error('Unauthorized', { additional_properties: { http_status_code: 403 } }), Access_denied : custom_error('Access denied', { additional_properties: { http_status_code: 403 } }), Not_found : custom_error('Not found', { additional_properties: { http_status_code: 404 } }), Input_missing : custom_error('Missing input', { additional_properties: { http_status_code: 400 } }), Error : custom_error('Server error', { additional_properties: { http_status_code: 500 } }) } // can serve static files result.serve_static_files = function(url_path, filesystem_path) { // https://github.com/koajs/static web.use(mount(url_path, statics(filesystem_path, { maxAge : 365 * 24 * 60 * 60 // 1 year }))) } // runs http server result.listen = (port, host = '0.0.0.0') => { return new Promise((resolve, reject) => { // the last route - throws not found error web.use(function*() { // throw new Method_not_found() this.status = 404 this.message = `The requested resource not found: ${this.method} ${this.url}` if (this.path !== '/favicon.ico') { log.error(this.message) } }) // http server const http_web_server = http.createServer() // // enable Koa for handling http requests // http_web_server.on('request', web.callback()) // copy-pasted from // https://github.com/koajs/koala/blob/master/lib/app.js // // "Expect: 100-continue" is something related to http request body parsing // http://crypto.pp.ua/2011/02/mexanizm-expectcontinue/ // const koa_callback = web.callback() http_web_server.on('request', koa_callback) http_web_server.on('checkContinue', function(request, response) { // requests with `Expect: 100-continue` request.checkContinue = true koa_callback(request, response) }) http_web_server.listen(port, host, error => { if (error) { return reject(error) } resolve() }) // .on('connection', () => connections++) // .on('close', () => connections--) }) } // mounts middleware at path result.mount = (path, handler) => { web.use(mount(path, handler)) } // exposes Koa .use() function for custom middleware result.use = web.use.bind(web) // can proxy http requests result.proxy = (from, to) => { if (!exists(to)) { to = from from = undefined } const proxy = http_proxy.createProxyServer({}) proxies.push(proxy) // proxy.closeAsync() is used when shutting down the web server Promise.promisifyAll(proxy) function proxy_middleware(to) { return function*(next) { const promise = new Promise((resolve, reject) => { this.res.on('close', () => { reject(new Error(`Http response closed while proxying ${this.url} to ${to}`)) }) this.res.on('finish', () => { resolve() }) // proxy.webAsync() won't work here, // because the last parameter is not a "callback", // it's just an error handler. // https://github.com/nodejitsu/node-http-proxy/issues/951 proxy.web(this.req, this.res, { target: to }, reject) }) yield promise } } if (from) { web.use(mount(from, proxy_middleware(to))) } else { web.use(proxy_middleware(to)) } } // done return result }