Skip to content

Commit

Permalink
all: implement /s and /x redirector
Browse files Browse the repository at this point in the history
Fixes #1
Fixes #2
  • Loading branch information
changkun committed Sep 16, 2020
1 parent 97afd08 commit 70134c4
Show file tree
Hide file tree
Showing 23 changed files with 1,288 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.app
*.rdb

# Dependency directories (remove the comment below to include it)
# vendor/
vendor/
29 changes: 29 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright 2020 The golang.design Initiative authors.
# All rights reserved. Use of this source code is governed
# by a MIT license that can be found in the LICENSE file.

VERSION = $(shell git describe --always --tags)
BUILDTIME = $(shell date +%FT%T%z)
GOPATH=$(shell go env GOPATH)
IMAGE = golang-design/redir
BINARY = redir.app
TARGET = -o $(BINARY)
BUILD_SETTINGS = -ldflags="-X main.Version=$(VERSION) -X main.BuildTime=$(BUILDTIME)"
BUILD_FLAGS = $(TARGET) $(BUILD_SETTINGS)

all: native
native:
GO111MODULE=on go build $(BUILD_FLAGS)
run:
./$(BINARY) -s
build:
docker build -t $(IMAGE):$(VERSION) -t $(IMAGE):latest -f docker/Dockerfile .
compose:
docker-compose -f docker/docker-compose.yml up -d
compose-down:
docker-compose -f docker/docker-compose.yml down
clean:
rm redir.app
docker rmi -f $(shell docker images -f "dangling=true" -q) 2> /dev/null; true
docker rmi -f $(IMAGE):latest $(IMAGE):$(VERSION) 2> /dev/null; true
.PHONY: native run build compose clean
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,82 @@
# redir

a request redirector that is dedicated for golang.design

## Design Purpose

The current `redir` implementation talks to a redis data store for PV/UV counting,
as well as short alias storage. In the booting phase, it will read `REDIR_CONF`
from environment variable to identify configuration file (default: `./config.yml`).

`redir` is designed for the following purpose: serve two major
redirectors `/s` and `/x` (at the moment).

### 1. Redirect `golang.design/x/pkg` to the `pkg`'s actual VCS.

This is based on the `go get` vanity import path convention. With this
feature, all packages issued by [golang.design](https://golang.design)
requires to use `golang.design/x/` import path.
That is saying, any `pkg` will be redirected to `github.com/golang-design/pkg`
if exist. The website itself will redirect the request to [pkg.go.dev](https://pkg.go.dev).

There is a reserved ping router for debugging purpose `/x/.ping` which will
give you a pong.

### 2. Redirect `golang.design/s/alias`

The served alias can be allocated by [golang.design](https://golang.design/) members.
The current approach is to use `redir` command on the [golang.design](https://golang.design/)
server. Here is the overview of its usage:

```
usage: redir [-s] [-op <operator> -a <alias> -l <link>]
options:
-a string
alias for a new link
-l string
actual link for the alias, optional for delete/fetch
-op string
operators, create/update/delete/fetch (default "create")
-s run redir service
example:
redir -s run the redir service
redir -a alias -l link allocate new short link if possible
redir -op fetch -a alias fetch alias information
```

For the command line usage, one only need to use `-a`, `-l` and `-op` if needed.
The command will talk to the redis data store and issue a new allocated alias.
For instance, the following command:

```
redir -a changkun -l https://changkun.de
```

creates a new alias under [golang.design/s/changkun](https://golang.design/s/changkun).

Moreover, it is possible to visit [`/s`](https://golang.design/s) directly listing all exist aliases under [golang.design](https://golang.design/).

## Build

`Makefile` defines different ways to build the service:

```bash
make # build native binary
make run # assume your local redis is running
make build # build docker images
make compose # run via docker-compose
make compose-down # remove compose stuff
make clean # cleanup
```

## Troubleshooting

### private golang.design projects `go get` failure

1. make sure you are a member of golang.design
2. add ssh public key to your account
3. `git config --global url."[email protected]:".insteadOf "https://github.com/"`

## License

MIT &copy; The golang.design Initiative Authors
59 changes: 59 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2020 The golang.design Initiative authors.
// All rights reserved. Use of this source code is governed
// by a MIT license that can be found in the LICENSE file.

package main

import (
"io/ioutil"
"log"
"os"
"runtime"

"gopkg.in/yaml.v2"
)

// build info, assign by compile time or runtime.
var (
Version string
BuildTime string
GoVersion = runtime.Version()
)

type config struct {
Host string `json:"host"`
Addr string `json:"addr"`
Store string `json:"store"`
Log string `json:"log"`
S struct {
Prefix string `json:"prefix"`
} `json:"s"`
X struct {
Prefix string `json:"prefix"`
VCS string `json:"vcs"`
ImportPath string `json:"import_path"`
RepoPath string `json:"repo_path"`
} `json:"x"`
}

func (c *config) parse() {
f := os.Getenv("REDIR_CONF")
d, err := ioutil.ReadFile(f)
if err != nil {
// Just try again with default setting.
d, err = ioutil.ReadFile("./config.yml")
if err != nil {
log.Fatalf("cannot read configuration, err: %v\n", err)
}
}
err = yaml.Unmarshal(d, c)
if err != nil {
log.Fatalf("cannot parse configuration, err: %v\n", err)
}
}

var conf config

func init() {
conf.parse()
}
16 changes: 16 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2020 The golang.design Initiative authors.
# All rights reserved. Use of this source code is governed
# by a MIT license that can be found in the LICENSE file.

---
host: https://golang.design
addr: :8080
store: redis://localhost:6379/9
log: "golang.design/redir: "
s:
prefix: /s/
x:
prefix: /x/
vcs: git
import_path: golang.design/x/*
repo_path: https://github.com/golang-design/*
27 changes: 27 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2020 The golang.design Initiative authors.
// All rights reserved. Use of this source code is governed
// by a MIT license that can be found in the LICENSE file.

package main

import (
"reflect"
"testing"
)

func TestParseConfig(t *testing.T) {
conf.parse()

// Test if all fields are filled.
v := reflect.ValueOf(conf)
for i := 0; i < v.NumField(); i++ {
if v.Field(i).Kind() == reflect.Struct {
continue
}
vv, ok := v.Field(i).Interface().(string)
if ok && len(vv) > 0 {
continue
}
t.Fatalf("read empty from config, field: %v", v.Type().Field(i).Name)
}
}
16 changes: 16 additions & 0 deletions data/container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Copyright 2020 The golang.design Initiative authors.
# All rights reserved. Use of this source code is governed
# by a MIT license that can be found in the LICENSE file.

---
host: https://golang.design/
addr: :8080
store: redis://redis:6379/9
log: "golang.design/redir: "
s:
prefix: /s/
x:
prefix: /x/
vcs: git
import_path: golang.design/x/*
repo_path: https://github.com/golang-design/*
Loading

0 comments on commit 70134c4

Please sign in to comment.