'use strict'; let PORT = 3000; let Koa = require('koa'), Serve = require('koa-serve'), Fs = require('fs'); let app = Koa(); app.use(Serve('src')); app.use(Serve('node_modules')); app.use(function *(next){ var start = new Date; yield next; var ms = new Date - start; this.set('X-Response-Time', ms + 'ms'); }); app.use(function *(){ this.body = Fs.readFileSync('index.html', 'utf-8'); }); app.listen(PORT); console.log(` o-------o /| /| / | / | o-|----o | | o----|--o
return new Promise(function startPromise(resolve) { /* istanbul ignore if */ if (cluster.isMaster) { lifecycleHook("onBeforeClusterFork"); for (let i = 0, c = cpuCount; i < c; i++) { cluster.fork(); } cluster.on("exit", function clusterExit(worker, code, signal) { logger.warn(`worker ${worker.process.pid} has died (code: ${code}) (signal: ${signal})`); }); resolve({ clusterForksCount: cpuCount }); } else { lifecycleHook("onWorkerStart"); const app = koa(); lifecycleHook("onStart"); // enable cors app.use(cors({ origin: function origin(ctx) { for (let i = 0, j = allowedOrigins.length; i < j; i++) { const allowedOrigin = allowedOrigins[i]; const hostname = ctx.header.host.split(":")[0]; /* istanbul ignore else */ if (hostname.includes(allowedOrigin)) { return "*"; } } /* istanbul ignore next */ return false; } })); // add gzip app.use(compress()); app.use(morgan.middleware(":id :status :method :url :res[content-length] - :response-time ms", morganOptions)); if (!__PROD__ || __TEST__) { app.use(babelDevTranspiler(cwd, { babelOptions, binDir: serverSettings.binDir, coverage: generalSettings.coverage, coverageSettings: generalSettings.coverageSettings, extensions: [".es6", ".js", ".es", ".jsx"], logger, logLevel: generalSettings.logLevel, origin: generalSettings.staticUrl, outDir: serverSettings.publicDir, sourceDir: serverSettings.sourceDir, minify: serverSettings.minifyTranspilerOutput, minifySettings: serverSettings.minifySettings })); } // serve statics app.use(fileServer); let serverType; switch (staticServerSettings.protocol) { case "http2": serverType = http2; break; case "https": serverType = https; break; case "http": default: serverType = http; break; } // Stop Limiting Your Connections with Default MaxSockets Value // http://webapplog.com/seven-things-you-should-stop-doing-with-node-js/ (serverType.globalAgent || https.globalAgent).maxSockets = Infinity; if (staticServerSettings.protocol === "http") { server = serverType.createServer(app.callback()); } else { server = serverType.createServer(secureSettings, app.callback()); } if (!__PROD__) { const startWebSocketServer = require("./utils/startWebSocketServer"); startWebSocketServer(cwd, { cache: fileServer.cache, server, watchOptions: { awaitWriteFinish: { pollInterval: 100, stabilityThreshold: 250 }, ignored: /\.(git|gz|map)|node_modules|jspm_packages|src/, ignoreInitial: true, persistent: true } }); } server.listen(port, function serverListener() { /* istanbul ignore else */ if (cluster.worker.id === cpuCount) { if (__PROD__) { logger.ok("Static server is running"); } else { logger.ok(`Static server is running at ${generalSettings.staticUrl}`); } lifecycleHook("onAfterStart"); resolve({ env: process.env.NODE_ENV, server }); } }); } });
// --- Require Dependencies ---------------------------------------------------- var http = require('http'); var fs = require('fs'); var io = require('socket.io'); var config = require('config'); var koa = require('koa'); var serve = require('koa-static'); var bodyParser = require('koa-body-parser'); // --- Setup Koa --------------------------------------------------------------- var app = koa(); app.use(bodyParser()); app.use(serve('./client')); // --- Setup Routes ------------------------------------------------------------ fs.readdirSync(__dirname + '/routes').forEach(function (filename) { if (filename[0] === '.') return; require('./routes/' + filename)(app); }); var server = http.Server(app.callback()); // --- Setup Sockets ----------------------------------------------------------- io = io(server);
const koa = require('koa'); const app = module.exports = koa(); const serve = require('koa-static'); const path = require('path'); // Serve static files app.use(serve(path.join(__dirname, 'public'))); if (!module.parent) { app.listen(2999); console.log('listening on port 2999'); }
// 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 }
//server.js import koa from 'koa'; import schema from './schema'; import { graphql } from 'graphql'; import bodyParser from 'koa-bodyparser'; let app = koa(); let PORT = 3000; // Parse post content as text app.use(bodyParser({ extendTypes: { text: 'application/graphql' } })); let router = require('koa-router')(); router .get('/', function *(){ //GraphQL executor this.body = yield graphql(schema, this.query.graphql) .then((result) => { return JSON.stringify(result, null, 2); }); }) .post('/', function *(){ this.body = yield graphql(schema, this.request.body.graphql) .then((result) => { return JSON.stringify(result, null, 2);
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'), //router = require('koa-route'), //static = require('koa-static'), staticCache = require('koa-static-cache'), swig = require('swig'), app = koa(), path = require('path'), // co = require('co'), parse = require('co-body'), views = require('co-views'), compose = require('koa-compose'), mongoose = require('mongoose'), _ = require('underscore'); //===================获取配置内容 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()); } //===================定义模版类型以及路径 /*swig.setDefaults({ autoescape:false });*/ var render = views(C.view, { map: { html: 'swig' } }) //定义静态模版以及路径 //app.use(static(path.join(root, 'static'))); app.use(staticCache(path.join(root, 'static'), { maxAge: 365 * 24 * 60 * 60 })) //公共函数定义 合并 underscore var styleFn = require(kpath + '/function/init')(kpath); F = _; F.extend(F,styleFn); //连接数据库 M.mongoose = mongoose; M.mongoose.connect(C.mongo); D = require(C.model + 'db'); //密钥 app.keys = [C.secret]; //全局函数 app.use(function*(next) { var mod = C.default_mod; R.method = this.request.method; R.url = this.request.url.split('?')[0]; if(R.url!='/favicon.ico'){ R.url = R.url.split('/'); //默认值处理 R.m = R.url[1]||mod[0];//module R.c = R.url[2]||mod[1];//controller R.a = R.url[3]||mod[2];//action if(R.url.length>4){ var d= meregeRq(R.url); this.query = this.query&&_.extend(this.query,d)||d; } if(!C.debug.logger){ try{ var cm = require(kpath+'middleLoad.js')(this,render,parse); // :TODO 探究如何判断是否是新函数 yield cm.init(); if(_.isFunction(cm[R.a])){ yield cm[R.a](); }else{ yield next; } }catch (e){ console.log(e); yield next; } }else{ var cm = require(kpath+'middleLoad.js')(this,render,parse); // :TODO 探究如何判断是否是新函数 yield cm.init(); if(_.isFunction(cm[R.a])){ yield cm[R.a](); }else{ yield next; } } } }); //指定路由请求 //:TODO 与配置路由相结合 function meregeRq(url,query){ var d={}; for (var i = 2; i < Math.ceil(url.length / 2); i++) { d[url[i * 2]] = url[i * 2 + 1]||''; } return d = d||''; } //404页面 app.use(function *pageNotFound(next){ this.body = yield render('404'); }); /** * 监听端口 */ app.listen(C.port); console.log('listening on port ' + C.port); /** * 错误处理 */ app.on('error', function (err) { log.error('server error', err); }); }
const koa = require('koa'), expect = require('expect'), uncapitalize = require('../'), app = koa(); app.use(uncapitalize); app.use(function *(next) { if (this.path.toLowerCase() != '/test') { return yield next; } this.body = "OK"; }); const request = require('supertest').agent(app.listen()); describe('koa uncapitalize', function() { describe('lowercase routes', function() { it('should not redirect', function(done) { request.get('/test').expect(200, done); }); }); describe('uppercase routes', function() { it('should redirect', function(done) { request.get('/TEST').expect(301, done); }); }); });
it('should recieve multiple fields and files via `multipart` on .body.files object', function (done) { var app = koa(); var usersResource = new Resource('users', { // POST /users create: function *(next) { this.status = 201; this.body = this.request.body; } }); app.use(koaBody({ multipart: true, formidable: { uploadDir: __dirname + '/temp' } })); app.use(usersResource.middleware()); request(http.createServer(app.callback())) .post('/users') .type('multipart/form-data') .field('names', 'John') .field('names', 'Paul') .attach('firstField', 'package.json') .attach('secondField', 'index.js') .attach('secondField', 'package.json') .attach('thirdField', 'LICENSE') .attach('thirdField', 'README.md') .attach('thirdField', 'package.json') .expect(201) .end(function(err, res){ if (err) return done(err); console.log(res.body.files); res.body.fields.names.should.be.an.Array().and.have.lengthOf(2); res.body.fields.names[0].should.equal('John'); res.body.fields.names[1].should.equal('Paul'); res.body.files.firstField.should.be.an.Object; res.body.files.firstField.name.should.equal('package.json'); should(fs.statSync(res.body.files.firstField.path)).be.ok; fs.unlinkSync(res.body.files.firstField.path); res.body.files.secondField.should.be.an.Array().and.have.lengthOf(2); res.body.files.secondField.should.containDeep([{ name: 'index.js' }]); res.body.files.secondField.should.containDeep([{ name: 'package.json' }]); should(fs.statSync(res.body.files.secondField[0].path)).be.ok; should(fs.statSync(res.body.files.secondField[1].path)).be.ok; fs.unlinkSync(res.body.files.secondField[0].path); fs.unlinkSync(res.body.files.secondField[1].path); res.body.files.thirdField.should.be.an.Array().and.have.lengthOf(3); res.body.files.thirdField.should.containDeep([{ name: 'LICENSE' }]); res.body.files.thirdField.should.containDeep([{ name: 'README.md' }]); res.body.files.thirdField.should.containDeep([{ name: 'package.json' }]); should(fs.statSync(res.body.files.thirdField[0].path)).be.ok; fs.unlinkSync(res.body.files.thirdField[0].path); should(fs.statSync(res.body.files.thirdField[1].path)).be.ok; fs.unlinkSync(res.body.files.thirdField[1].path); should(fs.statSync(res.body.files.thirdField[2].path)).be.ok; fs.unlinkSync(res.body.files.thirdField[2].path); done(); }); });
function createWebApp(options) { options = Object.assign( {}, DEFAULT_OPTIONS, options ); debug('options %j (keys only)', Object.keys(options)); const serviceRegistry = options.serviceRegistry; const koaServer = createKoaServer(); const webServer = http.createServer(); koaServer.context = Object.create(koaServer.context, { services: { enumerable: true, get() { return serviceRegistry; }, }, }); const stopWebServer = function* stopWebServer() { yield done => webServer.close(done); }; const startWebServer = function* startWebServer() { yield done => webServer.listen(options.port, options.host, done); }; const initializeApplication = function* initializeApplication() { yield serviceRegistry.initialize(); webServer.on('request', koaServer.callback()); }; const destroyApplication = function* destroyApplication() { yield stopWebServer(); }; const app = { get services() { return serviceRegistry; }, *initialize() { yield initializeApplication(); }, *destroy() { yield destroyApplication(); }, *start() { yield startWebServer(); }, *stop() { yield stopWebServer(); }, useMiddleware(mw) { koaServer.use(mw); }, }; const userRouter = createUserRouter(); const middleware = [ createPager(options.pager), createBodyParser(), createJwtParser(options.jwtParser), createUserInflatter(), userRouter.allowedMethods(), userRouter.routes(), ]; middleware.forEach(app.useMiddleware); return app; }
"use strict"; const koa = require('koa'), route = require('koa-route'), websockify = require('../'); const app = websockify(koa()); // Note it's app.ws.use and not app.use app.ws.use(route.all('/test/:id', function* (next) { // `this` is the socket passed from WebSocketServer to connection listeners this.send('Hello World'); this.on('message', function(message) { // do something with the message from client }); // yielding `next` will pass the socket on to the next ws middleware })); app.listen(3000);
import manifest from '../package.json'; import request from 'request-promise'; import debug from 'debug'; import koa from 'koa'; import serve from 'koa-static'; import logger from 'koa-logger'; import jsonBody from 'koa-json-body'; import session from 'koa-generic-session'; import redis from 'koa-redis'; import mount from 'koa-mount'; import proxy from 'koa-proxy'; const server = koa(); const log = debug('fou:server'); // Meta server.name = manifest.name; server.keys = process.env.FRONTEND_SESSION_KEYS ? process.env.FRONTEND_SESSION_KEYS.split(',') : ['123']; // Log requests server.use(logger()); // Serve files from the public folder const publicPath = __DEV__ ? './public' : './dist/public'; log('serving from %s', publicPath); server.use(serve(publicPath, { defer: false })); // Session config server.use(session({ store: process.env.FRONTEND_REDIS_HOST ? redis({
'use strict'; const koa = require('koa'); const path = require('path'); const koaApp = module.exports = koa(); const config = require('../../config'); const App = require('boar-server').app; const app = new App(koaApp); app.addBodyParseMiddleware({ jsonLimit: '100mb' }); app.addCorsSupportMiddleware(); app.addDynamicViewMiddleware(path.join(config.root, 'views'), true); app.loadControllers(path.join(config.root, 'controllers')); if (!module.parent) { app.listen(config.port); }
describe('DeploymentController', ()=> { const app = koa(); let consul, deploy, promote; before(() => { app.use(function*(next) { this.deploy = deploy; this.promote = promote; this.consul = consul; yield next; }); app.use(bodyParser()); app.use(deploymentController); }); describe('POST /deploy', () => { it('should throw if token is not valid', (done) => { request(app.listen()) .post('/deployments/deploy') .expect(403, done); }); it('should throw if text is not provided', (done) => { request(app.listen()) .post('/deployments/deploy') .send('token=token') .expect(400, done); }); it('should throw if text is not provided properly', (done) => { request(app.listen()) .post('/deployments/deploy') .send('token=token') .send('text=a b') .expect(400, done); }); it('should throw if canaray is already in use', (done) => { consul = { kv: { get: (key) => { return new Promise((resolve, reject) => { return resolve({Key: key, Value: '{"testing": true}'}); }); } } } request(app.listen()) .post('/deployments/deploy') .send('token=token') .send('text=a b c') .expect(400, done); }); it('should call deploy on success', (done) => { consul = { kv: { get: (key) => { return new Promise((resolve, reject) => { return resolve(); }); } }, catalog: { service: { nodes: (val) => { return new Promise((resolve, reject) => { return resolve(); }); } } } } deploy = sinon.spy(); request(app.listen()) .post('/deployments/deploy') .send('token=token') .send('text=a b c') .expect(200, (err, res) => { expect(err).to.not.exist; expect(deploy.calledOnce).to.be.true; done(); }); }); }); });
function Grant (_config) { var app = koa() app.config = config.init(_config) app._config = config app.use(route.all('/connect/:provider/:override?', function *(provider, override, next) { if (!this.session) { throw new Error('Grant: mount session middleware first') } if (this.method === 'POST' && !this.request.body) { throw new Error('Grant: mount body parser middleware first') } yield next })) app.use(route.get('/connect/:provider/:override?', function *(provider, override) { if (override === 'callback') { yield callback return } this.session.grant = { provider: provider } if (override) { this.session.grant.override = override } if (Object.keys(this.request.query || {}).length) { this.session.grant.dynamic = this.request.query } yield connect })) app.use(route.post('/connect/:provider/:override?', function *(provider, override) { this.session.grant = { provider: provider } if (override) { this.session.grant.override = override } if (Object.keys(this.request.body || {}).length) { this.session.grant.dynamic = this.request.body } yield connect })) function* connect () { var grant = this.session.grant var provider = config.provider(app.config, grant) var flow = flows[provider.oauth] var callback = function (err, url) { var path = (provider.callback || '') if (err) { if (path) { this.response.redirect(path + '?' + err) } else { this.body = err } } else { this.response.redirect(url) } }.bind(this) if (provider.oauth === 1) { try { grant.step1 = yield flow.step1(provider) var url = flow.step2(provider, grant.step1) var err = !/^http|\//.test(url) ? url : null callback(err, url) } catch (err) { callback(err) } } else if (provider.oauth === 2) { grant.state = provider.state var url = flow.step1(provider) callback(null, url) } else if (flow) { try { grant.step1 = yield flow.step1(provider) var url = flow.step2(provider, grant.step1) callback(null, url) } catch (err) { callback(err) } } else { var err = {error: 'Grant: missing or misconfigured provider'} callback(qs.stringify(err)) } } function* callback () { var grant = this.session.grant || {} var provider = config.provider(app.config, grant) var flow = flows[provider.oauth] var callback = function (err, response) { var path = (provider.callback || '') if (err) { if (path) { this.response.redirect(path + '?' + err) } else { this.body = err } } else if (!provider.transport || provider.transport === 'querystring') { this.response.redirect(path + '?' + response) } else if (provider.transport === 'session') { this.session.grant.response = qs.parse(response) this.response.redirect(path) } }.bind(this) if (provider.oauth === 1) { try { var response = yield flow.step3(provider, grant.step1, this.query) callback(null, response) } catch (err) { callback(err) } } else if (provider.oauth === 2) { try { var data = yield flow.step2(provider, this.query, grant) var response = flow.step3(provider, data) callback(null, response) } catch (err) { callback(err) } } else if (flow) { try { var response = yield flow.step3(provider, grant.step1) callback(null, response) } catch (err) { callback(err) } } else { var err = {error: 'Grant: missing session or misconfigured provider'} callback(qs.stringify(err)) } } return app }
describe('seneca-user-koa', function() { var ctx = { session: {}, state: {} }; var senecaActStub = sinon.stub(); var senecaMock = { actAsync: senecaActStub }; var app = koa().use(senecaUserKoa(senecaMock)); senecaActStub.returns(Promise.resolve({})); var testRouter = router() .get('/user/current', function * (next) { this.session = ctx.session; this.state = ctx.state; yield next; }); var superApp = koa() .use(testRouter.routes()) .use(mount('/', app)); superApp.keys = ['test']; describe('GET /user/current', function() { it('should give a 401 when there is no JWT', function(done) { ctx.state = {}; request(superApp.listen()) .get('/user/current') .expect(401) .end(done); }); it('should call seneca with the correct system and action', function(done) { ctx.state = { jwt: { sub: 'SUB1' } }; senecaActStub.reset(); senecaActStub.returns({ success: false }); request(superApp.listen()) .get('/user/current') .end(function() { expect(senecaActStub.args[0][0].system).to.equal('user'); expect(senecaActStub.args[0][0].action).to.equal('get'); done(); }); }); it('should call seneca with the user id from the JWT', function(done) { ctx.state = { jwt: { sub: 'SUB2' } }; senecaActStub.reset(); senecaActStub.returns({ success: false }); request(superApp.listen()) .get('/user/current') .end(function() { expect(senecaActStub.args[0][0].id).to.equal('SUB2'); done(); }); }); it('should give a 500 when the seneca response does not indicate success', function(done) { ctx.state = { jwt: { sub: 'SUB1' } }; senecaActStub.reset(); senecaActStub.returns({success: false}); request(superApp.listen()) .get('/user/current') .expect(500) .end(done); }); it('should return the seneca response when successful', function(done) { ctx.state = { jwt: { sub: 'SUB1' } }; senecaActStub.reset(); senecaActStub.returns({ success: true, result: 'TEST' }); request(superApp.listen()) .get('/user/current') .expect(200) .end(function(err, res) { expect(res.body.result).to.equal('TEST'); done(); }); }); }); });
var fs = require('fs') var crypto = require('crypto') var zlib = require('zlib') var request = require('supertest') var koa = require('koa') var http = require('http') var path = require('path') var staticCache = require('..') var app = koa() var files = {} app.use(staticCache(path.join(__dirname, '..'), { alias: { '/package': '/package.json' } }, files)) // force the files' mtime for (var key in files) { files[key].mtime = new Date().toUTCString() } var server = http.createServer(app.callback()) var app2 = koa() app2.use(staticCache(path.join(__dirname, '..'), { buffer: true })) var server2 = http.createServer(app2.callback()) var app3 = koa() app3.use(staticCache(path.join(__dirname, '..'), {
var Server = function Server() { var self = this this.app = koa() this.app.keys = ['m0j1gr@m'] this.app.use(koa_logger()) if (config.get('env') === 'development') { // So we can use koa-gzip as a npm devDependency. var koa_gzip = require('koa-gzip') this.app.use(koa_gzip()) } this.app.use(koa_body_parser()) this.app.use(koa_static(static_folder_name, {maxage: 1000 * 60 * 60 * 24 * 365})) this.app.use(koa_session({ expires: (new Moment()).add(10, 'year').toDate() })) this.app.use(function * (next) { console.log('method', this.request.method) console.log('url', this.request.url) console.log('header', this.request.header) console.log('session', this.session) console.log('body', this.request.body) yield next }) this.app.use(function * (next) { this.request.body = this.request.body || {} this.request.query = this.request.query || {} yield next }) this.app.use(koa_trie_router(this.app)) // API routes this.app.route('/_/api/account').post(AccountHTTPService.post()) this.app.route('/_/api/account/:id').get(AccountHTTPService.get()) this.app.route('/_/api/account/:id').put(AccountHTTPService.put()) this.app.route('/_/api/session').post(SessionHTTPService.post()) this.app.route('/_/api/session').del(SessionHTTPService.del()) this.app.route('/_/api/asset').post(AssetHTTPService.post()) this.app.route('/_/api/emoji_collection').post(EmojiCollectionHTTPService.post()) this.app.route('/_/api/emoji_collection').get(EmojiCollectionHTTPService.list()) this.app.route('/_/api/emoji_collection/:id').put(EmojiCollectionHTTPService.put()) this.app.route('/_/api/emoji_collection/:id').get(EmojiCollectionHTTPService.get()) this.app.route('/_/api/emoji_collection/:id').del(EmojiCollectionHTTPService.del()) this.app.route('/_/api/emoji').post(EmojiHTTPService.post()) this.app.route('/_/api/emoji').get(EmojiHTTPService.list()) // this.app.route('/_/api/emoji/:id').put(EmojiHTTPService.put()) this.app.route('/_/api/emoji/:id').get(EmojiHTTPService.get()) this.app.route('/_/api/emoji/:id').del(EmojiHTTPService.del()) this.app.route('/_/api/search').get(SearchHTTPService.list()) this.app.route('/_/api/featured').get(FeaturedHTTPService.list()) this.app.route('/_/api/event').post(EventHTTPService.post()) this.app.route('/_/api/emoji_collection_follower').post(EmojiCollectionFollowerHTTPService.post()) this.app.route('/_/api/emoji_collection_follower').get(EmojiCollectionFollowerHTTPService.list()) this.app.route('/_/api/emoji_collection_follower/:id').get(EmojiCollectionFollowerHTTPService.get()) this.app.route('/_/api/emoji_collection_follower/:id').del(EmojiCollectionFollowerHTTPService.del()) this.app.route('/tos').get(HomeHTTPService.tos()) this.app.route('/privacy').get(HomeHTTPService.tos()) // URL routes routes.forEach(function(route_config) { self.app.route(route_config.route).get(HomeHTTPService.get()) }) }
'use strict'; const koa = require('koa'); const router = require('koa-router')(); const rp = require('request-promise'); const main = koa(); router.get('/', function* () { this.body = yield this.render('Home', { props: { cheers: 'toto' }, }); }); router.get('/deputes', function* () { const deputes = yield rp('http://localhost:4001/api/v1/elus?limit=30').then(json => { return JSON.parse(json); }); this.body = yield this.render('Deputes', { props: { deputes: deputes }, scripts: ['https://maps.googleapis.com/maps/api/js'], }); }); router.get('/services/:id', function* () { this.body = yield this.render('Service', { props: { serviceId: this.params.id } }); }); main.use(router.routes())
/** * initializes koa-swagger-editor * @param {Object} options The options object * @param {String} options.statics The path to the swagger-editor directory, where index.html is located * @param {String} options.specFile The file path which is used to read/write our api specs * @param {String} [options.path='/'] The url mount path * @param {Object} [options.defaults={}] The options object for swagger-editor. Here you can override any settings from swagger-editor/config/defaults.json * @param {boolean} [options.defaults.useYamlBackend=true] Right now its hardcoded true and you are not able to change this, because swagger-editor has some problems with json * @param {boolean} [options.defaults.useBackendForStorage=true] This is true by default, otherwise i would say you are using this extension without reason * @param {String} [options.specURL] The URL used by swagger-editor to read/write the specs. Default is the same as in swagger-editor/config/defaults.json:backendEndpoint * @returns {any} koa-mount The koa generator */ function init(options) { if (!options) { throw new Error('missing options'); } options.path = options.path || '/'; if (!options.statics) { throw new Error('path to statics directory is required'); } try { const staticStat = fs.statSync(options.statics); if (!staticStat.isDirectory()) { throw new Error(); } } catch (e) { throw new Error('cannot read/access statics directory: ' + options.statics); } let configDefaults = {}; try { configDefaults = JSON.parse(fs.readFileSync(path.resolve(options.statics + '/config/defaults.json'))); } catch (e) { throw new Error('cannot read/access config defaults.json'); } if (!options.specFile) { throw new Error('filepath for spec is required'); } // If not, this module would make no sense configDefaults.useBackendForStorage = true; if (!options.specURL) { options.specURL = configDefaults.backendEndpoint; } else { configDefaults.backendEndpoint = options.specURL; } if (!options.defaults || options.defaults.useYamlBackend !== false) { configDefaults.useYamlBackend = true; } let apiRoute = require('./api')(options); let koaRouter = router() .get('/config/defaults.json', swaggerDefaults); let koaApp = koa() .use(checkPath) .use(serve(options.statics, { defer: true })) .use(koaRouter.routes()) .use(apiRoute.routes()); return mount(options.path, koaApp); /** * Serve swagger default settings with current options.defaults * @param {Function} next The next generator in koa`s chain * @returns {any} anything returned by next or undefined * @this koa */ function* swaggerDefaults(next) { this.body = Object.assign({}, configDefaults); if (options.defaults) { Object.assign(this.body, options.defaults); } // right now swagger-editor fails with json, use yaml only this.body.useYamlBackend = true; return yield next; } /** * checkPath function redirect all swagger requests w/o trailing slash * @param {Function} next The next generator in koa`s chain * @returns {any} anything returned by next or undefined * @this koa */ function* checkPath(next) { // koa statics use root url w/o trailing slash if (this.originalUrl === options.path && this.originalUrl[options.path.length - 1] !== '/') { this.redirect(this.originalUrl + '/'); } return yield next; } }
var limit = require('./index'); var request = require('supertest'); var http = require('http'); function helloMiddleware() { return function * hello(next) { this.response.type = 'text/html' this.response.body = '<p>Hello test.</p>'; yield * next; } } /** * appNonDefault description */ var appNonDefault = koa(); appNonDefault.use(limit({ duration: 1000 * 60, //1 min max: 3, //max requests env: 'test' })); appNonDefault.use(helloMiddleware()); appNonDefault = http.createServer(appNonDefault.callback()); /** * appBlack description */ var appBlack = koa(); appBlack.use(limit({ blackList: ['4.4.1.*'], accessForbidden: 'access forbidden, please contact foo@bar.com',
import lodash from 'lodash/index' import ramda from 'ramda/dist/ramda' import { isBrowser } from 'app/utils/predicates' import { makeCreateStore } from 'app/services/makeCreateStore' import rootReducer from 'app/modules/reducers' import promiseMiddleware from 'redux-promise-middleware' import thunkMiddleware from 'redux-thunk' chai.use(require('chai-shallow-deep-equal')) chai.use(require('chai-as-promised')) chai.use(require('sinon-chai')) chai.use(require('chai-enzyme')) const helpers = { cloneApp(app) { const clone = koa() clone.keys = lodash.clone(app.keys) clone.middleware = lodash.clone(app.middleware) return clone }, createStore(initialState={}) { return makeCreateStore([ promiseMiddleware, thunkMiddleware, ])(rootReducer, initialState) }, } setGlobals(isBrowser ? window : GLOBAL) function setGlobals(global) {
var path = require('path'); var koa = require('koa'); var appForHtml = koa(); var appForStatic = koa(); var logger = require('koa-logger'); // var error = require('koa-error'); var compress = require('koa-compress'); var serve = require('koa-static'); var proxy = require('koa-proxy'); var router = require('./router'); var config = require('./config'); var ports = config.ports; var proxyConfig = config.proxy; // ---------------------------------------------------------------------------- HTML服务 // 日志 appForHtml.use(logger()); // 错误打印 // appForHtml.use(error({ // engine: 'ejs', // template: path.resolve('build/error.ejs'), // cache: process.env !== 'development' // })); // 压缩服务 appForHtml.use(compress({ flush: require('zlib').Z_SYNC_FLUSH }));
var koa = require('koa') , backend = require('koa-backend') , bodyParser = require('koa-bodyparser') , validator = require('koa-validator') , views = require('koa-views') , passport = require('koa-passport') , app = koa() ; module.exports = app .use(bodyParser()) .use(validator()) .use(views('./views', { default: 'swig' , cache: 'memory' })) .use(passport.initialize()) .use(backend(app, __dirname + '/paths')) ;
const config = require('./config/environment'), koaConfig = require('./config/koa'), co = require('co'), koa = require('koa'), app = koa(), mongoose = require('mongoose'); module.exports = app; /** * Initializes koa server. Returns a promise. */ app.init = () => { // connect to mongo mongoose.connect('mongodb://localhost/nautilus'); // set up koa koaConfig(app); // lift server app.server = app.listen(config.app.port); if (config.app.env !== 'test') { console.log('Koa server up on port ' + config.app.port); } }; // auto init if this app is not being initialized by another module (i.e. using require('./app').init();) if (!module.parent) { try { app.init(); } catch (err) { console.error(err);
function middleware (fn) { return koa().use(fn).use(helloWorld()).callback() }
/** * This example simply sets the number of views from the same client * both as a cookie and as a response string. */ var koa = require('koa'); var app = module.exports = koa(); app.use(function *(){ var n = ~~this.cookies.get('view') + 1; this.cookies.set('view', n); this.body = n + ' views'; }); if (!module.parent) app.listen(3000);
'use strict' const Koa = require( 'koa' ) const Config = require( 'config' ) var app = Koa() app.use( function *() { this.body = 'Hello world' yield }) app.listen( Config.get( 'server.port' ) )
"use strict"; const koa = require("koa"); const path = require("path"); const logger = require("koa-logger"); const route = require("koa-route"); const app = koa(); const db = { article: { id: 1, name: "hey" } }; app.use(logger()); app.use(route.get("/test", function* () { this.type = "application/json"; this.body = JSON.stringify(db); })); app.on("error", err => { console.log("sent error %s to the cloud", err.message); console.log(err); }); app.listen(3001);
return new Promise(function startPromise(resolve) { const app = koa(); app.use(morgan.middleware(":id :status :method :url :res[content-length] - :response-time ms", morganOptions)); // enable cors app.use(cors()); // use conditional upstream from etag so that they are present app.use(conditional()); // add etags app.use(etag()); // add gzip app.use(compress()); // Handle the pesky favicon app.use(favicon(path.join(cwd, "favicon.ico"))); Object.keys(proxySettings).forEach(function eachProxyRoute(proxyRoute) { const host = proxySettings[proxyRoute]; logger.meta(`Proxy: ${proxyRoute} -> ${host}`); /* istanbul ignore next */ app.use(proxy({ host, map: (hostPath) => hostPath.replace(proxyRoute, ""), match: proxyRoute })); }); app.use(renderReactWithJspm(cwd, { wildcatConfig })); var serverType; switch (appServerSettings.protocol) { case "http2": serverType = http2; break; case "https": serverType = https; break; case "http": default: serverType = http; break; } // Stop Limiting Your Connections with Default MaxSockets Value // http://webapplog.com/seven-things-you-should-stop-doing-with-node-js/ (serverType.globalAgent || https.globalAgent).maxSockets = Infinity; if (appServerSettings.protocol === "http") { server = serverType.createServer(app.callback()); } else { server = serverType.createServer(secureSettings, app.callback()); } server.listen(port, function serverListener() { /* istanbul ignore else */ if (cluster.worker.id === cpuCount) { if (__PROD__) { logger.ok(`Node server is running on pid`, process.pid); } else { logger.ok(`Node server is running at ${generalSettings.originUrl} on pid`, process.pid); } resolve({ env: process.env.NODE_ENV, server }); } }); });