Go-Get 原理
不论是否开启Go Module
功能,go get
从版本控制系统VCS
中取包的基础过程是类似的。假设依赖包github.com/liujianping/foo
不在本地,需要通过go get
获取。发起以下命令:
go get github.com/liujianping/foo
正则匹配出依赖包的查询路径
go get
可以指定具体包的import
路径或者通过其自行分析代码中的import
得出需要获取包的路径。但是import
路径,并不直接就是该包的查询路径。在go get
的源码实现中,包的查询路径是通过一组正则匹配出来的。也就是说,import
路径是必须匹配这组正则表达式的,如果不匹配的话,代码是肯定无法编译的。
// Github
{
prefix: "github.com/",
re: `^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[\p{L}0-9_.\-]+)*$`,
vcs: "git",
repo: "https://{root}",
check: noVCSSuffix,
},
//省略其它VCS...
以包路径github.com/liujianping/foo
为例,正则匹配后,得出的查询路径就是:
https://github.com/liujianping/foo
再结合go-get
参数,向远端VCS系统发起https://github.com/liujianping/foo?go-get=1
请求。
查询得出包的远端仓库地址
包的远端仓库地址,可以通过go get
请求的响应中的go-import
的meta标签中的content中获取的。meta去标签格式如下:
。
- pkg: 包名,例如gopkg.in/yaml.v2,也是import path(后续通过修改该参数实现自定义import path)
- git: 版本控制系统
- repo: 源代码地址
如:
$: curl https://github.com/liujianping/foo?go-get=1 | grep go-import
根据仓库地址Clone到本地
虽然版本控制系统VCS
本身就存在各类区别,但是一些基础操作大多类似。在go get
中具体clone
的过程会根据具体的VCS
采用对应的操作。
Proxy搭建
govanityurls原理
govanityurls的原理十分简单,它本身就好比一个“导航”服务器。当go get将请求发送给govanityurls时,govanityurls将请求中的repo的真实地址返回给go get,后续go get再从真实的repo地址获取package数据。
可以看出go get第一步是尝试获取自定义路径的包的真实地址,govanityurls将返回一个类似如下内容的http应答(针对go get tonybai.com/gowechat请求):
Nothing to see here; see the package on godoc.
搭建环境
机器
- 测试机器:localhost
步骤
- 搭建Nginx,仅做一层反向代理
- 路径:/root/go-get-proxy/nginx
- 配置文件:
server {
listen 80;
listen 443 ssl;
server_name test.com;
ssl_certificate ../cert/cert.crt; // 后续生成
ssl_certificate_key ../cert/cert.key; // 后续生成
error_log logs/error.log; #指定错误日志文件路径
access_log logs/access.log; #指定访问日志文件路径
location / {
proxy_pass http://127.0.0.1:5000; // 为govanityurls端口
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
- 搭建govanityurls
- 路径:/root/go-get-proxy/govanityurls
- 配置文件:vanity.yaml(后续添加新包需要到这添加后重启)
/bluele/gcache:
repo: https://github.com/bluele/gcache
- 待完善代码:现在只有github.com的,需要补充其他来源的包
if strings.Contains(e.Repo, "github.com") {
e.Display = fmt.Sprintf("%v %v/tree/master{/dir} %v/blob/master{/dir}/{file}#L{line}", e.Repo, e.Repo, e.Repo)
}
- https证书获取
- 制作证书
$ openssl genrsa -out rootCA.key 2048
$ openssl req -x509 -new -nodes -key rootCA.key -subj "/CN=*.test.com" -days 5000 -out rootCA.pem
$ openssl genrsa -out cert.key 2048
$ openssl req -new -key cert.key -subj "/CN=test.com" -out cert.csr
$ openssl x509 -req -in cert.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out cert.crt -days 5000
- 放置证书
- 将cert.crt和cert.key拷贝到nginx/cert目录下,重启nginx,让其加载新的cert.crt和cert.key。
- rootCA.pem根据系统(指Client方)不一样有不一样的放置路径
- MAC
- sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.pem
- $GOROOT/src/crypto/x509/root_linux.go
- MAC
package x509
// Possible certificate files; stop after finding one.
var certFiles = []string{
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
}
Proxy使用
- 在mac上修改一下/etc/hosts,添加一条路由
localhost test.com
-
添加CA证书(仅在goland自动下载的时候需要添加,手动go get下载可以使用-insecure)
- sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain rootCA.pem
使用方式与其他包的使用相同
若需要引入新包,需要更新govanityurls并重启
参考资料
- https://tonybai.com/2017/06/28/set-custom-go-get-import-path-for-go-package/
- https://segmentfault.com/a/1190000018414744
- https://my.oschina.net/u/2306127/blog/787078
- https://github.com/golang/go/issues/27332