Go Modules の hosting と import の関係

とあるプロジェクトでセルフホストしている GitLab で Go Modules を利用しようしてハマったのでメモ。

foo モジュールを private.host/account1/foo に公開したとします。

go.mod

module private.host/account1/foo

go 1.12

利用側では、

import "private.host/account1/foo"

のように指定します。go get / run / build する際、go コマンドは https://private.host/account1/foo?go-get=1 のようにリクエストを投げるようです。GitLab などの VCS hosting サイトはこのリクエストに対して

<meta name="go-import" content="private.host/account1/foo git https://private.host/account1/foo.git">

のように、VCS の種類とリポジトリの URL を含むメタタグを HTML として返すことを期待されます。

go コマンドはこの HTML をパースして VCS の種類、リポジトリのロケーションを特定し、VCS の CLI コマンドにモジュールの取得を委譲します。

godoc.org

gitlab.com では go-get=1 のクエリパラメータ付きリクエストに以下のような HTML を返却しています。

<html>
<head>
  <meta name="go-import" content="gitlab.com/kondoumh/go-samplemodlue git https://gitlab.com/kondoumh/go-samplemodule.git" />
  :
</head>
<body>
  go get https://gitlab.com/kondoumh/go-samplemodule
</body>
</html>

GitHub の場合はこんな感じ

<html lang="en">
  <head>
    <meta charset="utf-8">
      :
    <meta name="go-import" content="github.com/kondoumh/gogreeting git https://github.com/kondoumh/gogreeting.git">
      :
</head>
<body>
  :

Go Modules はソースコードであり、Git 以外の VCS (Mercurial, Bazzar etc.) でもホストされる可能性があります。Java や Node.js などのようにビルド・パッケージングしてホストするわけではないので、このように VCS によらない方法を取っているのでしょう。

件の GitLab は HTTPS ポートが規定の 443 以外で公開されていました。しかし go コマンドは既定のポートにリクエストを投げるので Connection refused でエラーになっていました。443 ポートを受け付けるように設定したら無事に使えるようになりました。