Back

Vanity Redirection

Golang’s extensive list of existing packages for various commonly used functions is one of its biggest strengths. To use an existing project/package in code, all that needs to be done is to import in a .go file. Golang’s package management (ex: go modules, dep etc) manage how the packages are fetched and updated.

import "google.golang.org/grpc/metadata"

The same goes for installing a binary from an project.

$ go get -u google.golang.org/protobuf/cmd/protoc-gen-go

Go packages are described in the format <hostname>/[username]/[package-name] [version]. They are usually hosted on a compatible VCS server (ex: Github, Bitbucket, private VCS).

Go supports flexible remote import paths where the URL used by the clients to import a package can be independent of the actual location where it’s hosted.

This means that instead of serving packages via source dependent links (ex: https://github.com/KrishnaIyer/go-vanity-gen), a custom “vanity” URL can be used on a domain that you control (ex: https://go.krishnaiyer.dev/go-vanity-gen).

This post briefly explains the technicalities of vanity redirection and some existing tools that can be made use of to set up your own vanity redirects.

Why

  • Remove dependency on version control providers (ex: Github). The source code can be moved to a different repository without affecting clients.
  • Better catalogue of available projects.
  • It’s cool to use go.<your-domain> for all your go projects.

How does it work

When the go tooling queries a custom import path, it expects an html page with two important meta tags. These meta tags in turn tell the go tooling where the package is actually hosted. A second request is made to this path and the package is fetched.

Vanity

This is the html file that’s served at <your-domain>/<package-name> containing the important go-import and go-source meta tags. The body of this file is ignored by the tooling.

  • go-import: Describes the import path for the repository and the content contains 3 fields
    • import-prefix: The prefix or an exact match of the package.
    • vcs: One of bzr, fossil, git, hg, svn.
    • repo-root: The root of the repository with the appropriate scheme (ex: https).
<meta name="go-import" content="import-prefix vcs repo-root">

Ex:

<meta name="go-import" content="go.krishnaiyer.dev/go-vanity-gen git https://github.com/krishnaiyer/go-vanity-gen">
  • go-source: Used to specify links to the repository.
    • import-prefix: Same as with go-import.
    • repo-root: Same as with go-import.
    • directory: A reference to a particular directory (package) from the repository. It ends with an {/dir} substitution for a particular directory.
    • file: The reference to a particular file and decimal line number. Also ends with substitution strings; {/dir}/{file}#L{line}.
<meta name="go-source" content="import-prefix repo-root directory file">

Ex:

<meta name="go-source" content="go.krishnaiyer.dev/go-vanity-gen https://github.com/krishnaiyer/go-vanity-gen https://github.com/krishnaiyer/go-vanity-gen/tree/master{/dir} https://github.com/krishnaiyer/go-vanity-gen/blob/master{/dir}/{file}#L{line}">

Index

This is the index.html that’s served at the root of the custom domain; ex: go.example.com. This file is not necessary to use vanity redirection but is a common practice. This page is meant for (human) users and not for go tooling. The content of this index file can be anything, but it’s typically used to catalogue go packages (with links to documentation and the source package).

The following is a simple example of go packages listed on the index page.

`<!DOCTYPE html>
<html>
<h1>Welcome to go.my-domain.com </h1>
<h2> Here's a list of my go packages</h2>
<ul>
<li><a href="https://pkg.go.dev/repo/pkg1">repo/pkg1</a></li>
<li><a href="https://pkg.go.dev/repo/pkg2">repo/pkg2</a></li>
<li><a href="https://pkg.go.dev/repo/pkg3">repo/pkg3</a></li>
</ul>
</html>
`))

It’s advisable to keep the styling to a minimum to keep the file size low.

Tooling

Handling vanity redirects is essentially having a web server on the index and vanity paths that serves the requested assets. Depending on the hosting environment, there are a few solutions already available that can be used.

Hosting Environment Repository When to use it Comments
Google Cloud Platform GoogleCloudPlatform/govanityurls If you’re already familiar with GCP and use Google App Engine for your existing workloads. Maintained by Google
Google Cloud Functions KrishnaIyer/go-vanity-cloud-function If you use GCP but don’t want to deploy a server I don’t really maintain the repository as I don’t use it much.
Self Hosting (docker) KrishnaIyer/go-vanity-docker If you’re a more experienced cloud user with your own server. This is the most versatile option.
Simple static website KrishnaIyer/go-vanity-gen If you already host static content and your hosting infrastructure is easily extendable. This is what I use for go.krishnaiyer.dev and is really the simplest option.

Showcase

Head over to go.krishnaiyer.dev.

References

  1. govanityurls repository
  2. go-vanity-gen repository
Last updated on Jan 30, 2022 12:24 +0100