
A lightweight approach to Go vanity import paths
September 23, 2018
Golang uses URLs for the dependencies packages resolution. To unbundle the code repository hosting the package and the import path, Golang supports the idea of Vanity Import Paths. The way this has been implemented is that, as long as the import path points to a page where Go can find the real package URL, it will follow through.
So, we will need to create a web server that can serve pages in a way that the Go toolchains can understand. To do so, I use the following code:
package main
import (
"html/template"
"log"
"net/http"
"os"
"strings"
)
type conversion struct {
Vanity string
Real string
Domain string
}
var conversions = []conversion{
conversion{Domain: "go.fale.io", Vanity: "test", Real: "https://github.com/fale/test"},
}
var tpl = template.Must(template.New("main").Parse(`<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="go-import" content="{{ .Domain }}/{{ .Vanity }} git {{ .Real }}">
</head>
</html>
`))
func main() {
log.Println("Starting")
wwwPort := "80"
if os.Getenv("DEBUG") == "true" {
wwwPort = "10080"
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s %s\n", r.Method, r.URL, r.Proto)
for _, c := range conversions {
if r.URL.Path[1:] == c.Vanity || strings.HasPrefix(r.URL.Path[1:], c.Vanity+"/") {
w.WriteHeader(200)
tpl.Execute(w, c)
return
}
}
http.Error(w, "Not found", 404)
return
})
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) })
http.HandleFunc("/readiness", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) })
log.Println("Ready to serve")
http.ListenAndServe(":"+wwwPort, nil)
}
For every repository we have, we need to add one more item in the conversions
array.