安装
nmp i fastify @fastify/autoload @fastify/view @fastify/mysql @fastify/static
nmp i ejs fastify-vhost git-http-backend
测试代码 index.js:
const Fastify = require('fastify')
const autoload = require('@fastify/autoload')
const path = require('path')
const app = Fastify({ logger: true });
const vhost = require('fastify-vhost')
// git server
var spawn = require('child_process').spawn;
var gitBackend = require('git-http-backend');
var zlib = require('zlib');
var http = require('http');
var gitAllowIps = '125.120.172.51';
// 注册插件文件夹目录
app.register(autoload, {
dir: path.join(__dirname, 'plugins')
})
// 注册路由文件夹目录
app.register(autoload, {
dir: path.join(__dirname, 'routes'),
dirNameRoutePrefix: false, // lack of prefix will mean no prefix, instead of directory name
routeParams: true
// routes/users/_id/actions.js will be loaded with prefix /users/:id
// routes/__country-__language/actions.js will be loaded with prefix /:country-:language
})
// 注册MVC的视图引擎
app.register(require("@fastify/view"), {
engine: {
ejs: require("ejs"),
},
});
// 注册路由文件夹目录
app.register(require('@fastify/mysql'), {
connectionString: 'mysql://user:password@10.0.4.14:3306/notes'
})
// 添加一个虚拟主机
/*app.register(vhost, {
upstream: 'http://localhost:5003',
host: 'gits.host'
})*/
// 设置静态文件夹目录
app.register(require('@fastify/static'), {
root: path.join(__dirname, 'public'),
prefix: '/public/', // optional: default '/'
//constraints: { host: 'example.com' } // optional: default {}
})
// Declare a route
app.get('/', function handler (request, reply) {
reply.send({ hello: 'world' })
})
// mysql 查询
app.get('/gitIPs', function handler (request, reply) {
app.mysql.query(
'SELECT * FROM notes.gitsip', [],
function onResult (err, result) {
if(result && result[0].val) gitAllowIps = result[0].val;
reply.send(err || gitAllowIps);
}
)
})
// Run the server
app.listen({ port: 5000 }, (err) => {
if (err) {
app.log.error(err)
process.exit(1)
}
})
// 添加git server
app.after(() => {
app.addHook('onRequest', (request, reply, done) => {
var req = request.raw;
var res = reply.raw;
var arg = req.url.split('/')[1];
if(0 !== arg.indexOf('repos')){
// the function to continue with the lifecycle
done();
}else{
var repo = req.url.split('/')[2];
var dir = path.join(__dirname, '..', 'repos', repo);
var reqStream = req.headers['content-encoding'] == 'gzip' ?
req.pipe(zlib.createGunzip()) : req;
let ipAddr = req.headers['x-real-ip'];
//console.log('encoding:', req.headers);
//console.log('dir:', dir);
// 允许ip
if( !ipAddr && -1 == gitAllowIps.indexOf(ipAddr) ){
reply.send({ err: 'Bad Request @' + ipAddr})
return;
}
reqStream.pipe(gitBackend(req.url, function (err, service) {
if (err) return res.end(err + '\n');
res.setHeader('content-type', service.type);
//console.log(service.action, repo, service.fields);
var ps = spawn(service.cmd, service.args.concat(dir));
ps.stdout.pipe(service.createStream()).pipe(ps.stdin);
})).pipe(res);
}
});
});
服务端初始化git仓库
cd ..
mkdir repos
git init repos/falafel.git --bare -q
本地git克隆
git clone http://host/repos/falafel.git