/** * yohobuy app * @author: xuqi<qi.xu@yoho.cn> * @date: 2016/4/25 */ 'use strict'; const config = require('./config/common'); global.Promise = require('bluebird'); const yohoLib = require('yoho-node-lib'); // 全局注册library yohoLib.global(config); const express = require('express'); const path = require('path'); const compression = require('compression'); const bodyParser = require('body-parser'); const cookieParser = require('cookie-parser'); const moment = require('moment'); const uuid = require('uuid'); const pkg = require('./package.json'); const hbsEvent = require('./config/hbsevent'); const _ = require('lodash'); const stringProcess = require('./utils/string-process'); const app = express(); // 向模板注入变量 switch (app.get('env')) { case 'development': global.devEnv = app.locals.devEnv = true; break; case 'test': global.isTest = app.locals.isTest = true; break; case 'production': global.isProduction = app.locals.isProduction = true; break; default: break; } global.version = app.locals.version = pkg.version; app.locals.startTime = moment().format('YYYYMMDDHH'); app.locals.currentYear = moment().format('YYYY'); const logger = global.yoho.logger; // zookeeper if (config.zookeeperServer) { const monitor = global.yoho.monitorSender; const monitorType = _.get(monitor, 'type.ZOOKEEPER'); require('yoho-zookeeper')(config.zookeeperServer, 'wap', app.locals.wap = {}, false, { onerror: (err) => { monitor.tallyFail(monitorType, { code: err.code, message: err.name }); } }); } // 访问域名层级 app.set('subdomain offset', 3); app.set('etag', false); app.enable('trust proxy'); app.disable('x-powered-by'); // docker验证项目是否正常发布 app.use('/node/status.html', (req, res) => { return res.status(200).end(); }); app.head('*', (req, res) => { res.status(200).end(); }); app.use((req, res, next) => { req.url = stringProcess.decodeURIComponent(req.url) || '/404';// 错误的网址编码重定向404 req.isApmReport = _.get(req.app.locals, 'wap.open.bughd', false); // 把错误上报的开关绑定到上下文,node-lib 库要使用 let isSpider = /spider/i.test(req.get('User-Agent') || ''); if (config.aliasDomains.some(d => d === req.hostname) || isSpider) { // 如果是非m.yohobuy.com域名(无法设置sessionid到cookie域名不同)或是爬虫访问,session降级使用cookiesession req.session = { degrage: true }; } next(); }); // 添加请求上下文 app.use(global.yoho.httpCtx()); // 指定libray目录 global.utils = path.resolve('./utils'); // 访问域名层级 app.set('subdomain offset', 3); app.use(global.yoho.hbs({ extname: '.hbs', defaultLayout: 'layout', layoutsDir: path.join(__dirname, 'doraemon/views'), partialsDir: path.join(__dirname, 'doraemon/views/partial'), views: path.join(__dirname, 'doraemon/views'), helpers: _.assign(global.yoho.helpers, require('./utils/helpers')), cb: hbsEvent.cb })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(compression()); require('./doraemon/middleware/yoho-session')(app); app.use((req, res, next) => { req.user = {}; // 全局的用户数据 req.yoho = {}; // req和res绑定yoho对象,用于传递全局数据, 如req.yoho.channel等 req.app.locals.wap = app.locals.wap; // zookeper对象赋值 // 判断请求是否来自app req.yoho.isMiniApp = /miniProgram/i.test(req.get('User-Agent') || '') || req.query.client_type === 'miniapp'; req.yoho.isNowApp = /yohonow/i.test(req.get('User-Agent') || ''); req.yoho.isMarsApp = /yohomars/i.test(req.get('User-Agent') || ''); req.yoho.isYohoApp = /YohoBuy/i.test(req.get('User-Agent') || ''); req.yoho.isApp = req.yoho.isMiniApp || req.yoho.isNowApp || req.yoho.isMarsApp || req.yoho.isYohoApp || (req.query.app_version && req.query.app_version !== 'false') || (req.query.appVersion && req.query.appVersion !== 'false'); // 独立的 UDID if (!req.cookies.udid || (req.yoho.isApp && req.query.udid)) { let udid = uuid.v4(); if (req.yoho.isApp && req.query.udid) { udid = req.query.udid; } res.cookie('udid', udid, { domain: 'yohobuy.com', expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000) }); req.cookies.udid = udid; } next(); }); function isOpenApmRisk(req) { return _.get(req.app.locals, 'wap.open.apmrisk', false); } // dispatcher try { const tdkUrl = require('./doraemon/middleware/redis-url'); const user = require('./doraemon/middleware/user'); const reqParamsFilter = require('./doraemon/middleware/req-params-filter'); const urlRewrite = require('./doraemon/middleware/url-rewrite'); const subDomain = require('./doraemon/middleware/sub-domain'); const itemNameHandler = require('./doraemon/middleware/item-name-handler'); const setYohoData = require('./doraemon/middleware/set-yoho-data'); const errorHanlder = require('./doraemon/middleware/error-handler'); const setPageInfo = require('./doraemon/middleware/set-pageinfo'); const devtools = require('./doraemon/middleware/devtools'); const layoutTools = require('./doraemon/middleware/layout-tools'); const seo = require('./doraemon/middleware/seo'); const pageCache = require('./doraemon/middleware/page-cache'); const downloadBar = require('./doraemon/middleware/download-bar'); const routeEncode = require('./doraemon/middleware/route-encode'); const ifElseMd = require('./doraemon/middleware/ifElseMd'); const riskManagementApm = require('./doraemon/middleware/risk-management2'); const riskManagement = require('./doraemon/middleware/risk-management'); const statics = require('./doraemon/middleware/statics'); // YOHO 前置中间件 app.use(tdkUrl()); app.use(reqParamsFilter()); app.use(urlRewrite()); app.use(subDomain()); app.use(itemNameHandler); app.use(setYohoData()); app.use(user()); // 请求限制中间件 if (!app.locals.devEnv) { const limiter = require('./doraemon/middleware/limiter'); const limiterApm = require('./doraemon/middleware/limiter/index2'); app.use(ifElseMd(isOpenApmRisk, limiterApm, limiter)); } if (app.locals.devEnv) { app.use(devtools()); } app.use(seo()); app.use(setPageInfo()); app.use(layoutTools()); app.use(pageCache()); app.use(routeEncode.md); app.use(downloadBar()); app.use(ifElseMd(isOpenApmRisk, riskManagementApm(), riskManagement())); app.use(statics(app)); require('./dispatch')(app); app.all('*', errorHanlder.notFound()); // 404 // YOHO 后置中间件 app.use(errorHanlder.serverError()); } catch (err) { logger.error(err); } // listener app.listen(config.port, function() { logger.info('yohobuy start'); hbsEvent.event.on('hbs-complete', () => { process.send && process.send('ready'); logger.info('hbs-all-complete'); if (!process.env.NODE_ENV || process.env.NODE_ENV === 'dev') { let {devHost, port} = require('./config/devtools'); require('request-promise')({ url: `http://${devHost}:${port}/event?action=reload` }).then(() => {}, () =>{}); } }); });