百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Golang模块代理goproxy.io源码研读

toyiye 2024-06-24 19:21 10 浏览 0 评论

goproxy.io是一款很好用的Golang Module Proxy,解决了国内用户无法直接下载Golang模块依赖的问题。

本文准备研读一下其开源代码github.com/goproxyio/goproxy,了解下其实现原理。

goproxy工程的主要目录结构如下:

goproxy
 ├ build
 │ └ generate.sh
 ├ pkg
 │ └ proxy
 │ └ proxy.go
 └ main.go

main.go头部有一行代码:

//go:generate ./build/generate.sh

下面会解释其作用。

1 建立一个Golang Proxy服务需要实现哪些功能

$ go help goproxy
...
A Go module proxy is any web server that can respond to GET requests for
URLs of a specified form. The requests have no query parameters, so even
a site serving from a fixed file system (including a file:/// URL)
can be a module proxy.
The GET requests sent to a Go module proxy are:
GET $GOPROXY/<module>/@v/list returns a list of all known versions of the
given module, one per line.
GET $GOPROXY/<module>/@v/.info returns JSON-formatted metadata
about that version of the given module.
GET $GOPROXY/<module>/@v/.mod returns the go.mod file
for that version of the given module.
GET $GOPROXY/<module>/@v/.zip returns the zip archive
for that version of the given module.
...

从如上说明可知,使用诸如go get等go命令会从vcs下载所需模块,设置GOPROXY环境变量即可指定Go Module Proxy服务,其为不带参数URL的GET请求提供服务,为模块下载作了一层包装。

其主要提供如下几个接口:

a)GET $GOPROXY/<module>/@v/list

该接口返回给定模块的已知版本号列表,每行一个。

b)GET $GOPROXY/<module>/@v/<version>.info

该接口返回给定模块在给定版本的JSON格式的元数据信息。

c)GET $GOPROXY/<module>/@v/<version>.mod

该接口返回给定模块在给定版本的go.mod的内容。

d)GET $GOPROXY/<module>/@v/<version>.zip

该接口返回给定模块在给定版本的.zip压缩包。

为避免大小写敏感型文件系统服务问题,<module>及<version>会对大写字母加密,即将大写字母转换为!加小写字母的方式。

如github.com/Azure编码为github.com/!azure。

JSON格式的元数据信息对应的Go内置结构体为:

type Info struct {
 Version string // version string
 Time time.Time // commit time
}

给定模块在给定版本的.zip压缩包内的文件树结构与模块源码树结构一致,且模块及版本未使用大写字母加密。

不论go命令直接访问vcs还是从Proxy下载,其均会将模块的info、mod及zip文件组合到一起,置于$GOPATH/pkg/mod/cache/download本地缓存。

因缓存路径与请求路径对应,所以对$GOPATH/pkg/mod/cache/download文件夹以https://example.com/proxy提供服务即可访问到缓存的模块。

2 goproxy/build/generate.sh

当执行go generate命令时,Go会扫描当前包相关的源码文件,找出所有包含//go:generate的特殊注释,并执行注释指定的脚本。

因goproxy.io工程需要使用内置的模块获取包,而由上一篇文章“Golang 模块获取包modfetch研读”可知,modfetch、modload等模块获取包是位于cmd/go/internal路径下的,所以无法直接引用,main.go所指向的goproxy/build/generate.sh这个脚本即是用来将modfetch、modload等内部包及其依赖包拷贝至当前工作目录下,以便直接引用。

3 goproxy/main.go

main.go负责接收http请求,此外检查git有没有安装(因Go从诸如github.com等vcs下载新的依赖包需要依赖git工具),构造Golang Module的工作目录cacheDir等。

4 goproxy/pkg/proxy/proxy.go

proxy.go是该工程的核心代码,其会根据main.go传入的cacheDir设置工作目录。然后分别为后缀为.info,.mod,.zip,/@v/list,/@latest的几种类型的请求提供服务。

对如上类型的请求,会调用modfetch等包的内置函数来辅助实现,关于modfetch中几个核心函数的功能及用法,请参考上一篇博文:Golang 模块获取包modfetch研读。

a)若请求后缀为/@v/list,/@latest

因请求的是所有可用版本号或最新版本,所以必须请求vcs系统,所以可以使用modfetch.Lookup函数。

若是/@v/list,返回repo.Versions(""),若是/@latest,返回repo.Latest()。

b)若请求后缀为.info

使用modfetch.Stat函数,传入模块路径及版本号即可获取到修订信息,然后返回即可。

c)若请求后缀为.mod

使用modfetch.GoMod函数(源码中使用的是GoModFile,其实因需返回go.mod内容,使用GoMod即可),传入模块路径及版本号返回go.mod信息即可。

d)若请求后缀为.zip

使用modfetch.DownloadZip函数,其会返回文件路径,然后http.ServeFile即可。

如上即为goproxy.io对Go Module Proxy的实现,总体思路较清晰,代码较简洁。使用goproxy.io或将该开源代码搭建至一台国外ECS上,基本可以解决国内用户对Go Module无法直接下载的问题。

不过对于深度用户,有诸如权限管理、私有依赖管理等更高的需求。微软的工程师针对这些行业通用需求,实现了一个叫athens的工具,有机会可以学习一下。

原文链接:https://leileiluoluo.com/posts/goproxyio.html

本文作者:磊磊落落的博客,原创授权发布

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码