/
main.go
150 lines (123 loc) · 4.12 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// The gum binary starts up a gum server. See the usage text for configuration
// options.
package main
import (
"errors"
"flag"
"fmt"
"log"
"net/http"
"net/url"
"os"
"strings"
"willnorris.com/go/gum"
)
// goxc values
var (
// VERSION is the version string for gum.
VERSION = "HEAD"
// BUILD_DATE is the timestamp of when gum was built.
BUILD_DATE string
)
// Flags
var (
addr = flag.String("addr", "localhost:4594", "TCP address to listen on")
version = flag.Bool("version", false, "print version information")
staticDir = flag.String("static_dir", "", "directory of static site to setup redirects for")
redirects redirectSlice
)
func init() {
flag.Var(&redirects, "redirect", "redirect handler definition of the form 'prefix=destination'")
}
type redirect struct {
Prefix, Destination string
}
type redirectSlice []redirect
func (r *redirectSlice) String() string {
return fmt.Sprintf("%v", *r)
}
func (r *redirectSlice) Set(value string) error {
parts := strings.SplitN(value, "=", 2)
if len(parts) != 2 {
return errors.New("redirect flag value should be of the form 'prefix=dest'")
}
if _, err := url.Parse(parts[1]); err != nil {
return fmt.Errorf("Destination %q is not a valid URL: %v", parts[1], err)
}
*r = append(*r, redirect{Prefix: parts[0], Destination: parts[1]})
return nil
}
func usage() {
fmt.Print(`gum is a personal short URL resolver.
Usage:
gum [-redirect=<redirect>] [-static_dir=<static_dir>]
Gum supports two styles of handlers, which are configured with command line flags:
Redirect Handlers are configured by providing a mapping of the form
"prefix=dest" using the -redirect flag, which will redirect all URLs matching a
specified prefix to a given destination URL. For example, you could call gum
with the following flags:
gum -redirect x=http://example.com/
This would redirect all requests whose path begins with "/x" to the
corresponding URL on "http://example.com/". For example, the request
"/x/a/b?c=d" would be redirected to "http://example.com/a/b?c=d". Destination
URLs can be absolute or relative.
A Static Site Handler is configured by passing the root directory of a static
website using the -static_dir flag. This handler will parse all HTML files
under that directory looking for files with both a rel="canonical" and
rel="shortlink" link. If found, it will configure redirects from the shortlink
URL path to the canonical URL. In addition, the rel="shortlink" link can
provide a space-separate list of additional shortlinks in the 'data-alt-href'
attribute, which will also be redirected. This is mostly useful for legacy
shortlinks that should be redirected, but that you don't standard parsers to
see. For example, given an HTML file with the contents:
<html>
<link rel="canonical" href="http://example.com/post/12345678">
<link rel="shortlink" href="http://x.com/t123"
data-alt-href="http://x.com/b/123 http://x.com/b/456">
</html>
Requests whose path matched any of "/t123", "/b/123", or "/b/456" would be
redirected to "http://example.com/post/12345678". The static site handler
currently ignores the hostname of the shortlink URL when setting up redirects.
Flags:
`)
flag.PrintDefaults()
}
func main() {
flag.Usage = usage
flag.Parse()
if *version {
fmt.Printf("%v\nBuild: %v\n", VERSION, BUILD_DATE)
return
}
if port := os.Getenv("PORT"); *addr == "" && port != "" {
a := "localhost:" + port
addr = &a
}
g := gum.NewServer()
for _, r := range redirects {
h, err := gum.NewRedirectHandler(r.Prefix, r.Destination)
if err != nil {
log.Fatal("error adding redirect handler: ", err)
}
if err := g.AddHandler(h); err != nil {
log.Fatal("error adding redirect handler: ", err)
}
}
if *staticDir != "" {
h, err := gum.NewStaticHandler(*staticDir)
if err != nil {
log.Fatal("error adding static handler: ", err)
}
if err := g.AddHandler(h); err != nil {
log.Fatal("error adding static handler: ", err)
}
}
server := &http.Server{
Addr: *addr,
Handler: g,
}
fmt.Printf("gum (version %v) listening on %s\n", VERSION, server.Addr)
if err := server.ListenAndServe(); err != nil {
log.Fatal("ListenAndServe: ", err)
}
}