使用athens搭建基于本地文件私仓代理

二维码
| Sep 02, 2020 | 原创

众所周知,athens 是一款比较知名的模块代理开源方案,由微软的团队研发,网上也有很多的教程分享如何使用它部署公司级私仓。

不过今天要聊的是另一个话题,如何使用 athens 访问本地文件系统级私仓。之所以有这样的需求,主要是因为很多公司的内网 git 仓库是无法允许直接连接的。

因此,我们是否可以在本地文件中存放一份项目代码,然后让 athens 直接读取本地文件呢?所以,接下来,我们将尝试改造 athens 项目来支持该特性。

实现思路

整体实现思路也非常简单:根据用户请求的路由中的包名来判断是否是私有项目,如果是,那么尝试到本地某个目录文件系统中获取代码。另外,我们运行一个task脚本,定时更新这个本地私仓项目目录 即可。

和原先直接访问内往 git 仓库逻辑很相似,主要是通过请求路由,判断如果包名是内网域名,则直接提供本地文件目录服务

1. 添加路由,实现本地目录访问

我们需要做的第一步就是,改造 athens项目,添加自定义路由,拦截该路由下所有的请求让其访问本地文件目录,改造 app_proxy.go 文件,添加如下路由:

r.PathPrefix("/git.abc.com/").Handler(privateHandler(c))

// 私有项目
func privateHandler(c *config.Config) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        http.FileServer(http.Dir("/data/private_dir/")).ServeHTTP(w, r)
    }
}

我们增加了一个 git.abc.com 路由匹配,如果访问该路径前缀的所有请求都统一返回 /data/private_dir 目录的备份代码文件。

http.FileServergo 内置的文件系统服务方法,一行代码能够搞定一个基于本地文件服务系统,相当的酸爽。

2. 同步项目到本地目录 {async-task}

接下来我们需要做的是把你需要代理的私仓项目代码同步一份到该目录下即可,但并不是直接拷贝git仓库存放到目录中,而是需要按照 go 模块代理协议构建你的项目目录,即你的项目模块目录必须要求如下几个文件目录的:

gopkg.in
└── redis.v5
    └── @v
        ├── list
        ├── list.lock
        ├── v5.2.9.info
        └── v5.2.9.mod

redis 这个包来举例,你的目录结构需要按如上方式来组织,那么我们怎么来构建这些项目文件呢?有一个取巧的办法。我们知道,当我们使用 go get 命令下载一个包的时候,会在我们本地 ~/go/pkg/mod/cache/download 目录下缓存一份该模块代码,这个目录结构其实就是我们想要的目录结构,如果你表示怀疑,可以自己亲自看看。

我们可以利用这个特性,编写一个脚本,定时执行 go get[包名] 命令,然后利用本地缓存的这份代码作为项目私仓代码即可。

如此,我们便可以快速实现一个基于本地文件目录配置私有项目代理的服务,最后还要记得,作为私仓,一定要设置 GONOSUMDB 变量:

export GOPROXY=your-proxy.server
export GONOSUMDB=git.abc.com