node端后台启动及功能实现

一、引言

自从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后台的所有流程了,存档一下~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值