一、引言
自从dev环境将node服务注册到前端端口启动,加上之后又对node端打包,还用pm2启动之后。都快忘了,单独启动node端的状态了,在此记录一下
二、package.json及对应的指令
server下当然有package.json以及对应的指令,node运行某文件,index.js内容参考
require('babel-core/register')()
require('babel-polyfill')
process.env.NODE_ENV = process.env.NODE_ENV || 'development'
require('./app')
大概区别呢,就是不能直接使用es6语法,需要引入相关模块之后再使用类似import这种语法,
三、app.js内容可参考
import Koa from 'koa'
import register from './register'
const koa = new Koa()
// register middlewares
const { app, logger } = register(koa)
const port = process.env.PORT || 2333
app.listen(port)
logger.info(`Server [${process.pid}] is listening on ${port}`)
export default app
四、register文件
import path from 'path'
import koaStatic from 'koa-static'
import koaMount from 'koa-mount'
import koaViews from 'koa-views'
import koaSession from 'koa-session'
import { configure, getLogger } from 'log4js'
import logconf from './config/log'
import sessionconf from './config/session'
import { enrichResponse, enrichSession } from './enrich'
import { dynamicRouter, initRouter } from './route'
import sessionStore from './util/store'
// import koaCors from 'koa2-cors'
const webroot = path.join(__dirname, '../client')
const staticroot = path.join(__dirname, '../static')
// configure log4js
configure(logconf)
const logger = getLogger('server')
export default app => {
logger.debug('Registering middlewares for app...')
app.env = process.env.NODE_ENV || app.env
logger.debug('Setting app env to', app.env)
app.keys = ['hcz_web']
sessionconf.store = sessionStore
app.use(koaSession(sessionconf, app))
// app.use(koaCors({ credentials: true }))
// serve pure static assets 一定要有
app.use(koaMount('/static', koaStatic(staticroot)))
if (app.env !== 'development') {
logger.info('Setting packed resources directory', webroot, 'for env', process.env.NODE_ENV)
app.use(koaStatic(webroot))
app.use(koaViews(webroot, { extentions: 'html' }))
}
app.use(enrichResponse)
app.use(enrichSession)
app.use(async (ctx, next) => {
try {
await next()
} catch (e) {
logger.error('Uncaught exception:', e)
ctx.status = 400
ctx.body = 'Error'
}
})
if (app.env === 'development') {
app.use(dynamicRouter)
} else {
initRouter(app)
}
app.use(async ctx => {
if (!ctx.headerSent && app.env !== 'development') {
await ctx.render('index.html')
}
})
logger.debug('Middlewares registering completed\n')
return { app, logger }
}
五、route index的示例
import backendRoute from './backend'
// variables
const routers = [tradeRoute, backendRoute, hczRoute]
export const dynamicRouter = async (ctx, next) => {
if (ctx.path.match(/^\/api\/backend\//)) {
return await require('./backend').default.routes()(ctx, next)
}
await next()
}
export const initRouter = app => {
routers.forEach(route => {
app.use(route.routes(), route.allowedMethods())
})
}
六、具体route的参考
import { _, koaRouter, koaBody, log4js, fetch, dataMask } from '../util'
import proxyConf from '../config/backendProxy'
import { checkLogin, checkBindInfo, decryptToken, verifyToken } from '../middleware/handler'
import decipher from '../middleware/decipher'
// variables
const logger = log4js.getLogger('backendRoute')
const router = koaRouter({ prefix: '/api/backend' })
// const envProxyConf = _.get(proxyConf, process.env.NODE_ENV)
const proxyUrl = _.get(proxyConf[process.env.NODE_ENV], 'target')
router.use(koaBody({ multipart: true }), decipher)
// 获取用户信息之前 先将token解密后,进行token身份验证
router.post('/user.getUser', decryptToken, verifyToken, async ctx => {
logger.info('[BACK] get user info for ip:', ctx.ip)
const userId = _.get(ctx.state, 'decryptToken.aopsid')
_.set(ctx.request.body.requestData, 'userId', userId)
let res = await fetch(`${proxyUrl}.user.getUser`, ctx)
logger.info('[BACK] get user info res', res)
res.data = res.data || {}
res.data.userId = userId
ctx.session.user = res.data
res.data = dataMask(res.data)
logger.debug('[BACK] session-user', ctx.session.user)
res = _.omit(res, ['data.payPassword'])
ctx.body = res
})
// 用户列表页
router.post('/user.list', checkLogin(), async ctx => {
logger.info('[BACK] get Order List for ip:', ctx.ip)
ctx.request.body.requestData = _.omit(ctx.request.body.requestData, ['realName'])
let res = await fetch(`${proxyUrl}.user.list`, ctx)
logger.info('[BACK] get User List res', res)
if (_.isArray(_.get(res, 'data.rows'))) {
res.data.rows = _.map(res.data.rows, (val) => {
return dataMask(val)
})
}
ctx.body = res
})
export default router
七、fetch文件
import { createReadStream } from 'fs'
import _ from 'lodash'
import fetch from 'node-fetch'
import log4js from 'log4js'
import FormData from 'form-data'
const logger = log4js.getLogger("nodeFetch")
const defaultOpt = {
// headers: { 'x-requested-by': 'hcz_web' }
}
const handleReqBody = (ctx, body) => {
if (ctx.is('multipart/form-data')) {
const file = _.get(body, 'files.file')
delete ctx.headers['content-type']
const formData = new FormData()
formData.append('file', createReadStream(file.path))
_.forEach(body.fields, (val, key) => {
formData.append(key, val)
})
return formData
} else {
return _.isObject(body) ? JSON.stringify(body) : body
}
}
export default (url, ctx, options = {}) => new Promise((resolve, reject) => {
let body = _.isEmpty(options.body) ? ctx.request.body : options.body
const headers = _.omit(_.get(ctx.request, 'headers'), ['content-length', 'x-forward-for', 'x-forwarded-for'])
options = _.merge({}, defaultOpt, _.pick(ctx, ['method']), {
headers,
body: handleReqBody(ctx, body)
}, _.omit(options, 'body'))
logger.info('fetch params', url, options)
fetch(url, options)
.then(res => {
const contentType = res.headers.get('contenttype') || res.headers.get('content-type') || res.headers.get('Content-Type')
// logger.debug('--------contentType', contentType)
if (_.startsWith(contentType, 'application/json') || _.startsWith(contentType, 'text/plain')) {
logger.info('fecth application json')
return res.json()
} else if (_.startsWith(contentType, 'text/html')) {
logger.info('fecth text/html')
return res.text()
} else {
logger.info('fecth body', res.body)
return res.body
}
})
.then(formatRes => {
_.includes(url, 'getContent') ? logger.debug('--------fetch res', url, _.omit(formatRes, ['data.pages'])) : logger.debug('--------fetch res', url, formatRes)
resolve(formatRes)
})
.catch(err => {
logger.debug('--------fetch err', url, err)
reject(err)
})
})
至此就可以跑起整个node后台的所有流程了,存档一下~