项目需要安装 node 环境,如未安装,请移步 nodejs 官网下载安装
1,新建文件夹,初始化项目
mkdir node-api-demo && cd node-api-demo && mkdir api && mkdir config && mkdir common && touch index.js
npm init
cd api && touch get.js post.js
cd ../config && touch mysql.js
cd ../common && touch connect.js request.js
2,目录结构
├── api
│ ├── get.js // get类型 接口
│ └── post.js // post类型 接口
├── config
│ └── mysql.js // mysql 配置
├── common
│ ├── connect.js // 链接数据库
│ └── request.js // 第三方请求
├── node_modules // 依赖包
├── index.js // 入口
└── package.json
- 安装 koa
// koa
// koa-bodyparser post接口参数转换
// koa-logge 请求日志
// koa-router 路由
npm install -S koa koa-bodyparser koa-logger koa-router
- 安装 mysql
npm install -S mysql
- 安装 request
npm install -S request
入口文件 index.js 代码
'use strict'
const Koa = require('koa')
const app = new Koa()
const bodyParser = require('koa-bodyparser')
const logger = require('koa-logger')
/** 整体请求方式配置基本信息 */
app.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*')
ctx.set('Content-Type', 'application/json')
await next()
})
/** 引入api接口 */
const get = require('./api/get')
const post = require('./api/post')
/** get请求 */
app.use(get.routes(), get.allowedMethods())
/** post请求需要加上 bodyParser */
app.use(bodyParser()).use(gzl.routes(), gzl.allowedMethods())
app.use(bodyParser()).use(post.routes(), post.allowedMethods())
/**
* 请求日志
* methods、url、status、ms
*/
app.use(logger())
/** 项目启动端口 */
const host = 'http://127.0.0.1', port = 3706
/** 启动服务、监听端口 */
app.listen(port, () => {
console.log(`app started at port ${ host }:${ port }`)
})
api/get.js 文件代码
'use strict'
const router = require('koa-router')()
/** 路由模块配置 (前缀) */
router.prefix('/getApi')
router.get('/', async (ctx, next) => {
await next()
/** get 获取参数 ctx.query */
ctx.body = JSON.stringify({
code: 1,
data: ctx.query || {}
})
})
module.exports = router
api/post.js 文件代码
'use strict'
const router = require('koa-router')()
/** 路由模块配置 (前缀) */
router.prefix('/getApi')
router.post('/', async (ctx, next) => {
await next()
ctx.body = {
code: 1,
postParams: ctx.request.body
}
})
module.exports = router
3,使用数据库
配置数据库信息 config/mysql.js 文件代码
'use strict'
module.exports = {
user: 'root',
password: '123456',
database: 'test',
host: 'localhost',
port: 3306
}
链接数据库 common/connect.js 文件代码
'use strict'
const mysql = require('mysql')
const { user, password, database, host, port } = require('../config/mysql')
let pool = mysql.createPool({
user,
password,
database,
host,
port
})
/** 链接数据库操作 */
let query = (sql, values) => {
return new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
if (err) {
reject(err)
} else {
connection.query(sql, values, (err, fields) => {
if (err) reject(err)
else resolve(fields)
/** 释放链接 */
connection.release()
})
}
})
})
}
module.exports = {
query
}
调用 以修改 api/post.js 为例
'use strict'
const router = require('koa-router')()
const { query } = require('.../common/connect')
/** 路由模块配置 (前缀) */
router.prefix('/getApi')
/** 数据库操作 */
const getUser = () => {
return query('select * from user', [])
}
router.post('/', async (ctx, next) => {
await getUser().then(res => {
next()
ctx.body = {
code: 1,
data: res
}
})
})
module.exports = router
4,第三方请求
config/request.js 文件代码
'use strict'
const request = require('request')
/** url参数转换 */
const obj2String = (obj, arr = [], idx = 0) => {
for (let item in obj) {
arr[idx++] = [item, obj[item]]
}
return new URLSearchParams(arr).toString()
}
/** 第三方接口 调用 */
const requestApi = (method = 'get', url, params = null) => {
return new Promise((resolve, reject) => {
if (method === 'get') {
if (params) {
url += '?' + obj2String(params)
}
request.get(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(body)
} else {
reject(error)
}
})
} else {
const option = {
url: url,
method: 'post',
json: true,
headers: {
'Access-Control-Allow-Origin': '*',
'content-type': 'application/json'
},
body: params
}
request(option, function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(body)
} else {
reject(error)
}
})
}
})
}
module.exports = requestApi
调用 example
'use strict'
const requestApi = require('./methods/http')
requestApi('get', 'https://pv.sohu.com/cityjson', { ie: 'utf-8' }).then(res => console.log(res))
5,新建服务启动命令
在 package.json 中的 scripts 对象添加
"start": "node index.js"
6,使用 pm2 管理进程
全局安装 pm2
npm install -g pm2
修改启动脚本
"start": "pm2 start index.js --watch", // 启动程序 + 监听
"reload": "pm2 reload all", // 重启进程
"stop": "pm2 stop all", // 停止进程
"delete": "pm2 delete all" // 删除进程
7,其他
命令测试接口
// get
curl 'http://127.0.0.1:3706/getApi'
// post
curl -d 'username=huawei&password=123456' 'http://127.0.0.1:3706/postApi'
用户登录鉴权
- index.js
- post
// jsonwebtoken
图片上传接口
-
index.js
// 需要用到的依赖包 // koa-body 读取传输的文件 // koa-static 设置静态资源访问 const koaBody = require('koa-body') const path = require('path') const serve = require('koa-static') /**静态资源(服务端) */ app.use(serve(path.join(__dirname, './public/'))) // 注意访问时候不需要加 public /** 整体请求方式配置基本信息 */ app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', '*') ctx.set('Content-Type', 'application/json') let params = Object.assign({}, ctx.request.query, ctx.request.body, ctx.request.files) // 加上了 ctx.request.files ctx.request.header['authorization'] = 'Bearer ' + (params.token || '') await next() }) /** 图片上传配置 */ app.use(koaBody({ multipart: true, // multipart/form-data formidable: { maxFileSize: 200 * 1024 * 1024 // 文件大小阀值 20M } })) const upload = require('./api/upload') app.use(bodyParser()).use(upload.routes(), upload.allowedMethods())
-
upload.js
// string-random 生成随机字段命名文件 const fs = require('fs') const path = require('path') const stringRandom = require('string-random') const { serverName, port } = require('../config/serve') const router = require('koa-router')() router.post('/upload', async (ctx, next) => { const file = ctx.request.files.files const type = file.name.split('.')[1] || 'png' let name = `${ stringRandom(16) }.${ type }` const reader = fs.createReadStream(file.path) const publicPath = '/public' const imgPath = '/images/' let filePath = path.join(__dirname, '..' + publicPath + imgPath + `${ name }`) const upStream = fs.createWriteStream(filePath) reader.pipe(upStream) await next() ctx.body = { code: 1, data: `http://${ serverName }:${ port }${ imgPath }${ name }` } }) module.exports = router