加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
app.js 6.24 KB
一键复制 编辑 原始数据 按行查看 历史
const http = require('http')
const path = require('path')
const fs = require('fs')
const express = require('express')
const favicon = require('serve-favicon')
const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser')
const proxyMiddleware = require('http-proxy-middleware')
const md = new require('markdown-it')()
const opn = require('opn')
const body = require('stream-body')
const config = require('./config')
let app = express()
manufactureInfrastructure([
'public',
'mock/custom',
'mock/json',
'mock/proxy'
])
// allow cross-origin ajax request
app.all('*', (req, res, next) => {
console.log(`[${req.method}] ${req.url} ${new Date()}`)
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
res.header('Access-Control-Allow-Methods','PUT,POST,GET,DELETE,OPTIONS')
next()
})
// proxy api requests
Object.keys(config.proxyTable).forEach(function (context) {
var options = config.proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
options.onProxyRes = (proxyRes, req, res) => {
body.parse(proxyRes, (err, data) => {
const fileName = `${req.url.split('#')[0].split('?')[0].split(/^\//)[1].replace(/\//g, '-')}.json`
fs.writeFile(path.join(__dirname, 'mock', 'proxy', fileName), JSON.stringify(data, null, 2), err => {
if (err) { console.log(err) }
})
})
}
app.use(proxyMiddleware(context, options))
})
// app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
// enable uploading large file
app.use(bodyParser.json({ limit: '100000kb' }))
app.use(bodyParser.urlencoded({
extended: false,
limit: '100000kb'
}))
app.use(cookieParser())
app.use(config.root, express.static(path.join(__dirname, 'public'), {
index: 'index.html',
maxAge: 60 * 60 * 1000
}))
app.get('/readme', (req, res, next) => {
fs.readFile(path.join(__dirname, 'README.md'), (err, data) => {
if (err) {
console.log(err)
return
}
const readme = md.render(data.toString())
res.send(readme)
})
})
// response row json file content
config.jsonTable.forEach(context => {
// 根据路径生成对应的文件名(不含文件后缀)
const fileName = transferPathToFileName(context)
if (!fileName) { return }
// 若config.jsonTable数组中存在尚未建立对应json文件的路径,则创建之,免去手动创建的麻烦
const filePathAndName = path.join(__dirname, 'mock', 'json', `${fileName}.json`)
fs.access(filePathAndName, fs.F_OK, err => {
if (err) {
if (err.code === 'ENOENT') {
fs.writeFile(filePathAndName, '{}', err => {
console.log(err ? `${filePathAndName}文件创建失败!` : `${filePathAndName}文件创建成功!`)
})
} else {
console.log(err)
}
}
})
// 路由配置
app.all(context, (req, res, next) => {
fs.readFile(filePathAndName, (err, data) => {
if (err) {
res.json(err)
return
}
res.json(JSON.parse(data.toString()))
})
})
})
// response custom content
config.customTable.forEach(context => {
// 根据路径生成对应的文件名(不含文件后缀)
const fileName = transferPathToFileName(context)
if (!fileName) { return }
// 若config.jsonTable数组中存在尚未建立对应json文件的路径,则创建之,免去手动创建的麻烦
const filePathAndName = path.join(__dirname, 'mock', 'custom', `${fileName}.js`)
fs.access(filePathAndName, fs.F_OK, err => {
if (err) {
if (err.code === 'ENOENT') {
fs.writeFile(filePathAndName, 'module.exports = (req) => { return {} }', err => {
console.log(err ? `${filePathAndName}文件创建失败!` : `${filePathAndName}文件创建成功!`)
})
} else {
console.log(err)
}
}
})
// 路由配置
app.all(context, (req, res, next) => {
const content = require(filePathAndName)(req)
res.json(content)
})
})
// catch 404 and forward to error handler
app.use((req, res, next) => {
var err = new Error('Not Found')
err.status = 404
next(err)
})
// error handlers (will print stacktrace)
app.use((err, req, res, next) => {
res.status(err.status || 500).json({
message: err.message,
error: err
})
})
app.set('port', config.port)
const server = http.createServer(app)
server.listen(config.port)
server.on('error', onError)
server.on('listening', onListening)
// Event listener for HTTP server "error" event.
function onError (error) {
if (error.syscall !== 'listen') {
throw error
}
const bind = typeof config.port === 'string'
? 'Pipe ' + config.port
: 'Port ' + config.port
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges')
process.exit(1)
break
case 'EADDRINUSE':
console.error(bind + ' is already in use')
process.exit(1)
break
default:
throw error
}
}
// translate '/a/b-d/c#d?q=hello' to 'a-b-d-c'
function transferPathToFileName (path) {
if (!/^\/.*$/.test(path)) {
console.log(`[PATH ERROR]: path should start with symbol '/' instead of your ${path}`)
return false
}
return path.split('#')[0].split(/^\//)[1].replace(/\//g, '-')
}
// 构建项目文件夹
function manufactureInfrastructure (arrPaths) {
arrPaths.forEach(makePathSync)
}
// 代码来源:https://github.com/joehewitt/mkdir/blob/master/lib/mkdir.js
function makePathSync (dirPath, mode) {
dirPath = path.resolve(dirPath)
if (typeof mode === 'undefined') {
mode = parseInt('0777', 8) & (-process.umask())
}
try {
if (!fs.statSync(dirPath).isDirectory()) {
throw new Error(`${dirPath} exists and is not a directory`)
}
} catch (err) {
if (err.code === 'ENOENT') {
makePathSync(path.dirname(dirPath), mode)
fs.mkdirSync(dirPath, mode)
} else {
throw err
}
}
}
// Event listener for HTTP server "listening" event.
function onListening () {
const addr = server.address()
const bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port
console.log(`[MAIN] Listening on ${bind}`)
if (config.showReadMe) {
opn(`http://localhost:${config.port}/readme`)
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化