четверг, 4 марта 2021 г.

Модули в Golang: прокси модуля, общение с прокси

Команда go может загружать исходный код модуля и метаданные с прокси-сервера модуля. Переменная среды GOPROXY может использоваться для настройки прокси-серверов, к которым команда go может подключаться и может ли она напрямую взаимодействовать с системами контроля версий. Данные загруженного модуля сохраняются в кеш-памяти модуля. Команда go будет связываться с прокси только тогда, когда ему нужна информация, которой еще нет в кеше.

Предыдущий пост о протоколе GOPROXY описывает запросы, которые могут быть отправлены на сервер GOPROXY. Однако также полезно понимать, когда команда go делает эти запросы. Например, go build выполняется следующим образом:

  • Вычислить список сборки, прочитав файлы go.mod и выполнив выбор минимальной версии (MVS).
  • Прочитать пакеты, указанные в командной строке, и пакеты, которые они импортируют.
  • Если пакет не предоставляется ни одним модулем в списке сборки, найти модуль, который его предоставляет. Добавить требование модуля для последней версии в go.mod и начать заново.
  • Собрать пакеты после того, как все будет загружено.

Когда команда go вычисляет список сборки, она загружает файл go.mod для каждого модуля в графе модулей. Если файла go.mod нет в кеше, команда go загрузит его с прокси с помощью запроса $module/@v/$version.mod (где $module - это путь к модулю, а $version - версия). Эти запросы можно проверить с помощью такого инструмента, как curl. Например, приведенная ниже команда загружает файл go.mod для golang.org/x/mod в версии v0.2.0:

$ curl https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.mod
module golang.org/x/mod

go 1.12

require (
  golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
  golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
  golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898
)

Чтобы загрузить пакет, команде go нужен исходный код модуля, который его предоставляет. Исходный код модуля распространяется в виде файлов .zip, которые извлекаются в кеш модуля. Если в кеше нет .zip файла модуля, команда go загрузит его с помощью запроса $module/@v/$version.zip.

$ curl -O https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.zip
$ unzip -l v0.2.0.zip | head
Archive:  v0.2.0.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
     1479  00-00-1980 00:00   golang.org/x/mod@v0.2.0/LICENSE
     1303  00-00-1980 00:00   golang.org/x/mod@v0.2.0/PATENTS
      559  00-00-1980 00:00   golang.org/x/mod@v0.2.0/README
       21  00-00-1980 00:00   golang.org/x/mod@v0.2.0/codereview.cfg
      214  00-00-1980 00:00   golang.org/x/mod@v0.2.0/go.mod
     1476  00-00-1980 00:00   golang.org/x/mod@v0.2.0/go.sum
     5224  00-00-1980 00:00   golang.org/x/mod@v0.2.0/gosumcheck/main.go

Обратите внимание, что запросы .mod и .zip разделены, хотя файлы go.mod обычно содержатся в файлах .zip. Команде go может потребоваться загрузить файлы go.mod для многих различных модулей, а файлы .mod намного меньше, чем файлы .zip. Кроме того, если у проекта Go нет файла go.mod, прокси будет обслуживать синтетический файл go.mod, который содержит только директиву module. Синтетические файлы go.mod генерируются командой go при загрузке из системы контроля версий.

Если команде go необходимо загрузить пакет, не предоставленный каким-либо модулем в списке сборки, она попытается найти новый модуль, который его предоставляет. Таким образом, команда go запрашивает информацию о последней версии каждого пути к модулю, который, возможно, может содержать пакет. Например, для пакета golang.org/x/net/html команда go попытается найти последние версии модулей golang.org/x/net/html, golang.org/x/net, golang.org/x/ и golang.org. Фактически существует только golang.org/x/net, который предоставляет этот пакет, поэтому команда go использует последнюю версию этого модуля. Если пакет предоставляет более одного модуля, команда go будет использовать модуль с самым длинным путем.

Когда команда go запрашивает последнюю версию модуля, она сначала отправляет запрос на $module/@v/list. Если список пуст или ни одна из возвращенных версий не может быть использована, он отправляет запрос на $module/@latest. После выбора версии команда go отправляет запрос $module/@v/$version.info для метаданных. Затем она может отправить запросы $module/@v/$version.mod и $module/@v/$version.zip для загрузки файла go.mod и исходного кода.

$ curl https://proxy.golang.org/golang.org/x/mod/@v/list
v0.1.0
v0.2.0

$ curl https://proxy.golang.org/golang.org/x/mod/@v/v0.2.0.info
{"Version":"v0.2.0","Time":"2020-01-02T17:33:45Z"}

После загрузки файла .mod или .zip команда go вычисляет криптографический хеш и проверяет, соответствует ли он хешу в файле go.sum основного модуля. Если хеш отсутствует в go.sum, по умолчанию команда go извлекает его из базы данных контрольных сумм. Если вычисленный хеш не совпадает, команда go сообщает об ошибке безопасности и не устанавливает файл в кеш модуля. Переменные среды GOPRIVATE и GONOSUMDB могут использоваться для отключения запросов к базе данных контрольных сумм для определенных модулей. Переменная среды GOSUMDB также может быть отключена, чтобы полностью отключить запросы к базе данных контрольных сумм. Обратите внимание, что списки версий и метаданные версий, возвращаемые для запросов .info, не аутентифицируются и могут изменяться со временем.


Читайте также:


Комментариев нет:

Отправить комментарий